~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
1185.76.1 by Erik BÃ¥gfors
Support for --revision in pull
337
    def pull(self, source, overwrite=False, stop_revision=None):
1495.1.2 by Jelmer Vernooij
Move some generic methods of NativeBranch to Branch.
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.7.154 by Aaron Bentley
Removed changes from bzr.ab 1529..1536
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
1185.76.1 by Erik BÃ¥gfors
Support for --revision in pull
936
974.1.75 by Aaron Bentley
Sped up pull by copying locally first
937
        if stop_revision is None:
1390 by Robert Collins
pair programming worx... merge integration and weave
938
            stop_revision = other.last_revision()
1185.12.44 by abentley
Restored branch convergence to bzr pull
939
        ### 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
940
        if (stop_revision is not None and 
941
            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
942
            return
1260 by Martin Pool
- some updates for fetch/update function
943
        greedy_fetch(to_branch=self, from_branch=other,
1261 by Martin Pool
- new method Branch.has_revision
944
                     revision=stop_revision)
1185.12.44 by abentley
Restored branch convergence to bzr pull
945
        pullable_revs = self.pullable_revisions(other, stop_revision)
1185.12.45 by abentley
Cleanups for pull
946
        if len(pullable_revs) > 0:
1261 by Martin Pool
- new method Branch.has_revision
947
            self.append_revision(*pullable_revs)
1185.12.44 by abentley
Restored branch convergence to bzr pull
948
949
    def pullable_revisions(self, other, stop_revision):
1495.1.2 by Jelmer Vernooij
Move some generic methods of NativeBranch to Branch.
950
        """See Branch.pullable_revisions."""
1185.12.44 by abentley
Restored branch convergence to bzr pull
951
        other_revno = other.revision_id_to_revno(stop_revision)
952
        try:
953
            return self.missing_revisions(other, other_revno)
954
        except DivergedBranches, e:
955
            try:
956
                pullable_revs = get_intervening_revisions(self.last_revision(),
1185.65.1 by Aaron Bentley
Refactored out ControlFiles and RevisionStore from _Branch
957
                                                          stop_revision, 
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
958
                                                          self.repository)
1185.12.44 by abentley
Restored branch convergence to bzr pull
959
                assert self.last_revision() not in pullable_revs
960
                return pullable_revs
961
            except bzrlib.errors.NotAncestor:
962
                if is_ancestor(self.last_revision(), stop_revision, self):
963
                    return []
964
                else:
965
                    raise e
966
        
1185.33.59 by Martin Pool
[patch] keep a cached basis inventory (Johan Rydberg)
967
    def basis_tree(self):
968
        """See Branch.basis_tree."""
969
        try:
970
            revision_id = self.revision_history()[-1]
1185.65.15 by Robert Collins
Merge from integration.
971
            # FIXME: This is an abstraction violation, the basis tree 
972
            # here as defined is on the working tree, the method should
973
            # be too. The basis tree for a branch can be different than
974
            # that for a working tree. RBC 20051207
1185.33.59 by Martin Pool
[patch] keep a cached basis inventory (Johan Rydberg)
975
            xml = self.working_tree().read_basis_inventory(revision_id)
976
            inv = bzrlib.xml5.serializer_v5.read_inventory_from_string(xml)
1185.65.17 by Robert Collins
Merge from integration, mode-changes are broken.
977
            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.
978
        except (IndexError, NoSuchFile, NoWorkingTree), e:
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
979
            return self.repository.revision_tree(self.last_revision())
1185.33.59 by Martin Pool
[patch] keep a cached basis inventory (Johan Rydberg)
980
1 by mbp at sourcefrog
import from baz patch-364
981
    def working_tree(self):
1495.1.2 by Jelmer Vernooij
Move some generic methods of NativeBranch to Branch.
982
        """See Branch.working_tree."""
1185.2.2 by Lalo Martins
cleaning up and refactoring the branch module.
983
        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.
984
        from bzrlib.transport.local import LocalTransport
1534.4.28 by Robert Collins
first cut at merge from integration.
985
        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.
986
            not isinstance(self._transport, LocalTransport)):
1497 by Robert Collins
Move Branch.read_working_inventory to WorkingTree.
987
            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.
988
        return WorkingTree(self.base, branch=self)
