~bzr-pqm/bzr/bzr.dev

70 by mbp at sourcefrog
Prepare for smart recursive add.
1
# Copyright (C) 2005 Canonical Ltd
2
1 by mbp at sourcefrog
import from baz patch-364
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
17
1534.4.3 by Robert Collins
Implement BranchTestProviderAdapter, so tests now run across all branch formats.
18
from copy import deepcopy
1534.4.2 by Robert Collins
Introduce BranchFormats - factoring out intialisation of Branches.
19
from cStringIO import StringIO
20
import errno
21
import os
1497 by Robert Collins
Move Branch.read_working_inventory to WorkingTree.
22
import shutil
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
23
import sys
1534.4.3 by Robert Collins
Implement BranchTestProviderAdapter, so tests now run across all branch formats.
24
from unittest import TestSuite
1372 by Martin Pool
- avoid converting inventories to/from StringIO
25
from warnings import warn
1185.62.20 by John Arbash Meinel
Giving nicer warning when there is a leftover xml.pyc file.
26
try:
27
    import xml.sax.saxutils
28
except ImportError:
29
    raise ImportError("We were unable to import 'xml.sax.saxutils',"
30
                      " most likely you have an xml.pyc or xml.pyo file"
31
                      " lying around in your bzrlib directory."
32
                      " Please remove it.")
1393.2.1 by John Arbash Meinel
Merged in split-storage-2 branch. Need to cleanup a little bit more still.
33
from cStringIO import StringIO
1372 by Martin Pool
- avoid converting inventories to/from StringIO
34
1 by mbp at sourcefrog
import from baz patch-364
35
36
import bzrlib
1534.4.2 by Robert Collins
Introduce BranchFormats - factoring out intialisation of Branches.
37
from bzrlib.config import TreeConfig
1534.4.28 by Robert Collins
first cut at merge from integration.
38
from bzrlib.decorators import needs_read_lock, needs_write_lock
1534.4.2 by Robert Collins
Introduce BranchFormats - factoring out intialisation of Branches.
39
from bzrlib.delta import compare_trees
40
import bzrlib.errors as errors
41
from bzrlib.errors import (BzrError, InvalidRevisionNumber, InvalidRevisionId,
42
                           NoSuchRevision, HistoryMissing, NotBranchError,
1551.1.1 by Martin Pool
[merge] branch-formats branch, and reconcile changes
43
                           DivergedBranches, LockError,
1534.4.3 by Robert Collins
Implement BranchTestProviderAdapter, so tests now run across all branch formats.
44
                           UninitializableFormat,
45
                           UnlistableStore,
1534.4.2 by Robert Collins
Introduce BranchFormats - factoring out intialisation of Branches.
46
                           UnlistableBranch, NoSuchFile, NotVersionedError,
47
                           NoWorkingTree)
1185.65.15 by Robert Collins
Merge from integration.
48
import bzrlib.inventory as inventory
1534.4.2 by Robert Collins
Introduce BranchFormats - factoring out intialisation of Branches.
49
from bzrlib.inventory import Inventory
1185.65.14 by Robert Collins
Merge from aaron. Whee, we are synced. Yay. Begone the foul demons of merge conflicts.
50
from bzrlib.lockable_files import LockableFiles
1508.1.5 by Robert Collins
Move add from Branch to WorkingTree.
51
from bzrlib.osutils import (isdir, quotefn,
1185.31.32 by John Arbash Meinel
Updated the bzr sourcecode to use bzrlib.osutils.pathjoin rather than os.path.join to enforce internal use of / instead of \
52
                            rename, splitpath, sha_file,
1534.4.1 by Robert Collins
Allow parameterisation of the branch initialisation for bzrlib.
53
                            file_kind, abspath, normpath, pathjoin,
54
                            safe_unicode,
55
                            )
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
56
from bzrlib.textui import show_status
1534.4.2 by Robert Collins
Introduce BranchFormats - factoring out intialisation of Branches.
57
from bzrlib.trace import mutter, note
58
from bzrlib.tree import EmptyTree, RevisionTree
1534.4.28 by Robert Collins
first cut at merge from integration.
59
from bzrlib.repository import Repository
1185.65.14 by Robert Collins
Merge from aaron. Whee, we are synced. Yay. Begone the foul demons of merge conflicts.
60
from bzrlib.revision import (Revision, is_ancestor, get_intervening_revisions)
1393.2.1 by John Arbash Meinel
Merged in split-storage-2 branch. Need to cleanup a little bit more still.
61
from bzrlib.store import copy_all
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
62
from bzrlib.symbol_versioning import *
1417.1.6 by Robert Collins
introduce transactions for grouping actions done to and with branches
63
import bzrlib.transactions as transactions
1393.2.4 by John Arbash Meinel
All tests pass.
64
from bzrlib.transport import Transport, get_transport
1185.65.15 by Robert Collins
Merge from integration.
65
from bzrlib.tree import EmptyTree, RevisionTree
1185.65.11 by Robert Collins
Disable inheritance for getting at LockableFiles, rather use composition.
66
import bzrlib.ui
1189 by Martin Pool
- BROKEN: partial support for commit into weave
67
import bzrlib.xml5
1104 by Martin Pool
- Add a simple UIFactory
68
1094 by Martin Pool
- merge aaron's merge improvements 999..1008
69
1186 by Martin Pool
- start implementing v5 format; Branch refuses to operate on old branches
70
BZR_BRANCH_FORMAT_4 = "Bazaar-NG branch, format 0.0.4\n"
71
BZR_BRANCH_FORMAT_5 = "Bazaar-NG branch, format 5\n"
1429 by Robert Collins
merge in niemeyers prefixed-store patch
72
BZR_BRANCH_FORMAT_6 = "Bazaar-NG branch, format 6\n"
1185.70.3 by Martin Pool
Various updates to make storage branch mergeable:
73
74
75
# TODO: Maybe include checks for common corruption of newlines, etc?
1 by mbp at sourcefrog
import from baz patch-364
76
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
77
# TODO: Some operations like log might retrieve the same revisions
78
# repeatedly to calculate deltas.  We could perhaps have a weakref
1223 by Martin Pool
- store inventories in weave
79
# cache in memory to make this faster.  In general anything can be
1185.65.29 by Robert Collins
Implement final review suggestions.
80
# cached in memory between lock and unlock operations. .. nb thats
81
# what the transaction identity map provides
416 by Martin Pool
- bzr log and bzr root now accept an http URL
82
1442.1.63 by Robert Collins
Remove self.lock_*...finally: self.unlock() dead chickens from branch.py.
83
1 by mbp at sourcefrog
import from baz patch-364
84
######################################################################
85
# branch objects
86
558 by Martin Pool
- All top-level classes inherit from object
87
class Branch(object):
1 by mbp at sourcefrog
import from baz patch-364
88
    """Branch holding a history of revisions.
89
343 by Martin Pool
doc
90
    base
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
91
        Base directory/url of the branch.
92
    """
1534.4.1 by Robert Collins
Allow parameterisation of the branch initialisation for bzrlib.
93
    # this is really an instance variable - FIXME move it there
94
    # - RBC 20060112
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
95
    base = None
96
1534.4.1 by Robert Collins
Allow parameterisation of the branch initialisation for bzrlib.
97
    _default_initializer = None
98
    """The default initializer for making new branches."""
99
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
100
    def __init__(self, *ignored, **ignored_too):
101
        raise NotImplementedError('The Branch class is abstract')
102
103
    @staticmethod
1393.1.2 by Martin Pool
- better representation in Branch factories of opening old formats
104
    def open_downlevel(base):
1534.4.7 by Robert Collins
Move downlevel check up to the Branch.open logic, removing it from the Branch constructor and deprecating relax_version_check to the same.
105
        """Open a branch which may be of an old format."""
106
        return Branch.open(base, _unsupported=True)
1393.1.2 by Martin Pool
- better representation in Branch factories of opening old formats
107
        
108
    @staticmethod
1534.4.7 by Robert Collins
Move downlevel check up to the Branch.open logic, removing it from the Branch constructor and deprecating relax_version_check to the same.
109
    def open(base, _unsupported=False):
110
        """Open an existing branch, rooted at 'base' (url)
111
        
112
        _unsupported is a private parameter to the Branch class.
113
        """
1393.2.4 by John Arbash Meinel
All tests pass.
114
        t = get_transport(base)
1393.1.63 by Martin Pool
- add some trace statements
115
        mutter("trying to open %r with transport %r", base, t)
1534.4.5 by Robert Collins
Turn branch format.open into a factory.
116
        format = BzrBranchFormat.find_format(t)
1534.4.7 by Robert Collins
Move downlevel check up to the Branch.open logic, removing it from the Branch constructor and deprecating relax_version_check to the same.
117
        if not _unsupported and not format.is_supported():
118
            # see open_downlevel to open legacy branches.
119
            raise errors.UnsupportedFormatError(
120
                    'sorry, branch format %s not supported' % format,
121
                    ['use a different bzr version',
122
                     'or remove the .bzr directory'
123
                     ' and "bzr init" again'])
1534.4.5 by Robert Collins
Turn branch format.open into a factory.
124
        return format.open(t)
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
125
126
    @staticmethod
1185.2.8 by Lalo Martins
creating the new branch constructors
127
    def open_containing(url):
1185.1.41 by Robert Collins
massive patch from Alexander Belchenko - many PEP8 fixes, removes unused function uuid
128
        """Open an existing branch which contains url.
129
        
130
        This probes for a branch at url, and searches upwards from there.
1185.17.2 by Martin Pool
[pick] avoid problems in fetching when .bzr is not listable
131
132
        Basically we keep looking up until we find the control directory or
133
        run into the root.  If there isn't one, raises NotBranchError.
1534.4.22 by Robert Collins
update TODOs and move abstract methods that were misplaced on BzrBranchFormat5 to Branch.
134
        If there is one and it is either an unrecognised format or an unsupported 
135
        format, UnknownFormatError or UnsupportedFormatError are raised.
1442.1.64 by Robert Collins
Branch.open_containing now returns a tuple (Branch, relative-path).
136
        If there is one, it is returned, along with the unused portion of url.
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
137
        """
1393.2.4 by John Arbash Meinel
All tests pass.
138
        t = get_transport(url)
1534.4.22 by Robert Collins
update TODOs and move abstract methods that were misplaced on BzrBranchFormat5 to Branch.
139
        # this gets the normalised url back. I.e. '.' -> the full path.
1534.4.11 by Robert Collins
Convert test_open_containing from being a Remote test to being the more accurate Chrooted test.
140
        url = t.base
1185.17.2 by Martin Pool
[pick] avoid problems in fetching when .bzr is not listable
141
        while True:
142
            try:
1534.4.5 by Robert Collins
Turn branch format.open into a factory.
143
                format = BzrBranchFormat.find_format(t)
144
                return format.open(t), t.relpath(url)
1185.31.38 by John Arbash Meinel
Changing os.path.normpath to osutils.normpath
145
            except NotBranchError, e:
146
                mutter('not a branch in: %r %s', t.base, e)
1185.17.2 by Martin Pool
[pick] avoid problems in fetching when .bzr is not listable
147
            new_t = t.clone('..')
148
            if new_t.base == t.base:
149
                # reached the root, whatever that may be
1185.16.61 by mbp at sourcefrog
- start introducing hct error classes
150
                raise NotBranchError(path=url)
1185.17.2 by Martin Pool
[pick] avoid problems in fetching when .bzr is not listable
151
            t = new_t
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
152
153
    @staticmethod
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
154
    def create(base):
155
        """Create a new Branch at the url 'bzr'.
1534.4.1 by Robert Collins
Allow parameterisation of the branch initialisation for bzrlib.
156
        
157
        This will call the current default initializer with base
158
        as the only parameter.
159
        """
160
        return Branch._default_initializer(safe_unicode(base))
161
162
    @staticmethod
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
163
    @deprecated_function(zero_eight)
164
    def initialize(base):
165
        """Create a new working tree and branch, rooted at 'base' (url)
1551.1.2 by Martin Pool
Deprecation warnings for popular APIs that will change in BzrDir
166
167
        NOTE: This will soon be deprecated in favour of creation
168
        through a BzrDir.
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
169
        """
170
        # imported here to prevent scope creep as this is going.
171
        from bzrlib.workingtree import WorkingTree
172
        return WorkingTree.create_standalone(safe_unicode(base)).branch
173
174
    @staticmethod
1534.4.1 by Robert Collins
Allow parameterisation of the branch initialisation for bzrlib.
175
    def get_default_initializer():
176
        """Return the initializer being used for new branches."""
177
        return Branch._default_initializer
178
179
    @staticmethod
180
    def set_default_initializer(initializer):
181
        """Set the initializer to be used for new branches."""
182
        Branch._default_initializer = staticmethod(initializer)
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
183
184
    def setup_caching(self, cache_root):
185
        """Subclasses that care about caching should override this, and set
186
        up cached stores located under cache_root.
187
        """
1185.70.6 by Martin Pool
review fixups from John
188
        # seems to be unused, 2006-01-13 mbp
189
        warn('%s is deprecated' % self.setup_caching)
1400.1.1 by Robert Collins
implement a basic test for the ui branch command from http servers
190
        self.cache_root = cache_root
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
191
1185.35.11 by Aaron Bentley
Added support for branch nicks
192
    def _get_nick(self):
193
        cfg = self.tree_config()
1530.1.3 by Robert Collins
transport implementations now tested consistently.
194
        return cfg.get_option(u"nickname", default=self.base.split('/')[-2])
1185.35.11 by Aaron Bentley
Added support for branch nicks
195
196
    def _set_nick(self, nick):
197
        cfg = self.tree_config()
198
        cfg.set_option(nick, "nickname")
199
        assert cfg.get_option("nickname") == nick
200
201
    nick = property(_get_nick, _set_nick)
202
        
1495.1.2 by Jelmer Vernooij
Move some generic methods of NativeBranch to Branch.
203
    def push_stores(self, branch_to):
204
        """Copy the content of this branches store to branch_to."""
205
        raise NotImplementedError('push_stores is abstract')
206
207
    def lock_write(self):
208
        raise NotImplementedError('lock_write is abstract')
209
        
210
    def lock_read(self):
211
        raise NotImplementedError('lock_read is abstract')
212
213
    def unlock(self):
214
        raise NotImplementedError('unlock is abstract')
215
1185.70.3 by Martin Pool
Various updates to make storage branch mergeable:
216
    def peek_lock_mode(self):
217
        """Return lock mode for the Branch: 'r', 'w' or None"""
1185.70.6 by Martin Pool
review fixups from John
218
        raise NotImplementedError(self.peek_lock_mode)
1185.70.3 by Martin Pool
Various updates to make storage branch mergeable:
219
1495.1.2 by Jelmer Vernooij
Move some generic methods of NativeBranch to Branch.
220
    def abspath(self, name):
221
        """Return absolute filename for something in the branch
222
        
223
        XXX: Robert Collins 20051017 what is this used for? why is it a branch
224
        method and not a tree method.
225
        """
226
        raise NotImplementedError('abspath is abstract')
227
228
    def get_root_id(self):
229
        """Return the id of this branches root"""
230
        raise NotImplementedError('get_root_id is abstract')
231
1185.50.9 by John Arbash Meinel
[bug 3632] Matthieu Moy- bzr cat should default to last revision
232
    def print_file(self, file, revision_id):
1495.1.2 by Jelmer Vernooij
Move some generic methods of NativeBranch to Branch.
233
        """Print `file` to stdout."""
234
        raise NotImplementedError('print_file is abstract')
235
236
    def append_revision(self, *revision_ids):
237
        raise NotImplementedError('append_revision is abstract')
238
239
    def set_revision_history(self, rev_history):
240
        raise NotImplementedError('set_revision_history is abstract')
241
242
    def revision_history(self):
243
        """Return sequence of revision hashes on to this branch."""
244
        raise NotImplementedError('revision_history is abstract')
245
246
    def revno(self):
247
        """Return current revision number for this branch.
248
249
        That is equivalent to the number of revisions committed to
250
        this branch.
251
        """
252
        return len(self.revision_history())
253
254
    def last_revision(self):
255
        """Return last patch hash, or None if no history."""
256
        ph = self.revision_history()
257
        if ph:
258
            return ph[-1]
259
        else:
260
            return None
261
262
    def missing_revisions(self, other, stop_revision=None, diverged_ok=False):
263
        """Return a list of new revisions that would perfectly fit.
264
        
265
        If self and other have not diverged, return a list of the revisions
266
        present in other, but missing from self.
267
268
        >>> bzrlib.trace.silent = True
269
        >>> br1 = ScratchBranch()
270
        >>> br2 = ScratchBranch()
271
        >>> br1.missing_revisions(br2)
272
        []
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
273
        >>> br2.working_tree().commit("lala!", rev_id="REVISION-ID-1")
1495.1.2 by Jelmer Vernooij
Move some generic methods of NativeBranch to Branch.
274
        >>> br1.missing_revisions(br2)
275
        [u'REVISION-ID-1']
276
        >>> br2.missing_revisions(br1)
277
        []
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
278
        >>> br1.working_tree().commit("lala!", rev_id="REVISION-ID-1")
1495.1.2 by Jelmer Vernooij
Move some generic methods of NativeBranch to Branch.
279
        >>> br1.missing_revisions(br2)
280
        []
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
281
        >>> br2.working_tree().commit("lala!", rev_id="REVISION-ID-2A")
1495.1.2 by Jelmer Vernooij
Move some generic methods of NativeBranch to Branch.
282
        >>> br1.missing_revisions(br2)
283
        [u'REVISION-ID-2A']
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
284
        >>> br1.working_tree().commit("lala!", rev_id="REVISION-ID-2B")
1495.1.2 by Jelmer Vernooij
Move some generic methods of NativeBranch to Branch.
285
        >>> br1.missing_revisions(br2)
286
        Traceback (most recent call last):
1185.56.1 by Michael Ellerman
Simplify handling of DivergedBranches in cmd_pull()
287
        DivergedBranches: These branches have diverged.  Try merge.
1495.1.2 by Jelmer Vernooij
Move some generic methods of NativeBranch to Branch.
288
        """
289
        self_history = self.revision_history()
290
        self_len = len(self_history)
291
        other_history = other.revision_history()
292
        other_len = len(other_history)
293
        common_index = min(self_len, other_len) -1
294
        if common_index >= 0 and \
295
            self_history[common_index] != other_history[common_index]:
296
            raise DivergedBranches(self, other)
297
298
        if stop_revision is None:
299
            stop_revision = other_len
300
        else:
301
            assert isinstance(stop_revision, int)
302
            if stop_revision > other_len:
303
                raise bzrlib.errors.NoSuchRevision(self, stop_revision)
304
        return other_history[self_len:stop_revision]
1185.66.1 by Aaron Bentley
Merged from mainline
305
1495.1.2 by Jelmer Vernooij
Move some generic methods of NativeBranch to Branch.
306
    def update_revisions(self, other, stop_revision=None):
307
        """Pull in new perfect-fit revisions."""
308
        raise NotImplementedError('update_revisions is abstract')
309
310
    def pullable_revisions(self, other, stop_revision):
311
        raise NotImplementedError('pullable_revisions is abstract')
312
        
313
    def revision_id_to_revno(self, revision_id):
314
        """Given a revision id, return its revno"""
315
        if revision_id is None:
316
            return 0
317
        history = self.revision_history()
318
        try:
319
            return history.index(revision_id) + 1
320
        except ValueError:
321
            raise bzrlib.errors.NoSuchRevision(self, revision_id)
322
323
    def get_rev_id(self, revno, history=None):
324
        """Find the revision id of the specified revno."""
325
        if revno == 0:
326
            return None
327
        if history is None:
328
            history = self.revision_history()
329
        elif revno <= 0 or revno > len(history):
330
            raise bzrlib.errors.NoSuchRevision(self, revno)
331
        return history[revno - 1]
332
333
    def working_tree(self):
1508.1.15 by Robert Collins
Merge from mpool.
334
        """Return a `Tree` for the working copy if this is a local branch."""
1495.1.2 by Jelmer Vernooij
Move some generic methods of NativeBranch to Branch.
335
        raise NotImplementedError('working_tree is abstract')
336
337
    def pull(self, source, overwrite=False):
338
        raise NotImplementedError('pull is abstract')