1 by mbp at sourcefrog
import from baz patch-364
989
1490 by Robert Collins
Implement a 'bzr push' command, with saved locations; update diff to return 1.
990
    @needs_write_lock
1185.76.1 by Erik BÃ¥gfors
Support for --revision in pull
991
    def pull(self, source, overwrite=False, stop_revision=None):
1495.1.2 by Jelmer Vernooij
Move some generic methods of NativeBranch to Branch.
992
        """See Branch.pull."""
1490 by Robert Collins
Implement a 'bzr push' command, with saved locations; update diff to return 1.
993
        source.lock_read()
994
        try:
1185.33.44 by Martin Pool
[patch] show number of revisions pushed/pulled/merged (Robey Pointer)
995
            old_count = len(self.revision_history())
1490 by Robert Collins
Implement a 'bzr push' command, with saved locations; update diff to return 1.
996
            try:
1185.76.1 by Erik BÃ¥gfors
Support for --revision in pull
997
                self.update_revisions(source,stop_revision)
1490 by Robert Collins
Implement a 'bzr push' command, with saved locations; update diff to return 1.
998
            except DivergedBranches:
999
                if not overwrite:
1000
                    raise
1185.50.5 by John Arbash Meinel
pull --overwrite should always overwrite, not just if diverged. (Test case from Robey Pointer)
1001
            if overwrite:
1490 by Robert Collins
Implement a 'bzr push' command, with saved locations; update diff to return 1.
1002
                self.set_revision_history(source.revision_history())
1185.33.44 by Martin Pool
[patch] show number of revisions pushed/pulled/merged (Robey Pointer)
1003
            new_count = len(self.revision_history())
1004
            return new_count - old_count
1490 by Robert Collins
Implement a 'bzr push' command, with saved locations; update diff to return 1.
1005
        finally:
1006
            source.unlock()
1 by mbp at sourcefrog
import from baz patch-364
1007
1149 by Martin Pool
- make get_parent() be a method of Branch; add simple tests for it
1008
    def get_parent(self):
1495.1.2 by Jelmer Vernooij
Move some generic methods of NativeBranch to Branch.
1009
        """See Branch.get_parent."""
1149 by Martin Pool
- make get_parent() be a method of Branch; add simple tests for it
1010
        import errno
1011
        _locs = ['parent', 'pull', 'x-pull']
1012
        for l in _locs:
1013
            try:
1185.65.29 by Robert Collins
Implement final review suggestions.
1014
                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.
1015
            except NoSuchFile:
1016
                pass
1149 by Martin Pool
- make get_parent() be a method of Branch; add simple tests for it
1017
        return None
1018
1490 by Robert Collins
Implement a 'bzr push' command, with saved locations; update diff to return 1.
1019
    def get_push_location(self):
1495.1.2 by Jelmer Vernooij
Move some generic methods of NativeBranch to Branch.
1020
        """See Branch.get_push_location."""
1490 by Robert Collins
Implement a 'bzr push' command, with saved locations; update diff to return 1.
1021
        config = bzrlib.config.BranchConfig(self)
1022
        push_loc = config.get_user_option('push_location')
1023
        return push_loc
1024
1025
    def set_push_location(self, location):
1495.1.2 by Jelmer Vernooij
Move some generic methods of NativeBranch to Branch.
1026
        """See Branch.set_push_location."""
1490 by Robert Collins
Implement a 'bzr push' command, with saved locations; update diff to return 1.
1027
        config = bzrlib.config.LocationConfig(self.base)
1028
        config.set_user_option('push_location', location)
1029
1442.1.63 by Robert Collins
Remove self.lock_*...finally: self.unlock() dead chickens from branch.py.
1030
    @needs_write_lock
1150 by Martin Pool
- add new Branch.set_parent and tests
1031
    def set_parent(self, url):
1495.1.2 by Jelmer Vernooij
Move some generic methods of NativeBranch to Branch.
1032
        """See Branch.set_parent."""
1150 by Martin Pool
- add new Branch.set_parent and tests
1033
        # TODO: Maybe delete old location files?
1185.65.29 by Robert Collins
Implement final review suggestions.
1034
        # URLs should never be unicode, even on the local fs,
1035
        # FIXUP this and get_parent in a future branch format bump:
1036
        # read and rewrite the file, and have the new format code read