339
340
    def basis_tree(self):
341
        """Return `Tree` object for last revision.
342
343
        If there are no revisions yet, return an `EmptyTree`.
344
        """
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
345
        return self.repository.revision_tree(self.last_revision())
1495.1.2 by Jelmer Vernooij
Move some generic methods of NativeBranch to Branch.
346
347
    def rename_one(self, from_rel, to_rel):
348
        """Rename one file.
349
350
        This can change the directory or the filename or both.
351
        """
352
        raise NotImplementedError('rename_one is abstract')
353
354
    def move(self, from_paths, to_name):
355
        """Rename files.
356
357
        to_name must exist as a versioned directory.
358
359
        If to_name exists and is a directory, the files are moved into
360
        it, keeping their old names.  If it is a directory, 
361
362
        Note that to_name is only the last component of the new name;
363
        this doesn't change the directory.
364
365
        This returns a list of (from_path, to_path) pairs for each
366
        entry that is moved.
367
        """
368
        raise NotImplementedError('move is abstract')
369
370
    def get_parent(self):
371
        """Return the parent location of the branch.
372
373
        This is the default location for push/pull/missing.  The usual
374
        pattern is that the user can override it by specifying a
375
        location.
376
        """
377
        raise NotImplementedError('get_parent is abstract')
378
379
    def get_push_location(self):
380
        """Return the None or the location to push this branch to."""
381
        raise NotImplementedError('get_push_location is abstract')
382
383
    def set_push_location(self, location):
384
        """Set a new push location for this branch."""
385
        raise NotImplementedError('set_push_location is abstract')
386
387
    def set_parent(self, url):
388
        raise NotImplementedError('set_parent is abstract')
389
390
    def check_revno(self, revno):
391
        """\
392
        Check whether a revno corresponds to any revision.
393
        Zero (the NULL revision) is considered valid.
394
        """
395
        if revno != 0:
396
            self.check_real_revno(revno)
397
            
398
    def check_real_revno(self, revno):
399
        """\
400
        Check whether a revno corresponds to a real revision.
401
        Zero (the NULL revision) is considered invalid
402
        """
403
        if revno < 1 or revno > self.revno():
404
            raise InvalidRevisionNumber(revno)
405
        
1185.66.8 by Aaron Bentley
Applied Jelmer's patch to make clone a branch operation
406
    def clone(self, to_location, revision=None, basis_branch=None, to_branch_type=None):
407
        """Copy this branch into the existing directory to_location.
408
409
        Returns the newly created branch object.
410
411
        revision
412
            If not None, only revisions up to this point will be copied.
413
            The head of the new branch will be that revision.  Must be a
414
            revid or None.
415
    
416
        to_location -- The destination directory; must either exist and be 
417
            empty, or not exist, in which case it is created.
418
    
419
        basis_branch
420
            A local branch to copy revisions from, related to this branch. 
421
            This is used when branching from a remote (slow) branch, and we have
422
            a local branch that might contain some relevant revisions.
423
    
424
        to_branch_type
425
            Branch type of destination branch
426
        """
1534.4.28 by Robert Collins
first cut at merge from integration.
427
        from bzrlib.workingtree import WorkingTree
1185.66.8 by Aaron Bentley
Applied Jelmer's patch to make clone a branch operation
428
        assert isinstance(to_location, basestring)
429
        if not bzrlib.osutils.lexists(to_location):
430
            os.mkdir(to_location)
431
        if to_branch_type is None:
432
            to_branch_type = BzrBranch
1534.4.28 by Robert Collins
first cut at merge from integration.
433
        print "FIXME use a branch format here"
1185.66.8 by Aaron Bentley
Applied Jelmer's patch to make clone a branch operation
434
        br_to = to_branch_type.initialize(to_location)
435
        mutter("copy branch from %s to %s", self, br_to)
436
        if basis_branch is not None:
437
            basis_branch.push_stores(br_to)
438
        if revision is None:
439
            revision = self.last_revision()
440
        br_to.update_revisions(self, stop_revision=revision)
441
        br_to.set_parent(self.base)
1534.4.28 by Robert Collins
first cut at merge from integration.
442
        WorkingTree.create(br_to, to_location).set_root_id(self.get_root_id())
1185.66.8 by Aaron Bentley
Applied Jelmer's patch to make clone a branch operation
443
        mutter("copied")
444
        return br_to
1185.66.1 by Aaron Bentley
Merged from mainline
445
1534.4.22 by Robert Collins
update TODOs and move abstract methods that were misplaced on BzrBranchFormat5 to Branch.
446
    def fileid_involved_between_revs(self, from_revid, to_revid):
447
        """ This function returns the file_id(s) involved in the
448
            changes between the from_revid revision and the to_revid
449
            revision
450
        """
451
        raise NotImplementedError('fileid_involved_between_revs is abstract')
452
453
    def fileid_involved(self, last_revid=None):
454
        """ This function returns the file_id(s) involved in the
455
            changes up to the revision last_revid
456
            If no parametr is passed, then all file_id[s] present in the
457
            repository are returned
458
        """
459
        raise NotImplementedError('fileid_involved is abstract')
460
461
    def fileid_involved_by_set(self, changes):
462
        """ This function returns the file_id(s) involved in the
463
            changes present in the set 'changes'
464
        """
465
        raise NotImplementedError('fileid_involved_by_set is abstract')
466
467
    def fileid_involved_between_revs(self, from_revid, to_revid):
468
        """ This function returns the file_id(s) involved in the
469
            changes between the from_revid revision and the to_revid
470
            revision
471
        """
472
        raise NotImplementedError('fileid_involved_between_revs is abstract')
473
474
    def fileid_involved(self, last_revid=None):
475
        """ This function returns the file_id(s) involved in the
476
            changes up to the revision last_revid
477
            If no parametr is passed, then all file_id[s] present in the
478
            repository are returned
479
        """
480
        raise NotImplementedError('fileid_involved is abstract')
481
482
    def fileid_involved_by_set(self, changes):
483
        """ This function returns the file_id(s) involved in the
484
            changes present in the set 'changes'
485
        """
486
        raise NotImplementedError('fileid_involved_by_set is abstract')
1534.4.1 by Robert Collins
Allow parameterisation of the branch initialisation for bzrlib.
487
1534.4.2 by Robert Collins
Introduce BranchFormats - factoring out intialisation of Branches.
488
class BzrBranchFormat(object):
489
    """An encapsulation of the initialization and open routines for a format.
490
491
    Formats provide three things:
492
     * An initialization routine,
493
     * a format string,
494
     * an open routine.
495
496
    Formats are placed in an dict by their format string for reference 
497
    during branch opening. Its not required that these be instances, they
498
    can be classes themselves with class methods - it simply depends on 
499
    whether state is needed for a given format or not.
500
501
    Once a format is deprecated, just deprecate the initialize and open
502
    methods on the format class. Do not deprecate the object, as the 
503
    object will be created every time regardless.
504
    """
505
506
    _formats = {}
507
    """The known formats."""
508
509
    @classmethod
1534.4.4 by Robert Collins
Make BzrBranchFormat.find_format take a transport not a url for efficiency.
510
    def find_format(klass, transport):
1534.4.2 by Robert Collins
Introduce BranchFormats - factoring out intialisation of Branches.
511
        """Return the format registered for URL."""
1534.4.5 by Robert Collins
Turn branch format.open into a factory.
512
        try:
1534.4.7 by Robert Collins
Move downlevel check up to the Branch.open logic, removing it from the Branch constructor and deprecating relax_version_check to the same.
513
            format_string = transport.get(".bzr/branch-format").read()
514
            return klass._formats[format_string]
1534.4.5 by Robert Collins
Turn branch format.open into a factory.
515
        except NoSuchFile:
516
            raise NotBranchError(path=transport.base)
1534.4.7 by Robert Collins
Move downlevel check up to the Branch.open logic, removing it from the Branch constructor and deprecating relax_version_check to the same.
517
        except KeyError:
518
            raise errors.UnknownFormatError(format_string)
1534.4.2 by Robert Collins
Introduce BranchFormats - factoring out intialisation of Branches.
519
520
    def get_format_string(self):
521
        """Return the ASCII format string that identifies this format."""
522
        raise NotImplementedError(self.get_format_string)
523
524
    def _find_modes(self, t):
525
        """Determine the appropriate modes for files and directories.
526
        
527
        FIXME: When this merges into, or from storage,
528
        this code becomes delgatable to a LockableFiles instance.
529
530
        For now its cribbed and returns (dir_mode, file_mode)
531
        """
532
        try:
533
            st = t.stat('.')
534
        except errors.TransportNotPossible:
535
            dir_mode = 0755
536
            file_mode = 0644
537
        else:
538
            dir_mode = st.st_mode & 07777
539
            # Remove the sticky and execute bits for files
540
            file_mode = dir_mode & ~07111
541
        if not BzrBranch._set_dir_mode:
542
            dir_mode = None
543
        if not BzrBranch._set_file_mode:
544
            file_mode = None
545
        return dir_mode, file_mode
546
547
    def initialize(self, url):
548
        """Create a branch of this format at url and return an open branch."""
549
        t = get_transport(url)
550
        from bzrlib.weavefile import write_weave_v5
551
        from bzrlib.weave import Weave
552
        
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
553
        # Create an empty weave
1534.4.2 by Robert Collins
Introduce BranchFormats - factoring out intialisation of Branches.
554
        sio = StringIO()
555
        bzrlib.weavefile.write_weave_v5(Weave(), sio)
556
        empty_weave = sio.getvalue()
557
558
        # Since we don't have a .bzr directory, inherit the
559
        # mode from the root directory
1534.4.28 by Robert Collins
first cut at merge from integration.
560
        temp_control = LockableFiles(t, '')
561
        temp_control._transport.mkdir('.bzr',
562
                                      mode=temp_control._dir_mode)
563
        file_mode = temp_control._file_mode
564
        del temp_control
565
        mutter('created control directory in ' + t.base)
1534.4.2 by Robert Collins
Introduce BranchFormats - factoring out intialisation of Branches.
566
        control = t.clone('.bzr')
567
        dirs = ['revision-store', 'weaves']
1534.4.28 by Robert Collins
first cut at merge from integration.
568
        lock_file = 'branch-lock'