1037
        # using .get not .get_utf8. RBC 20060125
1038
        self.control_files.put_utf8('parent', url + '\n')
1150 by Martin Pool
- add new Branch.set_parent and tests
1039
1185.35.11 by Aaron Bentley
Added support for branch nicks
1040
    def tree_config(self):
1041
        return TreeConfig(self)
1042
1185.66.8 by Aaron Bentley
Applied Jelmer's patch to make clone a branch operation
1043
    def _get_truncated_history(self, revision_id):
1044
        history = self.revision_history()
1045
        if revision_id is None:
1046
            return history
1047
        try:
1048
            idx = history.index(revision_id)
1049
        except ValueError:
1050
            raise InvalidRevisionId(revision_id=revision, branch=self)
1051
        return history[:idx+1]
1052
1053
    @needs_read_lock
1054
    def _clone_weave(self, to_location, revision=None, basis_branch=None):
1534.4.28 by Robert Collins
first cut at merge from integration.
1055
        # prevent leakage
1056
        from bzrlib.workingtree import WorkingTree
1185.66.8 by Aaron Bentley
Applied Jelmer's patch to make clone a branch operation
1057
        assert isinstance(to_location, basestring)
1058
        if basis_branch is not None:
1059
            note("basis_branch is not supported for fast weave copy yet.")
1060
1061
        history = self._get_truncated_history(revision)
1062
        if not bzrlib.osutils.lexists(to_location):
1063
            os.mkdir(to_location)
1064
        branch_to = Branch.initialize(to_location)
1065
        mutter("copy branch from %s to %s", self, branch_to)
1066
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
1067
        self.repository.copy(branch_to.repository)
974.1.54 by aaron.bentley at utoronto
Fixed the revno bug in log
1068
        
1185.65.15 by Robert Collins
Merge from integration.
1069
        # must be done *after* history is copied across
1070
        # FIXME duplicate code with base .clone().
1534.4.28 by Robert Collins
first cut at merge from integration.
1071
        # .. would template method be useful here?  RBC 20051207
1185.66.8 by Aaron Bentley
Applied Jelmer's patch to make clone a branch operation
1072
        branch_to.set_parent(self.base)
1185.65.15 by Robert Collins
Merge from integration.
1073
        branch_to.append_revision(*history)
1534.4.28 by Robert Collins
first cut at merge from integration.
1074
        # FIXME: this should be in workingtree.clone
1075
        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
1076
        mutter("copied")
1077
        return branch_to
1078
1079
    def clone(self, to_location, revision=None, basis_branch=None, to_branch_type=None):
1534.7.154 by Aaron Bentley
Removed changes from bzr.ab 1529..1536
1080
        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
1081
        if to_branch_type is None:
1082
            to_branch_type = BzrBranch
1083
1084
        if to_branch_type == BzrBranch \
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
1085
            and self.repository.weave_store.listable() \
1086
            and self.repository.revision_store.listable():
1185.66.8 by Aaron Bentley
Applied Jelmer's patch to make clone a branch operation
1087
            return self._clone_weave(to_location, revision, basis_branch)
1088
1089
        return Branch.clone(self, to_location, revision, basis_branch, to_branch_type)
1185.35.11 by Aaron Bentley
Added support for branch nicks
1090
1185.64.2 by Goffredo Baroncelli
- implemented some suggestion by Robert Collins
1091
    def fileid_involved_between_revs(self, from_revid, to_revid):
1540.1.10 by John Arbash Meinel
PEP8 comment fixes, and spelling error fix.
1092
        """Find file_id(s) which are involved in the changes between revisions.
1093
1094
        This determines the set of revisions which are involved, and then
1095
        finds all file ids affected by those revisions.
1185.64.2 by Goffredo Baroncelli
- implemented some suggestion by Robert Collins
1096
        """
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.
1097
        # TODO: jam 20060119 This code assumes that w.inclusions will
1098
        #       always be correct. But because of the presence of ghosts
1099
        #       it is possible to be wrong.
1100
        #       One specific example from Robert Collins:
1101
        #       Two branches, with revisions ABC, and AD
1102
        #       C is a ghost merge of D.
1103
        #       Inclusions doesn't recognize D as an ancestor.
1104
        #       If D is ever merged in the future, the weave