569
        utf8_files = [('README', 
570
                       "This is a Bazaar-NG control directory.\n"
571
                       "Do not change any files in this directory.\n"),
572
                      ('branch-format', self.get_format_string()),
573
                      ('revision-history', ''),
574
                      ('branch-name', ''),
575
                      ]
576
        files = [('inventory.weave', StringIO(empty_weave)), 
577
                 ]
578
        
579
        # FIXME: RBC 20060125 dont peek under the covers
580
        # NB: no need to escape relative paths that are url safe.
581
        control.put(lock_file, StringIO(), mode=file_mode)
582
        control_files = LockableFiles(control, lock_file)
583
        control_files.lock_write()
584
        control_files._transport.mkdir_multi(dirs,
585
                mode=control_files._dir_mode)
586
        try:
587
            for file, content in utf8_files:
588
                control_files.put_utf8(file, content)
589
            for file, content in files:
590
                control_files.put(file, content)
591
        finally:
592
            control_files.unlock()
593
        return BzrBranch(t, _format=self, _control_files=control_files)
1534.4.2 by Robert Collins
Introduce BranchFormats - factoring out intialisation of Branches.
594
1534.4.7 by Robert Collins
Move downlevel check up to the Branch.open logic, removing it from the Branch constructor and deprecating relax_version_check to the same.
595
    def is_supported(self):
596
        """Is this format supported?
597
598
        Supported formats can be initialized and opened.
599
        Unsupported formats may not support initialization or committing or 
600
        some other features depending on the reason for not being supported.
601
        """
602
        return True
603
1534.4.5 by Robert Collins
Turn branch format.open into a factory.
604
    def open(self, transport):
1534.4.2 by Robert Collins
Introduce BranchFormats - factoring out intialisation of Branches.
605
        """Fill out the data in branch for the branch at url."""
1534.4.28 by Robert Collins
first cut at merge from integration.
606
        return BzrBranch(transport, _format=self)
1534.4.2 by Robert Collins
Introduce BranchFormats - factoring out intialisation of Branches.
607
608
    @classmethod
609
    def register_format(klass, format):
610
        klass._formats[format.get_format_string()] = format
611
1534.4.7 by Robert Collins
Move downlevel check up to the Branch.open logic, removing it from the Branch constructor and deprecating relax_version_check to the same.
612
    @classmethod
613
    def unregister_format(klass, format):
614
        assert klass._formats[format.get_format_string()] is format
615
        del klass._formats[format.get_format_string()]
616
1534.4.2 by Robert Collins
Introduce BranchFormats - factoring out intialisation of Branches.
617
618
class BzrBranchFormat4(BzrBranchFormat):
619
    """Bzr branch format 4.
620
621
    This format has:
622
     - flat stores
623
     - TextStores for texts, inventories,revisions.
624
625
    This format is deprecated: it indexes texts using a text it which is
626
    removed in format 5; write support for this format has been removed.
627
    """
628
629
    def get_format_string(self):
630
        """See BzrBranchFormat.get_format_string()."""
631
        return BZR_BRANCH_FORMAT_4
632
633
    def initialize(self, url):
634
        """Format 4 branches cannot be created."""
1534.4.3 by Robert Collins
Implement BranchTestProviderAdapter, so tests now run across all branch formats.
635
        raise UninitializableFormat(self)
1534.4.2 by Robert Collins
Introduce BranchFormats - factoring out intialisation of Branches.
636
1534.4.7 by Robert Collins
Move downlevel check up to the Branch.open logic, removing it from the Branch constructor and deprecating relax_version_check to the same.
637
    def is_supported(self):
638
        """Format 4 is not supported.
639
640
        It is not supported because the model changed from 4 to 5 and the
641
        conversion logic is expensive - so doing it on the fly was not 
642
        feasible.
643
        """
644
        return False
645
1534.4.2 by Robert Collins
Introduce BranchFormats - factoring out intialisation of Branches.
646
647
class BzrBranchFormat5(BzrBranchFormat):
648
    """Bzr branch format 5.
649
650
    This format has:
651
     - weaves for file texts and inventory
652
     - flat stores
653
     - TextStores for revisions and signatures.
654
    """
655
656
    def get_format_string(self):
657
        """See BzrBranchFormat.get_format_string()."""
658
        return BZR_BRANCH_FORMAT_5
659
660
661
class BzrBranchFormat6(BzrBranchFormat):
662
    """Bzr branch format 6.
663
664
    This format has:
665
     - weaves for file texts and inventory
666
     - hash subdirectory based stores.
667
     - TextStores for revisions and signatures.
668
    """
669
670
    def get_format_string(self):
671
        """See BzrBranchFormat.get_format_string()."""
672
        return BZR_BRANCH_FORMAT_6
673
674
675
BzrBranchFormat.register_format(BzrBranchFormat4())
676
BzrBranchFormat.register_format(BzrBranchFormat5())
677
BzrBranchFormat.register_format(BzrBranchFormat6())
678
1534.4.19 by Robert Collins
merge from integration.
679
# TODO: jam 20060108 Create a new branch format, and as part of upgrade
680
#       make sure that ancestry.weave is deleted (it is never used, but
681
#       used to be created)
1534.1.10 by Robert Collins
Merge from jam-integration.
682
1534.4.5 by Robert Collins
Turn branch format.open into a factory.
683
1495.1.5 by Jelmer Vernooij
Rename NativeBranch -> BzrBranch
684
class BzrBranch(Branch):
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
685
    """A branch stored in the actual filesystem.
686
687
    Note that it's "local" in the context of the filesystem; it doesn't
688
    really matter if it's on an nfs/smb/afs/coda/... share, as long as
689
    it's writable, and can be accessed via the normal filesystem API.
578 by Martin Pool
- start to move toward Branch.lock and unlock methods,
690
1 by mbp at sourcefrog
import from baz patch-364
691
    """
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
692
    # We actually expect this class to be somewhat short-lived; part of its
693
    # purpose is to try to isolate what bits of the branch logic are tied to
694
    # filesystem access, so that in a later step, we can extricate them to
695
    # a separarte ("storage") class.
1223 by Martin Pool
- store inventories in weave
696
    _inventory_weave = None
353 by Martin Pool
- Per-branch locks in read and write modes.
697
    
897 by Martin Pool
- merge john's revision-naming code
698
    # Map some sort of prefix into a namespace
699
    # stuff like "revno:10", "revid:", etc.
700
    # This should match a prefix with a function which accepts
701
    REVISION_NAMESPACES = {}
702
1391 by Robert Collins
merge from integration
703
    def push_stores(self, branch_to):
1495.1.2 by Jelmer Vernooij
Move some generic methods of NativeBranch to Branch.
704
        """See Branch.push_stores."""
1534.4.8 by Robert Collins
Unfuck upgrade.
705
        if (not isinstance(self._branch_format, BzrBranchFormat4) or
706
            self._branch_format != branch_to._branch_format):
1391 by Robert Collins
merge from integration
707
            from bzrlib.fetch import greedy_fetch
1534.4.8 by Robert Collins
Unfuck upgrade.
708
            mutter("Using fetch logic to push between %s(%s) and %s(%s)",
1393 by Robert Collins
reenable remotebranch tests
709
                   self, self._branch_format, branch_to, branch_to._branch_format)
1391 by Robert Collins
merge from integration
710
            greedy_fetch(to_branch=branch_to, from_branch=self,
711
                         revision=self.last_revision())
712
            return
713
1534.4.8 by Robert Collins
Unfuck upgrade.
714
        # format 4 to format 4 logic only.
1391 by Robert Collins
merge from integration
715
        store_pairs = ((self.text_store,      branch_to.text_store),
716
                       (self.inventory_store, branch_to.inventory_store),
717
                       (self.revision_store,  branch_to.revision_store))
718
        try:
719
            for from_store, to_store in store_pairs: 
720
                copy_all(from_store, to_store)
721
        except UnlistableStore:
722
            raise UnlistableBranch(from_store)
723
1534.4.32 by Robert Collins
Rename deprecated_nonce to DEPRECATED_PARAMETER
724
    def __init__(self, transport, init=DEPRECATED_PARAMETER,
725
                 relax_version_check=DEPRECATED_PARAMETER, _format=None,
1534.4.28 by Robert Collins
first cut at merge from integration.
726
                 _control_files=None):
1 by mbp at sourcefrog
import from baz patch-364
727
        """Create new branch object at a particular location.
728
907.1.2 by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport.
729
        transport -- A Transport object, defining how to access files.
62 by mbp at sourcefrog
- new find_branch_root function; based on suggestion from aaron
730
        
254 by Martin Pool
- Doc cleanups from Magnus Therning
731
        init -- If True, create new control files in a previously
1 by mbp at sourcefrog
import from baz patch-364
732
             unversioned directory.  If False, the branch must already
733
             be versioned.
734
1293 by Martin Pool
- add Branch constructor option to relax version check
735
        relax_version_check -- If true, the usual check for the branch
736
            version is not applied.  This is intended only for
737
            upgrade/recovery type use; it's not guaranteed that
738
            all operations will work on old format branches.
739
1 by mbp at sourcefrog
import from baz patch-364
740
        In the test suite, creation of new trees is tested using the
741
        `ScratchBranch` class.
742
        """
1393.1.15 by Martin Pool
- better assertion message
743
        assert isinstance(transport, Transport), \
744
            "%r is not a Transport" % transport
907.1.8 by John Arbash Meinel
Changed the format for abspath. Updated branch to use a hidden _transport
745
        self._transport = transport
1534.4.28 by Robert Collins
first cut at merge from integration.
746
        self._base = self._transport.base
747
        if _control_files is None:
748
            _control_files = LockableFiles(self._transport.clone(bzrlib.BZRDIR),
1185.69.2 by John Arbash Meinel
Changed LockableFiles to take the root directory directly. Moved mode information into LockableFiles instead of Branch
749
                                           'branch-lock')
1534.4.28 by Robert Collins
first cut at merge from integration.
750
        self.control_files = _control_files
1534.4.2 by Robert Collins
Introduce BranchFormats - factoring out intialisation of Branches.
751
        if deprecated_passed(init):
752
            warn("BzrBranch.__init__(..., init=XXX): The init parameter is "
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
753
                 "deprecated as of bzr 0.8. Please use Branch.create().",
754
                 DeprecationWarning,
755
                 stacklevel=2)