1105
        #       won't be fixed, because AD never saw revision C
1540.1.10 by John Arbash Meinel
PEP8 comment fixes, and spelling error fix.
1106
        #       to cause a conflict which would force a reweave.
1185.65.30 by Robert Collins
Merge integration.
1107
        w = self.repository.get_inventory_weave()
1185.64.2 by Goffredo Baroncelli
- implemented some suggestion by Robert Collins
1108
        from_set = set(w.inclusions([w.lookup(from_revid)]))
1109
        to_set = set(w.inclusions([w.lookup(to_revid)]))
1185.64.7 by Goffredo Baroncelli
added test for function fileid_involved
1110
        included = to_set.difference(from_set)
1534.1.11 by Robert Collins
Format tweaks for latest merges.
1111
        changed = map(w.idx_to_name, included)
1185.64.7 by Goffredo Baroncelli
added test for function fileid_involved
1112
        return self._fileid_involved_by_set(changed)
1185.64.2 by Goffredo Baroncelli
- implemented some suggestion by Robert Collins
1113
1114
    def fileid_involved(self, last_revid=None):
1540.1.10 by John Arbash Meinel
PEP8 comment fixes, and spelling error fix.
1115
        """Find all file_ids modified in the ancestry of last_revid.
1116
1117
        :param last_revid: If None, last_revision() will be used.
1185.64.2 by Goffredo Baroncelli
- implemented some suggestion by Robert Collins
1118
        """
1185.65.30 by Robert Collins
Merge integration.
1119
        w = self.repository.get_inventory_weave()
1185.64.2 by Goffredo Baroncelli
- implemented some suggestion by Robert Collins
1120
        if not last_revid:
1185.64.7 by Goffredo Baroncelli
added test for function fileid_involved
1121
            changed = set(w._names)
1185.64.2 by Goffredo Baroncelli
- implemented some suggestion by Robert Collins
1122
        else:
1185.64.7 by Goffredo Baroncelli
added test for function fileid_involved
1123
            included = w.inclusions([w.lookup(last_revid)])
1124
            changed = map(w.idx_to_name, included)
1125
        return self._fileid_involved_by_set(changed)
1185.64.2 by Goffredo Baroncelli
- implemented some suggestion by Robert Collins
1126
1127
    def fileid_involved_by_set(self, changes):
1540.1.10 by John Arbash Meinel
PEP8 comment fixes, and spelling error fix.
1128
        """Find all file_ids modified by the set of revisions passed in.
1129
1130
        :param changes: A set() of revision ids
1185.64.2 by Goffredo Baroncelli
- implemented some suggestion by Robert Collins
1131
        """
1540.1.10 by John Arbash Meinel
PEP8 comment fixes, and spelling error fix.
1132
        # TODO: jam 20060119 This line does *nothing*, remove it.
1133
        #       or better yet, change _fileid_involved_by_set so
1134
        #       that it takes the inventory weave, rather than
1135
        #       pulling it out by itself.
1185.65.30 by Robert Collins
Merge integration.
1136
        w = self.repository.get_inventory_weave()
1185.64.7 by Goffredo Baroncelli
added test for function fileid_involved
1137
        return self._fileid_involved_by_set(changes)
1138
1139
    def _fileid_involved_by_set(self, changes):
1540.1.10 by John Arbash Meinel
PEP8 comment fixes, and spelling error fix.
1140
        """Find the set of file-ids affected by the set of revisions.
1141
1142
        :param changes: A set() of revision ids.
1143
        :return: A set() of file ids.
1144
        
1145
        This peaks at the Weave, interpreting each line, looking to
1146
        see if it mentions one of the revisions. And if so, includes
1147
        the file id mentioned.
1148
        This expects both the Weave format, and the serialization
1149
        to have a single line per file/directory, and to have
1150
        fileid="" and revision="" on that line.
1151
        """