1534.4.2 by Robert Collins
Introduce BranchFormats - factoring out intialisation of Branches.
756
            if init:
757
                # this is slower than before deprecation, oh well never mind.
758
                # -> its deprecated.
759
                self._initialize(transport.base)
1534.4.28 by Robert Collins
first cut at merge from integration.
760
        self._check_format(_format)
1534.4.7 by Robert Collins
Move downlevel check up to the Branch.open logic, removing it from the Branch constructor and deprecating relax_version_check to the same.
761
        if deprecated_passed(relax_version_check):
762
            warn("BzrBranch.__init__(..., relax_version_check=XXX_: The "
763
                 "relax_version_check parameter is deprecated as of bzr 0.8. "
764
                 "Please use Branch.open_downlevel, or a BzrBranchFormat's "
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
765
                 "open() method.",
766
                 DeprecationWarning,
767
                 stacklevel=2)
1534.4.7 by Robert Collins
Move downlevel check up to the Branch.open logic, removing it from the Branch constructor and deprecating relax_version_check to the same.
768
            if (not relax_version_check
1534.4.8 by Robert Collins
Unfuck upgrade.
769
                and not self._branch_format.is_supported()):
1534.4.7 by Robert Collins
Move downlevel check up to the Branch.open logic, removing it from the Branch constructor and deprecating relax_version_check to the same.
770
                raise errors.UnsupportedFormatError(
771
                        'sorry, branch format %r not supported' % fmt,
772
                        ['use a different bzr version',
773
                         'or remove the .bzr directory'
774
                         ' and "bzr init" again'])
1185.69.2 by John Arbash Meinel
Changed LockableFiles to take the root directory directly. Moved mode information into LockableFiles instead of Branch
775
        self.repository = Repository(transport, self._branch_format)
1 by mbp at sourcefrog
import from baz patch-364
776
777
1534.4.1 by Robert Collins
Allow parameterisation of the branch initialisation for bzrlib.
778
    @staticmethod
779
    def _initialize(base):
780
        """Create a bzr branch in the latest format."""
1534.4.2 by Robert Collins
Introduce BranchFormats - factoring out intialisation of Branches.
781
        return BzrBranchFormat6().initialize(base)
1534.4.1 by Robert Collins
Allow parameterisation of the branch initialisation for bzrlib.
782
1 by mbp at sourcefrog
import from baz patch-364
783
    def __str__(self):
1185.65.11 by Robert Collins
Disable inheritance for getting at LockableFiles, rather use composition.
784
        return '%s(%r)' % (self.__class__.__name__, self.base)
1 by mbp at sourcefrog
import from baz patch-364
785
786
    __repr__ = __str__
787
578 by Martin Pool
- start to move toward Branch.lock and unlock methods,
788
    def __del__(self):
907.1.23 by John Arbash Meinel
Branch objects now automatically create Cached stores if the protocol is_remote.
789
        # TODO: It might be best to do this somewhere else,
790
        # but it is nice for a Branch object to automatically
791
        # cache it's information.
792
        # Alternatively, we could have the Transport objects cache requests
793
        # See the earlier discussion about how major objects (like Branch)
794
        # should never expect their __del__ function to run.
1185.70.6 by Martin Pool
review fixups from John
795
        # XXX: cache_root seems to be unused, 2006-01-13 mbp
1185.11.9 by John Arbash Meinel
Most tests pass, some problems with unavailable socket recv
796
        if hasattr(self, 'cache_root') and self.cache_root is not None:
907.1.23 by John Arbash Meinel
Branch objects now automatically create Cached stores if the protocol is_remote.
797
            try:
798
                shutil.rmtree(self.cache_root)
799
            except:
800
                pass
801
            self.cache_root = None
802
907.1.17 by John Arbash Meinel
Adding a Branch.base property, removing pull_loc()
803
    def _get_base(self):
1185.69.2 by John Arbash Meinel
Changed LockableFiles to take the root directory directly. Moved mode information into LockableFiles instead of Branch
804
        return self._base
907.1.17 by John Arbash Meinel
Adding a Branch.base property, removing pull_loc()
805
1442.1.5 by Robert Collins
Give branch.base a docstring.
806
    base = property(_get_base, doc="The URL for the root of this branch.")
578 by Martin Pool
- start to move toward Branch.lock and unlock methods,
807
1417.1.6 by Robert Collins
introduce transactions for grouping actions done to and with branches
808
    def _finish_transaction(self):
809
        """Exit the current transaction."""
1185.65.13 by Robert Collins
Merge from integration
810
        return self.control_files._finish_transaction()
1417.1.6 by Robert Collins
introduce transactions for grouping actions done to and with branches
811
812
    def get_transaction(self):
1185.65.13 by Robert Collins
Merge from integration
813
        """Return the current active transaction.
814
815
        If no transaction is active, this returns a passthrough object
816
        for which all data is immediately flushed and no caching happens.
817
        """
818
        # this is an explicit function so that we can do tricky stuff
819
        # when the storage in rev_storage is elsewhere.
820
        # we probably need to hook the two 'lock a location' and 
821
        # 'have a transaction' together more delicately, so that
822
        # we can have two locks (branch and storage) and one transaction
823
        # ... and finishing the transaction unlocks both, but unlocking
824
        # does not. - RBC 20051121
825
        return self.control_files.get_transaction()
826
827
    def _set_transaction(self, transaction):
1417.1.6 by Robert Collins
introduce transactions for grouping actions done to and with branches
828
        """Set a new active transaction."""
1185.65.13 by Robert Collins
Merge from integration
829
        return self.control_files._set_transaction(transaction)
353 by Martin Pool
- Per-branch locks in read and write modes.
830
67 by mbp at sourcefrog
use abspath() for the function that makes an absolute
831
    def abspath(self, name):
1495.1.2 by Jelmer Vernooij
Move some generic methods of NativeBranch to Branch.
832
        """See Branch.abspath."""
1185.65.11 by Robert Collins
Disable inheritance for getting at LockableFiles, rather use composition.
833
        return self.control_files._transport.abspath(name)
1185.58.4 by John Arbash Meinel
Added permission checking to Branch, and propogated that change into the stores.
834
1534.4.7 by Robert Collins
Move downlevel check up to the Branch.open logic, removing it from the Branch constructor and deprecating relax_version_check to the same.
835
    def _check_format(self, format):
1534.4.8 by Robert Collins
Unfuck upgrade.
836
        """Identify the branch format if needed.
1 by mbp at sourcefrog
import from baz patch-364
837
1534.4.8 by Robert Collins
Unfuck upgrade.
838
        The format is stored as a reference to the format object in
1187 by Martin Pool
- improved check for branch version
839
        self._branch_format for code that needs to check it later.
1 by mbp at sourcefrog
import from baz patch-364
840
1534.4.5 by Robert Collins
Turn branch format.open into a factory.
841
        The format parameter is either None or the branch format class
842
        used to open this branch.
163 by mbp at sourcefrog
merge win32 portability fixes
843
        """
1534.4.5 by Robert Collins
Turn branch format.open into a factory.
844
        if format is None:
845
            format = BzrBranchFormat.find_format(self._transport)
1534.4.8 by Robert Collins
Unfuck upgrade.
846
        self._branch_format = format
847
        mutter("got branch format %s", self._branch_format)
907.1.2 by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport.
848
1508.1.15 by Robert Collins
Merge from mpool.
849
    @needs_read_lock
909 by Martin Pool
- merge John's code to give the tree root an explicit file id
850
    def get_root_id(self):
1495.1.2 by Jelmer Vernooij
Move some generic methods of NativeBranch to Branch.
851
        """See Branch.get_root_id."""
1534.4.28 by Robert Collins
first cut at merge from integration.
852
        tree = self.repository.revision_tree(self.last_revision())
853
        return tree.inventory.root.file_id
1 by mbp at sourcefrog
import from baz patch-364
854
1185.65.3 by Aaron Bentley
Fixed locking-- all tests pass
855
    def lock_write(self):
1185.65.11 by Robert Collins
Disable inheritance for getting at LockableFiles, rather use composition.
856
        # TODO: test for failed two phase locks. This is known broken.
857
        self.control_files.lock_write()
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
858
        self.repository.lock_write()
1185.65.1 by Aaron Bentley
Refactored out ControlFiles and RevisionStore from _Branch
859
1185.65.3 by Aaron Bentley
Fixed locking-- all tests pass
860
    def lock_read(self):
1185.65.11 by Robert Collins
Disable inheritance for getting at LockableFiles, rather use composition.
861
        # TODO: test for failed two phase locks. This is known broken.
862
        self.control_files.lock_read()
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
863
        self.repository.lock_read()
1185.65.1 by Aaron Bentley
Refactored out ControlFiles and RevisionStore from _Branch
864
865
    def unlock(self):
1185.65.11 by Robert Collins
Disable inheritance for getting at LockableFiles, rather use composition.
866
        # TODO: test for failed two phase locks. This is known broken.
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
867
        self.repository.unlock()
1185.65.11 by Robert Collins
Disable inheritance for getting at LockableFiles, rather use composition.
868
        self.control_files.unlock()
1185.65.1 by Aaron Bentley
Refactored out ControlFiles and RevisionStore from _Branch
869
1185.70.3 by Martin Pool
Various updates to make storage branch mergeable:
870
    def peek_lock_mode(self):
871
        if self.control_files._lock_count == 0:
872
            return None
873
        else:
874
            return self.control_files._lock_mode
875
1442.1.63 by Robert Collins
Remove self.lock_*...finally: self.unlock() dead chickens from branch.py.
876
    @needs_read_lock
1185.50.9 by John Arbash Meinel
[bug 3632] Matthieu Moy- bzr cat should default to last revision
877
    def print_file(self, file, revision_id):
1495.1.2 by Jelmer Vernooij
Move some generic methods of NativeBranch to Branch.
878
        """See Branch.print_file."""
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
879
        return self.repository.print_file(file, revision_id)
1442.1.63 by Robert Collins
Remove self.lock_*...finally: self.unlock() dead chickens from branch.py.
880
881
    @needs_write_lock
905 by Martin Pool
- merge aaron's append_multiple.patch
882
    def append_revision(self, *revision_ids):
1495.1.2 by Jelmer Vernooij
Move some generic methods of NativeBranch to Branch.
883
        """See Branch.append_revision."""
905 by Martin Pool
- merge aaron's append_multiple.patch
884
        for revision_id in revision_ids:
885
            mutter("add {%s} to revision-history" % revision_id)
1442.1.63 by Robert Collins
Remove self.lock_*...finally: self.unlock() dead chickens from branch.py.
886
        rev_history = self.revision_history()
887
        rev_history.extend(revision_ids)
1442.1.68 by Robert Collins
'bzr pull' now accepts '--clobber'.
888
        self.set_revision_history(rev_history)
889
890
    @needs_write_lock
891
    def set_revision_history(self, rev_history):
1495.1.2 by Jelmer Vernooij
Move some generic methods of NativeBranch to Branch.
892
        """See Branch.set_revision_history."""
1185.65.12 by Robert Collins
Remove the only-used-once put_controlfiles, and change put_controlfile to put and put_utf8.
893
        self.control_files.put_utf8(
1185.65.11 by Robert Collins
Disable inheritance for getting at LockableFiles, rather use composition.
894
            'revision-history', '\n'.join(rev_history))
233 by mbp at sourcefrog
- more output from test.sh
895
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
896
    def get_revision_delta(self, revno):
897
        """Return the delta for one revision.
898
899
        The delta is relative to its mainline predecessor, or the
900
        empty tree for revision 1.
901
        """
902
        assert isinstance(revno, int)
903
        rh = self.revision_history()
904
        if not (1 <= revno <= len(rh)):
905
            raise InvalidRevisionNumber(revno)
906
907
        # revno is 1-based; list is 0-based
908
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
909
        new_tree = self.repository.revision_tree(rh[revno-1])
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
910
        if revno == 1:
911
            old_tree = EmptyTree()
912
        else:
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
913
            old_tree = self.repository.revision_tree(rh[revno-2])
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
914
        return compare_trees(old_tree, new_tree)
915
1442.1.63 by Robert Collins
Remove self.lock_*...finally: self.unlock() dead chickens from branch.py.
916
    @needs_read_lock
1 by mbp at sourcefrog
import from baz patch-364
917
    def revision_history(self):
1495.1.2 by Jelmer Vernooij
Move some generic methods of NativeBranch to Branch.
918
        """See Branch.revision_history."""
1185.65.11 by Robert Collins
Disable inheritance for getting at LockableFiles, rather use composition.
919
        # FIXME are transactions bound to control files ? RBC 20051121
1442.1.63 by Robert Collins
Remove self.lock_*...finally: self.unlock() dead chickens from branch.py.
920
        transaction = self.get_transaction()
921
        history = transaction.map.find_revision_history()
922
        if history is not None:
923
            mutter("cache hit for revision-history in %s", self)
1417.1.12 by Robert Collins
cache revision history during read transactions
924
            return list(history)
1442.1.63 by Robert Collins
Remove self.lock_*...finally: self.unlock() dead chickens from branch.py.
925
        history = [l.rstrip('\r\n') for l in
1185.65.29 by Robert Collins
Implement final review suggestions.
926
                self.control_files.get_utf8('revision-history').readlines()]
1442.1.63 by Robert Collins
Remove self.lock_*...finally: self.unlock() dead chickens from branch.py.
927
        transaction.map.add_revision_history(history)
928
        # this call is disabled because revision_history is 
929
        # not really an object yet, and the transaction is for objects.
930
        # transaction.register_clean(history, precious=True)
931
        return list(history)
1 by mbp at sourcefrog
import from baz patch-364
932
974.1.28 by aaron.bentley at utoronto
factored install_revisions out of update_revisions, updated test cases for greedy_fetch
933
    def update_revisions(self, other, stop_revision=None):
1495.1.2 by Jelmer Vernooij
Move some generic methods of NativeBranch to Branch.
934
        """See Branch.update_revisions."""
974.1.33 by aaron.bentley at utoronto
Added greedy_fetch to update_revisions
935
        from bzrlib.fetch import greedy_fetch
974.1.75 by Aaron Bentley
Sped up pull by copying locally first
936
        if stop_revision is None:
1390 by Robert Collins
pair programming worx... merge integration and weave
937
            stop_revision = other.last_revision()
1185.12.44 by abentley
Restored branch convergence to bzr pull
938
        ### Should this be checking is_ancestor instead of revision_history?
1441 by Robert Collins
tests passing is a good idea - move the branch open in cmd_branch to ensure this, and remove noise from the test suite
939
        if (stop_revision is not None and 
940
            stop_revision in self.revision_history()):
1440 by Robert Collins
further tuning of pull, do not do a local merge or fetch at all, if the remote branch is no newer than we are
941
            return
1260 by Martin Pool
- some updates for fetch/update function
942
        greedy_fetch(to_branch=self, from_branch=other,
1261 by Martin Pool
- new method Branch.has_revision
943
                     revision=stop_revision)
1185.12.44 by abentley
Restored branch convergence to bzr pull
944
        pullable_revs = self.pullable_revisions(other, stop_revision)
1185.12.45 by abentley
Cleanups for pull
945
        if len(pullable_revs) > 0:
1261 by Martin Pool
- new method Branch.has_revision
946
            self.append_revision(*pullable_revs)
1185.12.44 by abentley
Restored branch convergence to bzr pull
947
948
    def pullable_revisions(self, other, stop_revision):
1495.1.2 by Jelmer Vernooij
Move some generic methods of NativeBranch to Branch.
949
        """See Branch.pullable_revisions."""
1185.12.44 by abentley
Restored branch convergence to bzr pull
950
        other_revno = other.revision_id_to_revno(stop_revision)
951
        try:
952
            return self.missing_revisions(other, other_revno)
953
        except DivergedBranches, e:
954
            try:
955
                pullable_revs = get_intervening_revisions(self.last_revision(),
1185.65.1 by Aaron Bentley
Refactored out ControlFiles and RevisionStore from _Branch
956
                                                          stop_revision, 
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
957
                                                          self.repository)
1185.12.44 by abentley
Restored branch convergence to bzr pull
958
                assert self.last_revision() not in pullable_revs
959
                return pullable_revs
960
            except bzrlib.errors.NotAncestor:
961
                if is_ancestor(self.last_revision(), stop_revision, self):
962
                    return []
963
                else:
964
                    raise e
965
        
1185.33.59 by Martin Pool
[patch] keep a cached basis inventory (Johan Rydberg)
966
    def basis_tree(self):
967
        """See Branch.basis_tree."""
968
        try:
969
            revision_id = self.revision_history()[-1]
1185.65.15 by Robert Collins
Merge from integration.
970
            # FIXME: This is an abstraction violation, the basis tree 
971
            # here as defined is on the working tree, the method should
972
            # be too. The basis tree for a branch can be different than
973
            # that for a working tree. RBC 20051207
1185.33.59 by Martin Pool
[patch] keep a cached basis inventory (Johan Rydberg)
974
            xml = self.working_tree().read_basis_inventory(revision_id)
975
            inv = bzrlib.xml5.serializer_v5.read_inventory_from_string(xml)
1185.65.17 by Robert Collins
Merge from integration, mode-changes are broken.
976
            return RevisionTree(self.repository, inv, revision_id)
1185.49.26 by John Arbash Meinel
Adding tests for remote sftp branches without working trees, plus a bugfix to allow push to still work with a warning.
977
        except (IndexError, NoSuchFile, NoWorkingTree), e:
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
978
            return self.repository.revision_tree(self.last_revision())
1185.33.59 by Martin Pool
[patch] keep a cached basis inventory (Johan Rydberg)
979
1 by mbp at sourcefrog
import from baz patch-364
980
    def working_tree(self):
1495.1.2 by Jelmer Vernooij
Move some generic methods of NativeBranch to Branch.
981
        """See Branch.working_tree."""
1185.2.2 by Lalo Martins
cleaning up and refactoring the branch module.
982
        from bzrlib.workingtree import WorkingTree
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
983
        from bzrlib.transport.local import LocalTransport
1534.4.28 by Robert Collins
first cut at merge from integration.
984
        if (self.base.find('://') != -1 or 
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
985
            not isinstance(self._transport, LocalTransport)):
1497 by Robert Collins
Move Branch.read_working_inventory to WorkingTree.
986
            raise NoWorkingTree(self.base)
1457.1.1 by Robert Collins
rather than getting the branch inventory, WorkingTree can use the whole Branch, or make its own.
987
        return WorkingTree(self.base, branch=self)
1 by mbp at sourcefrog
import from baz patch-364
988
1490 by Robert Collins
Implement a 'bzr push' command, with saved locations; update diff to return 1.
989
    @needs_write_lock
990
    def pull(self, source, overwrite=False):
1495.1.2 by Jelmer Vernooij
Move some generic methods of NativeBranch to Branch.
991
        """See Branch.pull."""
1490 by Robert Collins
Implement a 'bzr push' command, with saved locations; update diff to return 1.
992
        source.lock_read()
993
        try:
1185.33.44 by Martin Pool
[patch] show number of revisions pushed/pulled/merged (Robey Pointer)
994
            old_count = len(self.revision_history())
1490 by Robert Collins
Implement a 'bzr push' command, with saved locations; update diff to return 1.
995
            try:
996
                self.update_revisions(source)
997
            except DivergedBranches:
998
                if not overwrite:
999
                    raise
1185.50.5 by John Arbash Meinel
pull --overwrite should always overwrite, not just if diverged. (Test case from Robey Pointer)
1000
            if overwrite:
1490 by Robert Collins
Implement a 'bzr push' command, with saved locations; update diff to return 1.
1001
                self.set_revision_history(source.revision_history())
1185.33.44 by Martin Pool
[patch] show number of revisions pushed/pulled/merged (Robey Pointer)
1002
            new_count = len(self.revision_history())
1003
            return new_count - old_count
1490 by Robert Collins
Implement a 'bzr push' command, with saved locations; update diff to return 1.
1004
        finally:
1005
            source.unlock()
1 by mbp at sourcefrog
import from baz patch-364
1006
1149 by Martin Pool
- make get_parent() be a method of Branch; add simple tests for it
1007
    def get_parent(self):