1534.4.19 by Robert Collins
merge from integration.
1152
        assert (isinstance(self._branch_format, BzrBranchFormat5) or
1153
                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.
1154
            "fileid_involved only supported for branches which store inventory as xml"
1155
1185.65.30 by Robert Collins
Merge integration.
1156
        w = self.repository.get_inventory_weave()
1534.1.11 by Robert Collins
Format tweaks for latest merges.
1157
        file_ids = set()
1185.64.7 by Goffredo Baroncelli
added test for function fileid_involved
1158
        for line in w._weave:
1159
1160
            # it is ugly, but it is due to the weave structure
1534.1.11 by Robert Collins
Format tweaks for latest merges.
1161
            if not isinstance(line, basestring): continue
1185.64.7 by Goffredo Baroncelli
added test for function fileid_involved
1162
1163
            start = line.find('file_id="')+9
1164
            if start < 9: continue
1534.1.11 by Robert Collins
Format tweaks for latest merges.
1165
            end = line.find('"', start)
1185.64.7 by Goffredo Baroncelli
added test for function fileid_involved
1166
            assert end>= 0
1540.1.6 by John Arbash Meinel
fileid_involved needs to unescape the file id and revision id
1167
            file_id = xml.sax.saxutils.unescape(line[start:end])
1185.64.7 by Goffredo Baroncelli
added test for function fileid_involved
1168
1169
            # check if file_id is already present
1170
            if file_id in file_ids: continue
1171
1172
            start = line.find('revision="')+10
1173
            if start < 10: continue
1534.1.11 by Robert Collins
Format tweaks for latest merges.
1174
            end = line.find('"', start)
1185.64.7 by Goffredo Baroncelli
added test for function fileid_involved
1175
            assert end>= 0
1540.1.6 by John Arbash Meinel
fileid_involved needs to unescape the file id and revision id
1176
            revision_id = xml.sax.saxutils.unescape(line[start:end])
1185.64.7 by Goffredo Baroncelli
added test for function fileid_involved
1177
1178
            if revision_id in changes:
1185.64.2 by Goffredo Baroncelli
- implemented some suggestion by Robert Collins
1179
                file_ids.add(file_id)
1180
1181
        return file_ids
1185.64.1 by Goffredo Baroncelli
function file_involved added
1182
1185.69.2 by John Arbash Meinel
Changed LockableFiles to take the root directory directly. Moved mode information into LockableFiles instead of Branch
1183
1534.4.1 by Robert Collins
Allow parameterisation of the branch initialisation for bzrlib.
1184
Branch.set_default_initializer(BzrBranch._initialize)
1185
1186
1534.4.3 by Robert Collins
Implement BranchTestProviderAdapter, so tests now run across all branch formats.
1187
class BranchTestProviderAdapter(object):
1188
    """A tool to generate a suite testing multiple branch formats at once.
1189
1190
    This is done by copying the test once for each transport and injecting
1191
    the transport_server, transport_readonly_server, and branch_format
1192
    classes into each copy. Each copy is also given a new id() to make it
1193
    easy to identify.
1194
    """
1195
1196
    def __init__(self, transport_server, transport_readonly_server, formats):
1197
        self._transport_server = transport_server
1198
        self._transport_readonly_server = transport_readonly_server
1199
        self._formats = formats
1200
    
1201
    def adapt(self, test):
1202
        result = TestSuite()
1203
        for format in self._formats:
1204
            new_test = deepcopy(test)
1205
            new_test.transport_server = self._transport_server
1206
            new_test.transport_readonly_server = self._transport_readonly_server
1207
            new_test.branch_format = format
1208
            def make_new_test_id():
1209
                new_id = "%s(%s)" % (new_test.id(), format.__class__.__name__)
1210
                return lambda: new_id
1211
            new_test.id = make_new_test_id()
1212
            result.addTest(new_test)
1213
        return result
1214
1215
1495.1.5 by Jelmer Vernooij
Rename NativeBranch -> BzrBranch
1216
class ScratchBranch(BzrBranch):
1 by mbp at sourcefrog
import from baz patch-364
1217
    """Special test class: a branch that cleans up after itself.
1218
1219
    >>> b = ScratchBranch()
1220
    >>> isdir(b.base)
1221
    True
1222
    >>> 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
1223
    >>> b._transport.__del__()
1 by mbp at sourcefrog
import from baz patch-364
1224
    >>> isdir(bd)
1225
    False
1226
    """
1442.1.42 by Robert Collins
rebuild ScratchBranch on top of ScratchTransport
1227
1228
    def __init__(self, files=[], dirs=[], transport=None):
1 by mbp at sourcefrog
import from baz patch-364
1229
        """Make a test branch.
1230
1231
        This creates a temporary directory and runs init-tree in it.
1232
1233
        If any files are listed, they are created in the working copy.
1234
        """
1442.1.42 by Robert Collins
rebuild ScratchBranch on top of ScratchTransport
1235
        if transport is None:
1236
            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.
1237
            # local import for scope restriction
1238
            from bzrlib.workingtree import WorkingTree
1239
            WorkingTree.create_standalone(transport.base)
1534.4.6 by Robert Collins
Remove last uses of the init= parameter to BzrBranch.
1240
            super(ScratchBranch, self).__init__(transport)
1442.1.42 by Robert Collins
rebuild ScratchBranch on top of ScratchTransport
1241
        else:
1242
            super(ScratchBranch, self).__init__(transport)
1243
1185.69.2 by John Arbash Meinel
Changed LockableFiles to take the root directory directly. Moved mode information into LockableFiles instead of Branch
1244
        # BzrBranch creates a clone to .bzr and then forgets about the
1245
        # original transport. A ScratchTransport() deletes itself and
1246
        # everything underneath it when it goes away, so we need to
1247
        # grab a local copy to prevent that from happening
1248
        self._transport = transport
1249
100 by mbp at sourcefrog
- add test case for ignore files
1250
        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
1251
            self._transport.mkdir(d)
100 by mbp at sourcefrog
- add test case for ignore files
1252
            
1 by mbp at sourcefrog
import from baz patch-364
1253
        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
1254
            self._transport.put(f, 'content of %s' % f)
1 by mbp at sourcefrog
import from baz patch-364
1255
622 by Martin Pool
Updated merge patch from Aaron
1256
    def clone(self):
1257
        """
1258
        >>> 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
1259
        >>> os.listdir(orig.base)
1260
        [u'.bzr', u'file1', u'file2']
622 by Martin Pool
Updated merge patch from Aaron
1261
        >>> clone = orig.clone()
1185.1.40 by Robert Collins
Merge what applied of Alexander Belchenko's win32 patch.
1262
        >>> if os.name != 'nt':
1263
        ...   os.path.samefile(orig.base, clone.base)
1264
        ... else:
1265
        ...   orig.base == clone.base
1266
        ...
622 by Martin Pool
Updated merge patch from Aaron
1267
        False
1185.69.2 by John Arbash Meinel
Changed LockableFiles to take the root directory directly. Moved mode information into LockableFiles instead of Branch
1268
        >>> os.listdir(clone.base)
1269
        [u'.bzr', u'file1', u'file2']
622 by Martin Pool
Updated merge patch from Aaron
1270
        """
800 by Martin Pool
Merge John's import-speedup branch:
1271
        from shutil import copytree
1185.31.40 by John Arbash Meinel
Added osutils.mkdtemp()
1272
        from bzrlib.osutils import mkdtemp
800 by Martin Pool
Merge John's import-speedup branch:
1273
        base = mkdtemp()
622 by Martin Pool
Updated merge patch from Aaron
1274
        os.rmdir(base)
800 by Martin Pool
Merge John's import-speedup branch:
1275
        copytree(self.base, base, symlinks=True)
1442.1.42 by Robert Collins
rebuild ScratchBranch on top of ScratchTransport
1276
        return ScratchBranch(
1277
            transport=bzrlib.transport.local.ScratchTransport(base))
1 by mbp at sourcefrog
import from baz patch-364
1278
    
1279
1280
######################################################################
1281
# predicates
1282
1283
1284
def is_control_file(filename):
1285
    ## FIXME: better check
1185.31.38 by John Arbash Meinel
Changing os.path.normpath to osutils.normpath
1286
    filename = normpath(filename)
1 by mbp at sourcefrog
import from baz patch-364
1287
    while filename != '':
1288
        head, tail = os.path.split(filename)
1534.1.11 by Robert Collins
Format tweaks for latest merges.
1289
        ## mutter('check %r for control file' % ((head, tail),))
1 by mbp at sourcefrog
import from baz patch-364
1290
        if tail == bzrlib.BZRDIR:
1291
            return True
70 by mbp at sourcefrog
Prepare for smart recursive add.
1292
        if filename == head:
1293
            break
1 by mbp at sourcefrog
import from baz patch-364
1294
        filename = head
1295
    return False