1495.1.2 by Jelmer Vernooij
Move some generic methods of NativeBranch to Branch.
1008
        """See Branch.get_parent."""
1149 by Martin Pool
- make get_parent() be a method of Branch; add simple tests for it
1009
        import errno
1010
        _locs = ['parent', 'pull', 'x-pull']
1011
        for l in _locs:
1012
            try:
1185.65.29 by Robert Collins
Implement final review suggestions.
1013
                return self.control_files.get_utf8(l).read().strip('\n')
1185.31.45 by John Arbash Meinel
Refactoring Exceptions found some places where the wrong exception was caught.
1014
            except NoSuchFile:
1015
                pass
1149 by Martin Pool
- make get_parent() be a method of Branch; add simple tests for it
1016
        return None
1017
1490 by Robert Collins
Implement a 'bzr push' command, with saved locations; update diff to return 1.
1018
    def get_push_location(self):
1495.1.2 by Jelmer Vernooij
Move some generic methods of NativeBranch to Branch.
1019
        """See Branch.get_push_location."""
1490 by Robert Collins
Implement a 'bzr push' command, with saved locations; update diff to return 1.
1020
        config = bzrlib.config.BranchConfig(self)
1021
        push_loc = config.get_user_option('push_location')
1022
        return push_loc
1023
1024
    def set_push_location(self, location):
1495.1.2 by Jelmer Vernooij
Move some generic methods of NativeBranch to Branch.
1025
        """See Branch.set_push_location."""
1490 by Robert Collins
Implement a 'bzr push' command, with saved locations; update diff to return 1.
1026
        config = bzrlib.config.LocationConfig(self.base)
1027
        config.set_user_option('push_location', location)
1028
1442.1.63 by Robert Collins
Remove self.lock_*...finally: self.unlock() dead chickens from branch.py.
1029
    @needs_write_lock
1150 by Martin Pool
- add new Branch.set_parent and tests
1030
    def set_parent(self, url):
1495.1.2 by Jelmer Vernooij
Move some generic methods of NativeBranch to Branch.
1031
        """See Branch.set_parent."""
1150 by Martin Pool
- add new Branch.set_parent and tests
1032
        # TODO: Maybe delete old location files?
1185.65.29 by Robert Collins
Implement final review suggestions.
1033
        # URLs should never be unicode, even on the local fs,
1034
        # FIXUP this and get_parent in a future branch format bump:
1035
        # read and rewrite the file, and have the new format code read
1036
        # using .get not .get_utf8. RBC 20060125
1037
        self.control_files.put_utf8('parent', url + '\n')
1150 by Martin Pool
- add new Branch.set_parent and tests
1038
1185.35.11 by Aaron Bentley
Added support for branch nicks
1039
    def tree_config(self):
1040
        return TreeConfig(self)
1041
1185.66.8 by Aaron Bentley
Applied Jelmer's patch to make clone a branch operation
1042
    def _get_truncated_history(self, revision_id):
1043
        history = self.revision_history()
1044
        if revision_id is None:
1045
            return history
1046
        try:
1047
            idx = history.index(revision_id)
1048
        except ValueError:
1049
            raise InvalidRevisionId(revision_id=revision, branch=self)
1050
        return history[:idx+1]
1051
1052
    @needs_read_lock
1053
    def _clone_weave(self, to_location, revision=None, basis_branch=None):
1534.4.28 by Robert Collins
first cut at merge from integration.
1054
        # prevent leakage
1055
        from bzrlib.workingtree import WorkingTree
1185.66.8 by Aaron Bentley
Applied Jelmer's patch to make clone a branch operation
1056
        assert isinstance(to_location, basestring)
1057
        if basis_branch is not None:
1058
            note("basis_branch is not supported for fast weave copy yet.")
1059
1060
        history = self._get_truncated_history(revision)
1061
        if not bzrlib.osutils.lexists(to_location):
1062
            os.mkdir(to_location)
1063
        branch_to = Branch.initialize(to_location)
1064
        mutter("copy branch from %s to %s", self, branch_to)
1065
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
1066
        self.repository.copy(branch_to.repository)
974.1.54 by aaron.bentley at utoronto
Fixed the revno bug in log
1067
        
1185.65.15 by Robert Collins
Merge from integration.
1068
        # must be done *after* history is copied across
1069
        # FIXME duplicate code with base .clone().
1534.4.28 by Robert Collins
first cut at merge from integration.
1070
        # .. would template method be useful here?  RBC 20051207
1185.66.8 by Aaron Bentley
Applied Jelmer's patch to make clone a branch operation
1071
        branch_to.set_parent(self.base)
1185.65.15 by Robert Collins
Merge from integration.
1072
        branch_to.append_revision(*history)
1534.4.28 by Robert Collins
first cut at merge from integration.
1073
        # FIXME: this should be in workingtree.clone
1074
        WorkingTree.create(branch_to, to_location).set_root_id(self.get_root_id())
1185.66.8 by Aaron Bentley
Applied Jelmer's patch to make clone a branch operation
1075
        mutter("copied")
1076
        return branch_to
1077
1078
    def clone(self, to_location, revision=None, basis_branch=None, to_branch_type=None):
1534.4.28 by Robert Collins
first cut at merge from integration.
1079
        print "FIXME: clone via create and fetch is probably faster when versioned file comes in."
1185.66.8 by Aaron Bentley
Applied Jelmer's patch to make clone a branch operation
1080
        if to_branch_type is None:
1081
            to_branch_type = BzrBranch
1082
1083
        if to_branch_type == BzrBranch \
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
1084
            and self.repository.weave_store.listable() \
1085
            and self.repository.revision_store.listable():
1185.66.8 by Aaron Bentley
Applied Jelmer's patch to make clone a branch operation
1086
            return self._clone_weave(to_location, revision, basis_branch)
1087
1088
        return Branch.clone(self, to_location, revision, basis_branch, to_branch_type)
1185.35.11 by Aaron Bentley
Added support for branch nicks
1089
1185.64.2 by Goffredo Baroncelli
- implemented some suggestion by Robert Collins
1090
    def fileid_involved_between_revs(self, from_revid, to_revid):
1540.1.10 by John Arbash Meinel
PEP8 comment fixes, and spelling error fix.
1091
        """Find file_id(s) which are involved in the changes between revisions.
1092
1093
        This determines the set of revisions which are involved, and then
1094
        finds all file ids affected by those revisions.
1185.64.2 by Goffredo Baroncelli
- implemented some suggestion by Robert Collins
1095
        """
1540.1.8 by John Arbash Meinel
Add an assert that fileid_involved won't be used if the branch format hasn't been determined to work with it. And a TODO about what needs to be fixed for weave inclusions.
1096
        # TODO: jam 20060119 This code assumes that w.inclusions will
1097
        #       always be correct. But because of the presence of ghosts
1098
        #       it is possible to be wrong.
1099
        #       One specific example from Robert Collins:
1100
        #       Two branches, with revisions ABC, and AD
1101
        #       C is a ghost merge of D.
1102
        #       Inclusions doesn't recognize D as an ancestor.
1103
        #       If D is ever merged in the future, the weave
1104
        #       won't be fixed, because AD never saw revision C
1540.1.10 by John Arbash Meinel
PEP8 comment fixes, and spelling error fix.
1105
        #       to cause a conflict which would force a reweave.
1185.65.30 by Robert Collins
Merge integration.
1106
        w = self.repository.get_inventory_weave()
1185.64.2 by Goffredo Baroncelli
- implemented some suggestion by Robert Collins
1107
        from_set = set(w.inclusions([w.lookup(from_revid)]))
1108
        to_set = set(w.inclusions([w.lookup(to_revid)]))
1185.64.7 by Goffredo Baroncelli
added test for function fileid_involved
1109
        included = to_set.difference(from_set)
1534.1.11 by Robert Collins
Format tweaks for latest merges.
1110
        changed = map(w.idx_to_name, included)
1185.64.7 by Goffredo Baroncelli
added test for function fileid_involved
1111
        return self._fileid_involved_by_set(changed)
1185.64.2 by Goffredo Baroncelli
- implemented some suggestion by Robert Collins
1112
1113
    def fileid_involved(self, last_revid=None):
1540.1.10 by John Arbash Meinel
PEP8 comment fixes, and spelling error fix.
1114
        """Find all file_ids modified in the ancestry of last_revid.
1115
1116
        :param last_revid: If None, last_revision() will be used.
1185.64.2 by Goffredo Baroncelli
- implemented some suggestion by Robert Collins
1117
        """
1185.65.30 by Robert Collins
Merge integration.
1118
        w = self.repository.get_inventory_weave()
1185.64.2 by Goffredo Baroncelli
- implemented some suggestion by Robert Collins
1119
        if not last_revid:
1185.64.7 by Goffredo Baroncelli
added test for function fileid_involved
1120
            changed = set(w._names)
1185.64.2 by Goffredo Baroncelli
- implemented some suggestion by Robert Collins
1121
        else:
1185.64.7 by Goffredo Baroncelli
added test for function fileid_involved
1122
            included = w.inclusions([w.lookup(last_revid)])
1123
            changed = map(w.idx_to_name, included)
1124
        return self._fileid_involved_by_set(changed)
1185.64.2 by Goffredo Baroncelli
- implemented some suggestion by Robert Collins
1125
1126
    def fileid_involved_by_set(self, changes):
1540.1.10 by John Arbash Meinel
PEP8 comment fixes, and spelling error fix.
1127
        """Find all file_ids modified by the set of revisions passed in.
1128
1129
        :param changes: A set() of revision ids
1185.64.2 by Goffredo Baroncelli
- implemented some suggestion by Robert Collins
1130
        """
1540.1.10 by John Arbash Meinel
PEP8 comment fixes, and spelling error fix.
1131
        # TODO: jam 20060119 This line does *nothing*, remove it.
1132
        #       or better yet, change _fileid_involved_by_set so
1133
        #       that it takes the inventory weave, rather than
1134
        #       pulling it out by itself.
1185.65.30 by Robert Collins
Merge integration.
1135
        w = self.repository.get_inventory_weave()
1185.64.7 by Goffredo Baroncelli
added test for function fileid_involved
1136
        return self._fileid_involved_by_set(changes)
1137
1138
    def _fileid_involved_by_set(self, changes):
1540.1.10 by John Arbash Meinel
PEP8 comment fixes, and spelling error fix.
1139
        """Find the set of file-ids affected by the set of revisions.
1140
1141
        :param changes: A set() of revision ids.
1142
        :return: A set() of file ids.
1143
        
1144
        This peaks at the Weave, interpreting each line, looking to
1145
        see if it mentions one of the revisions. And if so, includes
1146
        the file id mentioned.
1147
        This expects both the Weave format, and the serialization
1148
        to have a single line per file/directory, and to have
1149
        fileid="" and revision="" on that line.
1150
        """
1534.4.19 by Robert Collins
merge from integration.
1151
        assert (isinstance(self._branch_format, BzrBranchFormat5) or
1152
                isinstance(self._branch_format, BzrBranchFormat6)), \
1540.1.8 by John Arbash Meinel
Add an assert that fileid_involved won't be used if the branch format hasn't been determined to work with it. And a TODO about what needs to be fixed for weave inclusions.
1153
            "fileid_involved only supported for branches which store inventory as xml"
1154
1185.65.30 by Robert Collins
Merge integration.
1155
        w = self.repository.get_inventory_weave()
1534.1.11 by Robert Collins
Format tweaks for latest merges.
1156
        file_ids = set()
1185.64.7 by Goffredo Baroncelli
added test for function fileid_involved
1157
        for line in w._weave:
1158
1159
            # it is ugly, but it is due to the weave structure
1534.1.11 by Robert Collins
Format tweaks for latest merges.
1160
            if not isinstance(line, basestring): continue
1185.64.7 by Goffredo Baroncelli
added test for function fileid_involved
1161
1162
            start = line.find('file_id="')+9
1163
            if start < 9: continue
1534.1.11 by Robert Collins
Format tweaks for latest merges.
1164
            end = line.find('"', start)
1185.64.7 by Goffredo Baroncelli
added test for function fileid_involved
1165
            assert end>= 0
1540.1.6 by John Arbash Meinel
fileid_involved needs to unescape the file id and revision id
1166
            file_id = xml.sax.saxutils.unescape(line[start:end])
1185.64.7 by Goffredo Baroncelli
added test for function fileid_involved
1167
1168
            # check if file_id is already present
1169
            if file_id in file_ids: continue
1170
1171
            start = line.find('revision="')+10
1172
            if start < 10: continue
1534.1.11 by Robert Collins
Format tweaks for latest merges.
1173
            end = line.find('"', start)
1185.64.7 by Goffredo Baroncelli
added test for function fileid_involved
1174
            assert end>= 0
1540.1.6 by John Arbash Meinel
fileid_involved needs to unescape the file id and revision id
1175
            revision_id = xml.sax.saxutils.unescape(line[start:end])
1185.64.7 by Goffredo Baroncelli
added test for function fileid_involved
1176
1177
            if revision_id in changes:
1185.64.2 by Goffredo Baroncelli
- implemented some suggestion by Robert Collins
1178
                file_ids.add(file_id)
1179
1180
        return file_ids
1185.64.1 by Goffredo Baroncelli
function file_involved added
1181
1185.69.2 by John Arbash Meinel
Changed LockableFiles to take the root directory directly. Moved mode information into LockableFiles instead of Branch
1182
1534.4.1 by Robert Collins
Allow parameterisation of the branch initialisation for bzrlib.
1183
Branch.set_default_initializer(BzrBranch._initialize)
1184
1185
1534.4.3 by Robert Collins
Implement BranchTestProviderAdapter, so tests now run across all branch formats.
1186
class BranchTestProviderAdapter(object):
1187
    """A tool to generate a suite testing multiple branch formats at once.
1188
1189
    This is done by copying the test once for each transport and injecting
1190
    the transport_server, transport_readonly_server, and branch_format
1191
    classes into each copy. Each copy is also given a new id() to make it
1192
    easy to identify.
1193
    """
1194
1195
    def __init__(self, transport_server, transport_readonly_server, formats):
1196
        self._transport_server = transport_server
1197
        self._transport_readonly_server = transport_readonly_server
1198
        self._formats = formats
1199
    
1200
    def adapt(self, test):
1201
        result = TestSuite()
1202
        for format in self._formats:
1203
            new_test = deepcopy(test)
1204
            new_test.transport_server = self._transport_server
1205
            new_test.transport_readonly_server = self._transport_readonly_server
1206
            new_test.branch_format = format
1207
            def make_new_test_id():
1208
                new_id = "%s(%s)" % (new_test.id(), format.__class__.__name__)
1209
                return lambda: new_id
1210
            new_test.id = make_new_test_id()
1211
            result.addTest(new_test)
1212
        return result
1213
1214
1495.1.5 by Jelmer Vernooij
Rename NativeBranch -> BzrBranch
1215
class ScratchBranch(BzrBranch):
1 by mbp at sourcefrog
import from baz patch-364
1216
    """Special test class: a branch that cleans up after itself.
1217
1218
    >>> b = ScratchBranch()
1219
    >>> isdir(b.base)
1220
    True
1221
    >>> bd = b.base
1185.69.2 by John Arbash Meinel
Changed LockableFiles to take the root directory directly. Moved mode information into LockableFiles instead of Branch
1222
    >>> b._transport.__del__()
1 by mbp at sourcefrog
import from baz patch-364
1223
    >>> isdir(bd)
1224
    False
1225
    """
1442.1.42 by Robert Collins
rebuild ScratchBranch on top of ScratchTransport
1226
1227
    def __init__(self, files=[], dirs=[], transport=None):
1 by mbp at sourcefrog
import from baz patch-364
1228
        """Make a test branch.
1229
1230
        This creates a temporary directory and runs init-tree in it.
1231
1232
        If any files are listed, they are created in the working copy.
1233
        """
1442.1.42 by Robert Collins
rebuild ScratchBranch on top of ScratchTransport
1234
        if transport is None:
1235
            transport = bzrlib.transport.local.ScratchTransport()
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
1236
            # local import for scope restriction
1237
            from bzrlib.workingtree import WorkingTree
1238
            WorkingTree.create_standalone(transport.base)
1534.4.6 by Robert Collins
Remove last uses of the init= parameter to BzrBranch.
1239
            super(ScratchBranch, self).__init__(transport)
1442.1.42 by Robert Collins
rebuild ScratchBranch on top of ScratchTransport
1240
        else:
1241
            super(ScratchBranch, self).__init__(transport)
1242
1185.69.2 by John Arbash Meinel
Changed LockableFiles to take the root directory directly. Moved mode information into LockableFiles instead of Branch
1243
        # BzrBranch creates a clone to .bzr and then forgets about the
1244
        # original transport. A ScratchTransport() deletes itself and
1245
        # everything underneath it when it goes away, so we need to
1246
        # grab a local copy to prevent that from happening
1247
        self._transport = transport
1248
100 by mbp at sourcefrog
- add test case for ignore files
1249
        for d in dirs:
1185.69.2 by John Arbash Meinel
Changed LockableFiles to take the root directory directly. Moved mode information into LockableFiles instead of Branch
1250
            self._transport.mkdir(d)
100 by mbp at sourcefrog
- add test case for ignore files
1251
            
1 by mbp at sourcefrog
import from baz patch-364
1252
        for f in files:
1185.69.2 by John Arbash Meinel
Changed LockableFiles to take the root directory directly. Moved mode information into LockableFiles instead of Branch
1253
            self._transport.put(f, 'content of %s' % f)
1 by mbp at sourcefrog
import from baz patch-364
1254
622 by Martin Pool
Updated merge patch from Aaron
1255
    def clone(self):
1256
        """
1257
        >>> orig = ScratchBranch(files=["file1", "file2"])
1185.69.2 by John Arbash Meinel
Changed LockableFiles to take the root directory directly. Moved mode information into LockableFiles instead of Branch
1258
        >>> os.listdir(orig.base)
1259
        [u'.bzr', u'file1', u'file2']
622 by Martin Pool
Updated merge patch from Aaron
1260
        >>> clone = orig.clone()
1185.1.40 by Robert Collins
Merge what applied of Alexander Belchenko's win32 patch.
1261
        >>> if os.name != 'nt':
1262
        ...   os.path.samefile(orig.base, clone.base)
1263
        ... else:
1264
        ...   orig.base == clone.base
1265
        ...
622 by Martin Pool
Updated merge patch from Aaron
1266
        False
1185.69.2 by John Arbash Meinel
Changed LockableFiles to take the root directory directly. Moved mode information into LockableFiles instead of Branch
1267
        >>> os.listdir(clone.base)
1268
        [u'.bzr', u'file1', u'file2']
622 by Martin Pool
Updated merge patch from Aaron
1269
        """
800 by Martin Pool
Merge John's import-speedup branch:
1270
        from shutil import copytree
1185.31.40 by John Arbash Meinel
Added osutils.mkdtemp()
1271
        from bzrlib.osutils import mkdtemp
800 by Martin Pool
Merge John's import-speedup branch:
1272
        base = mkdtemp()
622 by Martin Pool
Updated merge patch from Aaron
1273
        os.rmdir(base)
800 by Martin Pool
Merge John's import-speedup branch:
1274
        copytree(self.base, base, symlinks=True)
1442.1.42 by Robert Collins
rebuild ScratchBranch on top of ScratchTransport
1275
        return ScratchBranch(
1276
            transport=bzrlib.transport.local.ScratchTransport(base))
1 by mbp at sourcefrog
import from baz patch-364
1277
    
1278
1279
######################################################################
1280
# predicates
1281
1282
1283
def is_control_file(filename):
1284
    ## FIXME: better check
1185.31.38 by John Arbash Meinel
Changing os.path.normpath to osutils.normpath
1285
    filename = normpath(filename)
1 by mbp at sourcefrog
import from baz patch-364
1286
    while filename != '':
1287
        head, tail = os.path.split(filename)
1534.1.11 by Robert Collins
Format tweaks for latest merges.
1288
        ## mutter('check %r for control file' % ((head, tail),))
1 by mbp at sourcefrog
import from baz patch-364
1289
        if tail == bzrlib.BZRDIR:
1290
            return True
70 by mbp at sourcefrog
Prepare for smart recursive add.
1291
        if filename == head:
1292
            break
1 by mbp at sourcefrog
import from baz patch-364
1293
        filename = head
1294
    return False