~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
1497 by Robert Collins
Move Branch.read_working_inventory to WorkingTree.
18
import shutil
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
19
import sys
20
import os
1371 by Martin Pool
- raise NotBranchError if format file can't be read
21
import errno
1372 by Martin Pool
- avoid converting inventories to/from StringIO
22
from warnings import warn
1393.2.1 by John Arbash Meinel
Merged in split-storage-2 branch. Need to cleanup a little bit more still.
23
from cStringIO import StringIO
1372 by Martin Pool
- avoid converting inventories to/from StringIO
24
1 by mbp at sourcefrog
import from baz patch-364
25
26
import bzrlib
800 by Martin Pool
Merge John's import-speedup branch:
27
from bzrlib.trace import mutter, note
1508.1.5 by Robert Collins
Move add from Branch to WorkingTree.
28
from bzrlib.osutils import (isdir, quotefn,
1390 by Robert Collins
pair programming worx... merge integration and weave
29
                            rename, splitpath, sha_file, appendpath, 
1185.16.70 by Martin Pool
- improved handling of non-ascii branch names and test
30
                            file_kind, abspath)
1417.1.6 by Robert Collins
introduce transactions for grouping actions done to and with branches
31
import bzrlib.errors as errors
1192 by Martin Pool
- clean up code for retrieving stored inventories
32
from bzrlib.errors import (BzrError, InvalidRevisionNumber, InvalidRevisionId,
1299 by Martin Pool
- tidy up imports
33
                           NoSuchRevision, HistoryMissing, NotBranchError,
1391 by Robert Collins
merge from integration
34
                           DivergedBranches, LockError, UnlistableStore,
1497 by Robert Collins
Move Branch.read_working_inventory to WorkingTree.
35
                           UnlistableBranch, NoSuchFile, NotVersionedError,
36
                           NoWorkingTree)
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
37
from bzrlib.textui import show_status
1185.65.10 by Robert Collins
Rename Controlfiles to LockableFiles.
38
from bzrlib.config import TreeConfig
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
39
from bzrlib.delta import compare_trees
1185.65.15 by Robert Collins
Merge from integration.
40
import bzrlib.inventory as inventory
1192 by Martin Pool
- clean up code for retrieving stored inventories
41
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.
42
from bzrlib.lockable_files import LockableFiles
43
from bzrlib.revision import (Revision, is_ancestor, get_intervening_revisions)
44
from bzrlib.repository import Repository
1393.2.1 by John Arbash Meinel
Merged in split-storage-2 branch. Need to cleanup a little bit more still.
45
from bzrlib.store import copy_all
1417.1.6 by Robert Collins
introduce transactions for grouping actions done to and with branches
46
import bzrlib.transactions as transactions
1393.2.4 by John Arbash Meinel
All tests pass.
47
from bzrlib.transport import Transport, get_transport
1185.65.15 by Robert Collins
Merge from integration.
48
from bzrlib.tree import EmptyTree, RevisionTree
1185.65.11 by Robert Collins
Disable inheritance for getting at LockableFiles, rather use composition.
49
import bzrlib.ui
1189 by Martin Pool
- BROKEN: partial support for commit into weave
50
import bzrlib.xml5
1104 by Martin Pool
- Add a simple UIFactory
51
1094 by Martin Pool
- merge aaron's merge improvements 999..1008
52
1186 by Martin Pool
- start implementing v5 format; Branch refuses to operate on old branches
53
BZR_BRANCH_FORMAT_4 = "Bazaar-NG branch, format 0.0.4\n"
54
BZR_BRANCH_FORMAT_5 = "Bazaar-NG branch, format 5\n"
1429 by Robert Collins
merge in niemeyers prefixed-store patch
55
BZR_BRANCH_FORMAT_6 = "Bazaar-NG branch, format 6\n"
1 by mbp at sourcefrog
import from baz patch-364
56
## TODO: Maybe include checks for common corruption of newlines, etc?
57
58
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
59
# TODO: Some operations like log might retrieve the same revisions
60
# repeatedly to calculate deltas.  We could perhaps have a weakref
1223 by Martin Pool
- store inventories in weave
61
# cache in memory to make this faster.  In general anything can be
62
# cached in memory between lock and unlock operations.
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
63
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
64
def find_branch(*ignored, **ignored_too):
65
    # XXX: leave this here for about one release, then remove it
66
    raise NotImplementedError('find_branch() is not supported anymore, '
67
                              'please use one of the new branch constructors')
416 by Martin Pool
- bzr log and bzr root now accept an http URL
68
1442.1.63 by Robert Collins
Remove self.lock_*...finally: self.unlock() dead chickens from branch.py.
69
70
def needs_read_lock(unbound):
71
    """Decorate unbound to take out and release a read lock."""
72
    def decorated(self, *args, **kwargs):
73
        self.lock_read()
74
        try:
75
            return unbound(self, *args, **kwargs)
76
        finally:
77
            self.unlock()
78
    return decorated
79
80
81
def needs_write_lock(unbound):
82
    """Decorate unbound to take out and release a write lock."""
83
    def decorated(self, *args, **kwargs):
84
        self.lock_write()
85
        try:
86
            return unbound(self, *args, **kwargs)
87
        finally:
88
            self.unlock()
89
    return decorated
90
1 by mbp at sourcefrog
import from baz patch-364
91
######################################################################
92
# branch objects
93
558 by Martin Pool
- All top-level classes inherit from object
94
class Branch(object):
1 by mbp at sourcefrog
import from baz patch-364
95
    """Branch holding a history of revisions.
96
343 by Martin Pool
doc
97
    base
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
98
        Base directory/url of the branch.
99
    """
100
    base = None
101
102
    def __init__(self, *ignored, **ignored_too):
103
        raise NotImplementedError('The Branch class is abstract')
104
105
    @staticmethod
1393.1.2 by Martin Pool
- better representation in Branch factories of opening old formats
106
    def open_downlevel(base):
107
        """Open a branch which may be of an old format.
108
        
109
        Only local branches are supported."""
1495.1.5 by Jelmer Vernooij
Rename NativeBranch -> BzrBranch
110
        return BzrBranch(get_transport(base), relax_version_check=True)
1393.1.2 by Martin Pool
- better representation in Branch factories of opening old formats
111
        
112
    @staticmethod
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
113
    def open(base):
114
        """Open an existing branch, rooted at 'base' (url)"""
1393.2.4 by John Arbash Meinel
All tests pass.
115
        t = get_transport(base)
1393.1.63 by Martin Pool
- add some trace statements
116
        mutter("trying to open %r with transport %r", base, t)
1495.1.5 by Jelmer Vernooij
Rename NativeBranch -> BzrBranch
117
        return BzrBranch(t)
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
118
119
    @staticmethod
1185.2.8 by Lalo Martins
creating the new branch constructors
120
    def open_containing(url):
1185.1.41 by Robert Collins
massive patch from Alexander Belchenko - many PEP8 fixes, removes unused function uuid
121
        """Open an existing branch which contains url.
122
        
123
        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
124
125
        Basically we keep looking up until we find the control directory or
126
        run into the root.  If there isn't one, raises NotBranchError.
1442.1.64 by Robert Collins
Branch.open_containing now returns a tuple (Branch, relative-path).
127
        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.
128
        """
1393.2.4 by John Arbash Meinel
All tests pass.
129
        t = get_transport(url)
1185.17.2 by Martin Pool
[pick] avoid problems in fetching when .bzr is not listable
130
        while True:
131
            try:
1495.1.5 by Jelmer Vernooij
Rename NativeBranch -> BzrBranch
132
                return BzrBranch(t), t.relpath(url)
1185.17.2 by Martin Pool
[pick] avoid problems in fetching when .bzr is not listable
133
            except NotBranchError:
134
                pass
135
            new_t = t.clone('..')
136
            if new_t.base == t.base:
137
                # reached the root, whatever that may be
1185.16.61 by mbp at sourcefrog
- start introducing hct error classes
138
                raise NotBranchError(path=url)
1185.17.2 by Martin Pool
[pick] avoid problems in fetching when .bzr is not listable
139
            t = new_t
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
140
141
    @staticmethod
142
    def initialize(base):
143
        """Create a new branch, rooted at 'base' (url)"""
1185.65.15 by Robert Collins
Merge from integration.
144
        t = get_transport(unicode(base))
1495.1.5 by Jelmer Vernooij
Rename NativeBranch -> BzrBranch
145
        return BzrBranch(t, init=True)
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
146
147
    def setup_caching(self, cache_root):
148
        """Subclasses that care about caching should override this, and set
149
        up cached stores located under cache_root.
150
        """
1400.1.1 by Robert Collins
implement a basic test for the ui branch command from http servers
151
        self.cache_root = cache_root
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
152
1185.35.11 by Aaron Bentley
Added support for branch nicks
153
    def _get_nick(self):
154
        cfg = self.tree_config()
155
        return cfg.get_option(u"nickname", default=self.base.split('/')[-1])
156
157
    def _set_nick(self, nick):
158
        cfg = self.tree_config()
159
        cfg.set_option(nick, "nickname")
160
        assert cfg.get_option("nickname") == nick
161
162
    nick = property(_get_nick, _set_nick)
163
        
1495.1.2 by Jelmer Vernooij
Move some generic methods of NativeBranch to Branch.
164
    def push_stores(self, branch_to):
165
        """Copy the content of this branches store to branch_to."""
166
        raise NotImplementedError('push_stores is abstract')
167
168
    def lock_write(self):
169
        raise NotImplementedError('lock_write is abstract')
170
        
171
    def lock_read(self):
172
        raise NotImplementedError('lock_read is abstract')
173
174
    def unlock(self):
175
        raise NotImplementedError('unlock is abstract')
176
177
    def abspath(self, name):
178
        """Return absolute filename for something in the branch
179
        
180
        XXX: Robert Collins 20051017 what is this used for? why is it a branch
181
        method and not a tree method.
182
        """
183
        raise NotImplementedError('abspath is abstract')
184
185
    def get_root_id(self):
186
        """Return the id of this branches root"""
187
        raise NotImplementedError('get_root_id is abstract')
188
1185.50.9 by John Arbash Meinel
[bug 3632] Matthieu Moy- bzr cat should default to last revision
189
    def print_file(self, file, revision_id):
1495.1.2 by Jelmer Vernooij
Move some generic methods of NativeBranch to Branch.
190
        """Print `file` to stdout."""
191
        raise NotImplementedError('print_file is abstract')
192
193
    def append_revision(self, *revision_ids):
194
        raise NotImplementedError('append_revision is abstract')
195
196
    def set_revision_history(self, rev_history):
197
        raise NotImplementedError('set_revision_history is abstract')
198
199
    def revision_history(self):
200
        """Return sequence of revision hashes on to this branch."""
201
        raise NotImplementedError('revision_history is abstract')
202
203
    def revno(self):
204
        """Return current revision number for this branch.
205
206
        That is equivalent to the number of revisions committed to
207
        this branch.
208
        """
209
        return len(self.revision_history())
210
211
    def last_revision(self):
212
        """Return last patch hash, or None if no history."""
213
        ph = self.revision_history()
214
        if ph:
215
            return ph[-1]
216
        else:
217
            return None
218
219
    def missing_revisions(self, other, stop_revision=None, diverged_ok=False):
220
        """Return a list of new revisions that would perfectly fit.
221
        
222
        If self and other have not diverged, return a list of the revisions
223
        present in other, but missing from self.
224
225
        >>> from bzrlib.commit import commit
226
        >>> bzrlib.trace.silent = True
227
        >>> br1 = ScratchBranch()
228
        >>> br2 = ScratchBranch()
229
        >>> br1.missing_revisions(br2)
230
        []
231
        >>> commit(br2, "lala!", rev_id="REVISION-ID-1")
232
        >>> br1.missing_revisions(br2)
233
        [u'REVISION-ID-1']
234
        >>> br2.missing_revisions(br1)
235
        []
236
        >>> commit(br1, "lala!", rev_id="REVISION-ID-1")
237
        >>> br1.missing_revisions(br2)
238
        []
239
        >>> commit(br2, "lala!", rev_id="REVISION-ID-2A")
240
        >>> br1.missing_revisions(br2)
241
        [u'REVISION-ID-2A']
242
        >>> commit(br1, "lala!", rev_id="REVISION-ID-2B")
243
        >>> br1.missing_revisions(br2)
244
        Traceback (most recent call last):
245
        DivergedBranches: These branches have diverged.
246
        """
247
        self_history = self.revision_history()
248
        self_len = len(self_history)
249
        other_history = other.revision_history()
250
        other_len = len(other_history)
251
        common_index = min(self_len, other_len) -1
252
        if common_index >= 0 and \
253
            self_history[common_index] != other_history[common_index]:
254
            raise DivergedBranches(self, other)
255
256
        if stop_revision is None:
257
            stop_revision = other_len
258
        else:
259
            assert isinstance(stop_revision, int)
260
            if stop_revision > other_len:
261
                raise bzrlib.errors.NoSuchRevision(self, stop_revision)
262
        return other_history[self_len:stop_revision]
1185.66.1 by Aaron Bentley
Merged from mainline
263
1495.1.2 by Jelmer Vernooij
Move some generic methods of NativeBranch to Branch.
264
    
265
    def update_revisions(self, other, stop_revision=None):
266
        """Pull in new perfect-fit revisions."""
267
        raise NotImplementedError('update_revisions is abstract')
268
269
    def pullable_revisions(self, other, stop_revision):
270
        raise NotImplementedError('pullable_revisions is abstract')
271
        
272
    def revision_id_to_revno(self, revision_id):
273
        """Given a revision id, return its revno"""
274
        if revision_id is None:
275
            return 0
276
        history = self.revision_history()
277
        try:
278
            return history.index(revision_id) + 1
279
        except ValueError:
280
            raise bzrlib.errors.NoSuchRevision(self, revision_id)
281
282
    def get_rev_id(self, revno, history=None):
283
        """Find the revision id of the specified revno."""
284
        if revno == 0:
285
            return None
286
        if history is None:
287
            history = self.revision_history()
288
        elif revno <= 0 or revno > len(history):
289
            raise bzrlib.errors.NoSuchRevision(self, revno)
290
        return history[revno - 1]
291
292
    def working_tree(self):
1508.1.15 by Robert Collins
Merge from mpool.
293
        """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.
294
        raise NotImplementedError('working_tree is abstract')
295
296
    def pull(self, source, overwrite=False):
297
        raise NotImplementedError('pull is abstract')
298
299
    def basis_tree(self):
300
        """Return `Tree` object for last revision.
301
302
        If there are no revisions yet, return an `EmptyTree`.
303
        """
1185.66.1 by Aaron Bentley
Merged from mainline
304
        return self.storage.revision_tree(self.last_revision())
1495.1.2 by Jelmer Vernooij
Move some generic methods of NativeBranch to Branch.
305
306
    def rename_one(self, from_rel, to_rel):
307
        """Rename one file.
308
309
        This can change the directory or the filename or both.
310
        """
311
        raise NotImplementedError('rename_one is abstract')
312
313
    def move(self, from_paths, to_name):
314
        """Rename files.
315
316
        to_name must exist as a versioned directory.
317
318
        If to_name exists and is a directory, the files are moved into
319
        it, keeping their old names.  If it is a directory, 
320
321
        Note that to_name is only the last component of the new name;
322
        this doesn't change the directory.
323
324
        This returns a list of (from_path, to_path) pairs for each
325
        entry that is moved.
326
        """
327
        raise NotImplementedError('move is abstract')
328
329
    def get_parent(self):
330
        """Return the parent location of the branch.
331
332
        This is the default location for push/pull/missing.  The usual
333
        pattern is that the user can override it by specifying a
334
        location.
335
        """
336
        raise NotImplementedError('get_parent is abstract')
337
338
    def get_push_location(self):
339
        """Return the None or the location to push this branch to."""
340
        raise NotImplementedError('get_push_location is abstract')
341
342
    def set_push_location(self, location):
343
        """Set a new push location for this branch."""
344
        raise NotImplementedError('set_push_location is abstract')
345
346
    def set_parent(self, url):
347
        raise NotImplementedError('set_parent is abstract')
348
349
    def check_revno(self, revno):
350
        """\
351
        Check whether a revno corresponds to any revision.
352
        Zero (the NULL revision) is considered valid.
353
        """
354
        if revno != 0:
355
            self.check_real_revno(revno)
356
            
357
    def check_real_revno(self, revno):
358
        """\
359
        Check whether a revno corresponds to a real revision.
360
        Zero (the NULL revision) is considered invalid
361
        """
362
        if revno < 1 or revno > self.revno():
363
            raise InvalidRevisionNumber(revno)
364
        
365
    def sign_revision(self, revision_id, gpg_strategy):
366
        raise NotImplementedError('sign_revision is abstract')
367
368
    def store_revision_signature(self, gpg_strategy, plaintext, revision_id):
369
        raise NotImplementedError('store_revision_signature is abstract')
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
370
1185.66.8 by Aaron Bentley
Applied Jelmer's patch to make clone a branch operation
371
    def clone(self, to_location, revision=None, basis_branch=None, to_branch_type=None):
372
        """Copy this branch into the existing directory to_location.
373
374
        Returns the newly created branch object.
375
376
        revision
377
            If not None, only revisions up to this point will be copied.
378
            The head of the new branch will be that revision.  Must be a
379
            revid or None.
380
    
381
        to_location -- The destination directory; must either exist and be 
382
            empty, or not exist, in which case it is created.
383
    
384
        basis_branch
385
            A local branch to copy revisions from, related to this branch. 
386
            This is used when branching from a remote (slow) branch, and we have
387
            a local branch that might contain some relevant revisions.
388
    
389
        to_branch_type
390
            Branch type of destination branch
391
        """
392
        assert isinstance(to_location, basestring)
393
        if not bzrlib.osutils.lexists(to_location):
394
            os.mkdir(to_location)
395
        if to_branch_type is None:
396
            to_branch_type = BzrBranch
397
        br_to = to_branch_type.initialize(to_location)
398
        mutter("copy branch from %s to %s", self, br_to)
399
        if basis_branch is not None:
400
            basis_branch.push_stores(br_to)
401
        br_to.working_tree().set_root_id(self.get_root_id())
402
        if revision is None:
403
            revision = self.last_revision()
404
        br_to.update_revisions(self, stop_revision=revision)
405
        br_to.set_parent(self.base)
1185.65.15 by Robert Collins
Merge from integration.
406
        # circular import protection
407
        from bzrlib.merge import build_working_dir
408
        build_working_dir(to_location)
1185.66.8 by Aaron Bentley
Applied Jelmer's patch to make clone a branch operation
409
        mutter("copied")
410
        return br_to
1185.66.1 by Aaron Bentley
Merged from mainline
411
1495.1.5 by Jelmer Vernooij
Rename NativeBranch -> BzrBranch
412
class BzrBranch(Branch):
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
413
    """A branch stored in the actual filesystem.
414
415
    Note that it's "local" in the context of the filesystem; it doesn't
416
    really matter if it's on an nfs/smb/afs/coda/... share, as long as
417
    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,
418
1 by mbp at sourcefrog
import from baz patch-364
419
    """
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
420
    # We actually expect this class to be somewhat short-lived; part of its
421
    # purpose is to try to isolate what bits of the branch logic are tied to
422
    # filesystem access, so that in a later step, we can extricate them to
423
    # a separarte ("storage") class.
1223 by Martin Pool
- store inventories in weave
424
    _inventory_weave = None
353 by Martin Pool
- Per-branch locks in read and write modes.
425
    
897 by Martin Pool
- merge john's revision-naming code
426
    # Map some sort of prefix into a namespace
427
    # stuff like "revno:10", "revid:", etc.
428
    # This should match a prefix with a function which accepts
429
    REVISION_NAMESPACES = {}
430
1391 by Robert Collins
merge from integration
431
    def push_stores(self, branch_to):
1495.1.2 by Jelmer Vernooij
Move some generic methods of NativeBranch to Branch.
432
        """See Branch.push_stores."""
1391 by Robert Collins
merge from integration
433
        if (self._branch_format != branch_to._branch_format
434
            or self._branch_format != 4):
435
            from bzrlib.fetch import greedy_fetch
1393 by Robert Collins
reenable remotebranch tests
436
            mutter("falling back to fetch logic to push between %s(%s) and %s(%s)",
437
                   self, self._branch_format, branch_to, branch_to._branch_format)
1391 by Robert Collins
merge from integration
438
            greedy_fetch(to_branch=branch_to, from_branch=self,
439
                         revision=self.last_revision())
440
            return
441
442
        store_pairs = ((self.text_store,      branch_to.text_store),
443
                       (self.inventory_store, branch_to.inventory_store),
444
                       (self.revision_store,  branch_to.revision_store))
445
        try:
446
            for from_store, to_store in store_pairs: 
447
                copy_all(from_store, to_store)
448
        except UnlistableStore:
449
            raise UnlistableBranch(from_store)
450
1393.2.1 by John Arbash Meinel
Merged in split-storage-2 branch. Need to cleanup a little bit more still.
451
    def __init__(self, transport, init=False,
1293 by Martin Pool
- add Branch constructor option to relax version check
452
                 relax_version_check=False):
1 by mbp at sourcefrog
import from baz patch-364
453
        """Create new branch object at a particular location.
454
907.1.2 by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport.
455
        transport -- A Transport object, defining how to access files.
62 by mbp at sourcefrog
- new find_branch_root function; based on suggestion from aaron
456
        
254 by Martin Pool
- Doc cleanups from Magnus Therning
457
        init -- If True, create new control files in a previously
1 by mbp at sourcefrog
import from baz patch-364
458
             unversioned directory.  If False, the branch must already
459
             be versioned.
460
1293 by Martin Pool
- add Branch constructor option to relax version check
461
        relax_version_check -- If true, the usual check for the branch
462
            version is not applied.  This is intended only for
463
            upgrade/recovery type use; it's not guaranteed that
464
            all operations will work on old format branches.
465
1 by mbp at sourcefrog
import from baz patch-364
466
        In the test suite, creation of new trees is tested using the
467
        `ScratchBranch` class.
468
        """
1393.1.15 by Martin Pool
- better assertion message
469
        assert isinstance(transport, Transport), \
470
            "%r is not a Transport" % transport
1185.65.11 by Robert Collins
Disable inheritance for getting at LockableFiles, rather use composition.
471
        self.control_files = LockableFiles(transport, 'branch-lock')
1 by mbp at sourcefrog
import from baz patch-364
472
        if init:
473
            self._make_control()
1293 by Martin Pool
- add Branch constructor option to relax version check
474
        self._check_format(relax_version_check)
1185.66.5 by Aaron Bentley
Renamed RevisionStorage to Repository
475
        self.storage = Repository(transport, self._branch_format)
1 by mbp at sourcefrog
import from baz patch-364
476
477
    def __str__(self):
1185.65.11 by Robert Collins
Disable inheritance for getting at LockableFiles, rather use composition.
478
        return '%s(%r)' % (self.__class__.__name__, self.base)
1 by mbp at sourcefrog
import from baz patch-364
479
480
    __repr__ = __str__
481
578 by Martin Pool
- start to move toward Branch.lock and unlock methods,
482
    def __del__(self):
907.1.23 by John Arbash Meinel
Branch objects now automatically create Cached stores if the protocol is_remote.
483
        # TODO: It might be best to do this somewhere else,
484
        # but it is nice for a Branch object to automatically
485
        # cache it's information.
486
        # Alternatively, we could have the Transport objects cache requests
487
        # See the earlier discussion about how major objects (like Branch)
488
        # should never expect their __del__ function to run.
1185.11.9 by John Arbash Meinel
Most tests pass, some problems with unavailable socket recv
489
        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.
490
            try:
491
                shutil.rmtree(self.cache_root)
492
            except:
493
                pass
494
            self.cache_root = None
495
907.1.17 by John Arbash Meinel
Adding a Branch.base property, removing pull_loc()
496
    def _get_base(self):
1185.65.11 by Robert Collins
Disable inheritance for getting at LockableFiles, rather use composition.
497
        if self.control_files._transport:
498
            return self.control_files._transport.base
907.1.19 by John Arbash Meinel
Updated ScratchBranch and Branch.base, All Tests PASS !!!
499
        return None
907.1.17 by John Arbash Meinel
Adding a Branch.base property, removing pull_loc()
500
1442.1.5 by Robert Collins
Give branch.base a docstring.
501
    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,
502
1417.1.6 by Robert Collins
introduce transactions for grouping actions done to and with branches
503
    def _finish_transaction(self):
504
        """Exit the current transaction."""
1185.65.13 by Robert Collins
Merge from integration
505
        return self.control_files._finish_transaction()
1417.1.6 by Robert Collins
introduce transactions for grouping actions done to and with branches
506
507
    def get_transaction(self):
1185.65.13 by Robert Collins
Merge from integration
508
        """Return the current active transaction.
509
510
        If no transaction is active, this returns a passthrough object
511
        for which all data is immediately flushed and no caching happens.
512
        """
513
        # this is an explicit function so that we can do tricky stuff
514
        # when the storage in rev_storage is elsewhere.
515
        # we probably need to hook the two 'lock a location' and 
516
        # 'have a transaction' together more delicately, so that
517
        # we can have two locks (branch and storage) and one transaction
518
        # ... and finishing the transaction unlocks both, but unlocking
519
        # does not. - RBC 20051121
520
        return self.control_files.get_transaction()
521
522
    def _set_transaction(self, transaction):
1417.1.6 by Robert Collins
introduce transactions for grouping actions done to and with branches
523
        """Set a new active transaction."""
1185.65.13 by Robert Collins
Merge from integration
524
        return self.control_files._set_transaction(transaction)
353 by Martin Pool
- Per-branch locks in read and write modes.
525
67 by mbp at sourcefrog
use abspath() for the function that makes an absolute
526
    def abspath(self, name):
1495.1.2 by Jelmer Vernooij
Move some generic methods of NativeBranch to Branch.
527
        """See Branch.abspath."""
1185.65.11 by Robert Collins
Disable inheritance for getting at LockableFiles, rather use composition.
528
        return self.control_files._transport.abspath(name)
67 by mbp at sourcefrog
use abspath() for the function that makes an absolute
529
1 by mbp at sourcefrog
import from baz patch-364
530
    def _make_control(self):
800 by Martin Pool
Merge John's import-speedup branch:
531
        from bzrlib.inventory import Inventory
1393.2.2 by John Arbash Meinel
Updated stores to use Transport
532
        from bzrlib.weavefile import write_weave_v5
533
        from bzrlib.weave import Weave
802 by Martin Pool
- Remove XMLMixin class in favour of simple pack_xml, unpack_xml functions
534
        
1185.11.1 by John Arbash Meinel
(broken) Transport work is merged in. Tests do not pass yet.
535
        # Create an empty inventory
907.1.47 by John Arbash Meinel
Created mkdir_multi, modified branch to use _multi forms when initializing a branch, creating a full test routine for transports
536
        sio = StringIO()
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
537
        # if we want per-tree root ids then this is the place to set
538
        # them; they're not needed for now and so ommitted for
539
        # simplicity.
1393.2.1 by John Arbash Meinel
Merged in split-storage-2 branch. Need to cleanup a little bit more still.
540
        bzrlib.xml5.serializer_v5.write_inventory(Inventory(), sio)
1393.2.2 by John Arbash Meinel
Updated stores to use Transport
541
        empty_inv = sio.getvalue()
542
        sio = StringIO()
543
        bzrlib.weavefile.write_weave_v5(Weave(), sio)
544
        empty_weave = sio.getvalue()
907.1.47 by John Arbash Meinel
Created mkdir_multi, modified branch to use _multi forms when initializing a branch, creating a full test routine for transports
545
1393.2.1 by John Arbash Meinel
Merged in split-storage-2 branch. Need to cleanup a little bit more still.
546
        dirs = [[], 'revision-store', 'weaves']
907.1.47 by John Arbash Meinel
Created mkdir_multi, modified branch to use _multi forms when initializing a branch, creating a full test routine for transports
547
        files = [('README', 
1 by mbp at sourcefrog
import from baz patch-364
548
            "This is a Bazaar-NG control directory.\n"
907.1.47 by John Arbash Meinel
Created mkdir_multi, modified branch to use _multi forms when initializing a branch, creating a full test routine for transports
549
            "Do not change any files in this directory.\n"),
1429 by Robert Collins
merge in niemeyers prefixed-store patch
550
            ('branch-format', BZR_BRANCH_FORMAT_6),
907.1.47 by John Arbash Meinel
Created mkdir_multi, modified branch to use _multi forms when initializing a branch, creating a full test routine for transports
551
            ('revision-history', ''),
552
            ('branch-name', ''),
553
            ('branch-lock', ''),
554
            ('pending-merges', ''),
1393.2.2 by John Arbash Meinel
Updated stores to use Transport
555
            ('inventory', empty_inv),
556
            ('inventory.weave', empty_weave),
557
            ('ancestry.weave', empty_weave)
907.1.47 by John Arbash Meinel
Created mkdir_multi, modified branch to use _multi forms when initializing a branch, creating a full test routine for transports
558
        ]
1185.65.11 by Robert Collins
Disable inheritance for getting at LockableFiles, rather use composition.
559
        cfn = self.control_files._rel_controlfilename
560
        self.control_files._transport.mkdir_multi([cfn(d) for d in dirs])
1185.65.12 by Robert Collins
Remove the only-used-once put_controlfiles, and change put_controlfile to put and put_utf8.
561
        for file, content in files:
562
            self.control_files.put_utf8(file, content)
1185.65.11 by Robert Collins
Disable inheritance for getting at LockableFiles, rather use composition.
563
        mutter('created control directory in ' + self.base)
802 by Martin Pool
- Remove XMLMixin class in favour of simple pack_xml, unpack_xml functions
564
1293 by Martin Pool
- add Branch constructor option to relax version check
565
    def _check_format(self, relax_version_check):
1 by mbp at sourcefrog
import from baz patch-364
566
        """Check this branch format is supported.
567
1187 by Martin Pool
- improved check for branch version
568
        The format level is stored, as an integer, in
569
        self._branch_format for code that needs to check it later.
1 by mbp at sourcefrog
import from baz patch-364
570
571
        In the future, we might need different in-memory Branch
572
        classes to support downlevel branches.  But not yet.
163 by mbp at sourcefrog
merge win32 portability fixes
573
        """
1185.11.9 by John Arbash Meinel
Most tests pass, some problems with unavailable socket recv
574
        try:
1185.65.11 by Robert Collins
Disable inheritance for getting at LockableFiles, rather use composition.
575
            fmt = self.control_files.controlfile('branch-format', 'r').read()
1185.11.9 by John Arbash Meinel
Most tests pass, some problems with unavailable socket recv
576
        except NoSuchFile:
1185.16.61 by mbp at sourcefrog
- start introducing hct error classes
577
            raise NotBranchError(path=self.base)
1393.1.63 by Martin Pool
- add some trace statements
578
        mutter("got branch format %r", fmt)
1429 by Robert Collins
merge in niemeyers prefixed-store patch
579
        if fmt == BZR_BRANCH_FORMAT_6:
580
            self._branch_format = 6
581
        elif fmt == BZR_BRANCH_FORMAT_5:
1187 by Martin Pool
- improved check for branch version
582
            self._branch_format = 5
1294 by Martin Pool
- refactor branch version detection
583
        elif fmt == BZR_BRANCH_FORMAT_4:
584
            self._branch_format = 4
585
586
        if (not relax_version_check
1429 by Robert Collins
merge in niemeyers prefixed-store patch
587
            and self._branch_format not in (5, 6)):
1185.1.53 by Robert Collins
raise a specific error on unsupported branches so that they can be distinguished from generic errors
588
            raise errors.UnsupportedFormatError(
589
                           'sorry, branch format %r not supported' % fmt,
576 by Martin Pool
- raise exceptions rather than using bailout()
590
                           ['use a different bzr version',
1393.2.1 by John Arbash Meinel
Merged in split-storage-2 branch. Need to cleanup a little bit more still.
591
                            'or remove the .bzr directory'
592
                            ' and "bzr init" again'])
907.1.2 by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport.
593
1508.1.15 by Robert Collins
Merge from mpool.
594
    @needs_read_lock
909 by Martin Pool
- merge John's code to give the tree root an explicit file id
595
    def get_root_id(self):
1495.1.2 by Jelmer Vernooij
Move some generic methods of NativeBranch to Branch.
596
        """See Branch.get_root_id."""
1185.65.1 by Aaron Bentley
Refactored out ControlFiles and RevisionStore from _Branch
597
        inv = self.storage.get_inventory(self.last_revision())
909 by Martin Pool
- merge John's code to give the tree root an explicit file id
598
        return inv.root.file_id
1 by mbp at sourcefrog
import from baz patch-364
599
1185.65.3 by Aaron Bentley
Fixed locking-- all tests pass
600
    def lock_write(self):
1185.65.11 by Robert Collins
Disable inheritance for getting at LockableFiles, rather use composition.
601
        # TODO: test for failed two phase locks. This is known broken.
602
        self.control_files.lock_write()
1185.65.3 by Aaron Bentley
Fixed locking-- all tests pass
603
        self.storage.lock_write()
1185.65.1 by Aaron Bentley
Refactored out ControlFiles and RevisionStore from _Branch
604
1185.65.3 by Aaron Bentley
Fixed locking-- all tests pass
605
    def lock_read(self):
1185.65.11 by Robert Collins
Disable inheritance for getting at LockableFiles, rather use composition.
606
        # TODO: test for failed two phase locks. This is known broken.
607
        self.control_files.lock_read()
1185.65.3 by Aaron Bentley
Fixed locking-- all tests pass
608
        self.storage.lock_read()
1185.65.1 by Aaron Bentley
Refactored out ControlFiles and RevisionStore from _Branch
609
610
    def unlock(self):
1185.65.11 by Robert Collins
Disable inheritance for getting at LockableFiles, rather use composition.
611
        # TODO: test for failed two phase locks. This is known broken.
1185.65.3 by Aaron Bentley
Fixed locking-- all tests pass
612
        self.storage.unlock()
1185.65.11 by Robert Collins
Disable inheritance for getting at LockableFiles, rather use composition.
613
        self.control_files.unlock()
1185.65.1 by Aaron Bentley
Refactored out ControlFiles and RevisionStore from _Branch
614
1442.1.63 by Robert Collins
Remove self.lock_*...finally: self.unlock() dead chickens from branch.py.
615
    @needs_read_lock
1185.50.9 by John Arbash Meinel
[bug 3632] Matthieu Moy- bzr cat should default to last revision
616
    def print_file(self, file, revision_id):
1495.1.2 by Jelmer Vernooij
Move some generic methods of NativeBranch to Branch.
617
        """See Branch.print_file."""
1185.65.15 by Robert Collins
Merge from integration.
618
        return self.storage.print_file(file, revision_id)
1442.1.63 by Robert Collins
Remove self.lock_*...finally: self.unlock() dead chickens from branch.py.
619
620
    @needs_write_lock
905 by Martin Pool
- merge aaron's append_multiple.patch
621
    def append_revision(self, *revision_ids):
1495.1.2 by Jelmer Vernooij
Move some generic methods of NativeBranch to Branch.
622
        """See Branch.append_revision."""
905 by Martin Pool
- merge aaron's append_multiple.patch
623
        for revision_id in revision_ids:
624
            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.
625
        rev_history = self.revision_history()
626
        rev_history.extend(revision_ids)
1442.1.68 by Robert Collins
'bzr pull' now accepts '--clobber'.
627
        self.set_revision_history(rev_history)
628
629
    @needs_write_lock
630
    def set_revision_history(self, rev_history):
1495.1.2 by Jelmer Vernooij
Move some generic methods of NativeBranch to Branch.
631
        """See Branch.set_revision_history."""
1185.33.59 by Martin Pool
[patch] keep a cached basis inventory (Johan Rydberg)
632
        old_revision = self.last_revision()
633
        new_revision = rev_history[-1]
1185.65.12 by Robert Collins
Remove the only-used-once put_controlfiles, and change put_controlfile to put and put_utf8.
634
        self.control_files.put_utf8(
1185.65.11 by Robert Collins
Disable inheritance for getting at LockableFiles, rather use composition.
635
            'revision-history', '\n'.join(rev_history))
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.
636
        try:
1185.65.15 by Robert Collins
Merge from integration.
637
            # FIXME: RBC 20051207 this smells wrong, last_revision in the 
638
            # working tree may be != to last_revision in the branch - so
639
            # why is this passing in the branches last_revision ?
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.
640
            self.working_tree().set_last_revision(new_revision, old_revision)
641
        except NoWorkingTree:
642
            mutter('Unable to set_last_revision without a working tree.')
233 by mbp at sourcefrog
- more output from test.sh
643
672 by Martin Pool
- revision records include the hash of their inventory and
644
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
645
    def get_revision_delta(self, revno):
646
        """Return the delta for one revision.
647
648
        The delta is relative to its mainline predecessor, or the
649
        empty tree for revision 1.
650
        """
651
        assert isinstance(revno, int)
652
        rh = self.revision_history()
653
        if not (1 <= revno <= len(rh)):
654
            raise InvalidRevisionNumber(revno)
655
656
        # revno is 1-based; list is 0-based
657
1185.65.1 by Aaron Bentley
Refactored out ControlFiles and RevisionStore from _Branch
658
        new_tree = self.storage.revision_tree(rh[revno-1])
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
659
        if revno == 1:
660
            old_tree = EmptyTree()
661
        else:
1185.65.1 by Aaron Bentley
Refactored out ControlFiles and RevisionStore from _Branch
662
            old_tree = self.storage.revision_tree(rh[revno-2])
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
663
        return compare_trees(old_tree, new_tree)
664
1442.1.63 by Robert Collins
Remove self.lock_*...finally: self.unlock() dead chickens from branch.py.
665
    @needs_read_lock
1 by mbp at sourcefrog
import from baz patch-364
666
    def revision_history(self):
1495.1.2 by Jelmer Vernooij
Move some generic methods of NativeBranch to Branch.
667
        """See Branch.revision_history."""
1185.65.11 by Robert Collins
Disable inheritance for getting at LockableFiles, rather use composition.
668
        # 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.
669
        transaction = self.get_transaction()
670
        history = transaction.map.find_revision_history()
671
        if history is not None:
672
            mutter("cache hit for revision-history in %s", self)
1417.1.12 by Robert Collins
cache revision history during read transactions
673
            return list(history)
1442.1.63 by Robert Collins
Remove self.lock_*...finally: self.unlock() dead chickens from branch.py.
674
        history = [l.rstrip('\r\n') for l in
1185.65.11 by Robert Collins
Disable inheritance for getting at LockableFiles, rather use composition.
675
                self.control_files.controlfile('revision-history', 'r').readlines()]
1442.1.63 by Robert Collins
Remove self.lock_*...finally: self.unlock() dead chickens from branch.py.
676
        transaction.map.add_revision_history(history)
677
        # this call is disabled because revision_history is 
678
        # not really an object yet, and the transaction is for objects.
679
        # transaction.register_clean(history, precious=True)
680
        return list(history)
1 by mbp at sourcefrog
import from baz patch-364
681
974.1.28 by aaron.bentley at utoronto
factored install_revisions out of update_revisions, updated test cases for greedy_fetch
682
    def update_revisions(self, other, stop_revision=None):
1495.1.2 by Jelmer Vernooij
Move some generic methods of NativeBranch to Branch.
683
        """See Branch.update_revisions."""
974.1.33 by aaron.bentley at utoronto
Added greedy_fetch to update_revisions
684
        from bzrlib.fetch import greedy_fetch
974.1.75 by Aaron Bentley
Sped up pull by copying locally first
685
        if stop_revision is None:
1390 by Robert Collins
pair programming worx... merge integration and weave
686
            stop_revision = other.last_revision()
1185.12.44 by abentley
Restored branch convergence to bzr pull
687
        ### 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
688
        if (stop_revision is not None and 
689
            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
690
            return
1260 by Martin Pool
- some updates for fetch/update function
691
        greedy_fetch(to_branch=self, from_branch=other,
1261 by Martin Pool
- new method Branch.has_revision
692
                     revision=stop_revision)
1185.12.44 by abentley
Restored branch convergence to bzr pull
693
        pullable_revs = self.pullable_revisions(other, stop_revision)
1185.12.45 by abentley
Cleanups for pull
694
        if len(pullable_revs) > 0:
1261 by Martin Pool
- new method Branch.has_revision
695
            self.append_revision(*pullable_revs)
1185.12.44 by abentley
Restored branch convergence to bzr pull
696
697
    def pullable_revisions(self, other, stop_revision):
1495.1.2 by Jelmer Vernooij
Move some generic methods of NativeBranch to Branch.
698
        """See Branch.pullable_revisions."""
1185.12.44 by abentley
Restored branch convergence to bzr pull
699
        other_revno = other.revision_id_to_revno(stop_revision)
700
        try:
701
            return self.missing_revisions(other, other_revno)
702
        except DivergedBranches, e:
703
            try:
704
                pullable_revs = get_intervening_revisions(self.last_revision(),
1185.65.1 by Aaron Bentley
Refactored out ControlFiles and RevisionStore from _Branch
705
                                                          stop_revision, 
706
                                                          self.storage)
1185.12.44 by abentley
Restored branch convergence to bzr pull
707
                assert self.last_revision() not in pullable_revs
708
                return pullable_revs
709
            except bzrlib.errors.NotAncestor:
710
                if is_ancestor(self.last_revision(), stop_revision, self):
711
                    return []
712
                else:
713
                    raise e
714
        
1185.33.59 by Martin Pool
[patch] keep a cached basis inventory (Johan Rydberg)
715
    def basis_tree(self):
716
        """See Branch.basis_tree."""
717
        try:
718
            revision_id = self.revision_history()[-1]
1185.65.15 by Robert Collins
Merge from integration.
719
            # FIXME: This is an abstraction violation, the basis tree 
720
            # here as defined is on the working tree, the method should
721
            # be too. The basis tree for a branch can be different than
722
            # that for a working tree. RBC 20051207
1185.33.59 by Martin Pool
[patch] keep a cached basis inventory (Johan Rydberg)
723
            xml = self.working_tree().read_basis_inventory(revision_id)
724
            inv = bzrlib.xml5.serializer_v5.read_inventory_from_string(xml)
1185.65.15 by Robert Collins
Merge from integration.
725
            return RevisionTree(self.storage.weave_store, 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.
726
        except (IndexError, NoSuchFile, NoWorkingTree), e:
1185.65.15 by Robert Collins
Merge from integration.
727
            return self.storage.revision_tree(self.last_revision())
1185.33.59 by Martin Pool
[patch] keep a cached basis inventory (Johan Rydberg)
728
1 by mbp at sourcefrog
import from baz patch-364
729
    def working_tree(self):
1495.1.2 by Jelmer Vernooij
Move some generic methods of NativeBranch to Branch.
730
        """See Branch.working_tree."""
1185.2.2 by Lalo Martins
cleaning up and refactoring the branch module.
731
        from bzrlib.workingtree import WorkingTree
1185.65.11 by Robert Collins
Disable inheritance for getting at LockableFiles, rather use composition.
732
        if self.base.find('://') != -1:
1497 by Robert Collins
Move Branch.read_working_inventory to WorkingTree.
733
            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.
734
        return WorkingTree(self.base, branch=self)
1 by mbp at sourcefrog
import from baz patch-364
735
1490 by Robert Collins
Implement a 'bzr push' command, with saved locations; update diff to return 1.
736
    @needs_write_lock
737
    def pull(self, source, overwrite=False):
1495.1.2 by Jelmer Vernooij
Move some generic methods of NativeBranch to Branch.
738
        """See Branch.pull."""
1490 by Robert Collins
Implement a 'bzr push' command, with saved locations; update diff to return 1.
739
        source.lock_read()
740
        try:
1185.33.44 by Martin Pool
[patch] show number of revisions pushed/pulled/merged (Robey Pointer)
741
            old_count = len(self.revision_history())
1490 by Robert Collins
Implement a 'bzr push' command, with saved locations; update diff to return 1.
742
            try:
743
                self.update_revisions(source)
744
            except DivergedBranches:
745
                if not overwrite:
746
                    raise
1185.50.5 by John Arbash Meinel
pull --overwrite should always overwrite, not just if diverged. (Test case from Robey Pointer)
747
            if overwrite:
1490 by Robert Collins
Implement a 'bzr push' command, with saved locations; update diff to return 1.
748
                self.set_revision_history(source.revision_history())
1185.33.44 by Martin Pool
[patch] show number of revisions pushed/pulled/merged (Robey Pointer)
749
            new_count = len(self.revision_history())
750
            return new_count - old_count
1490 by Robert Collins
Implement a 'bzr push' command, with saved locations; update diff to return 1.
751
        finally:
752
            source.unlock()
1 by mbp at sourcefrog
import from baz patch-364
753
1149 by Martin Pool
- make get_parent() be a method of Branch; add simple tests for it
754
    def get_parent(self):
1495.1.2 by Jelmer Vernooij
Move some generic methods of NativeBranch to Branch.
755
        """See Branch.get_parent."""
1149 by Martin Pool
- make get_parent() be a method of Branch; add simple tests for it
756
        import errno
757
        _locs = ['parent', 'pull', 'x-pull']
758
        for l in _locs:
759
            try:
1185.65.11 by Robert Collins
Disable inheritance for getting at LockableFiles, rather use composition.
760
                return self.control_files.controlfile(l, 'r').read().strip('\n')
1185.50.11 by John Arbash Meinel
[merge] Refactor NoSuchFile style exceptions.
761
            except NoSuchFile:
762
                pass
1149 by Martin Pool
- make get_parent() be a method of Branch; add simple tests for it
763
        return None
764
1490 by Robert Collins
Implement a 'bzr push' command, with saved locations; update diff to return 1.
765
    def get_push_location(self):
1495.1.2 by Jelmer Vernooij
Move some generic methods of NativeBranch to Branch.
766
        """See Branch.get_push_location."""
1490 by Robert Collins
Implement a 'bzr push' command, with saved locations; update diff to return 1.
767
        config = bzrlib.config.BranchConfig(self)
768
        push_loc = config.get_user_option('push_location')
769
        return push_loc
770
771
    def set_push_location(self, location):
1495.1.2 by Jelmer Vernooij
Move some generic methods of NativeBranch to Branch.
772
        """See Branch.set_push_location."""
1490 by Robert Collins
Implement a 'bzr push' command, with saved locations; update diff to return 1.
773
        config = bzrlib.config.LocationConfig(self.base)
774
        config.set_user_option('push_location', location)
775
1442.1.63 by Robert Collins
Remove self.lock_*...finally: self.unlock() dead chickens from branch.py.
776
    @needs_write_lock
1150 by Martin Pool
- add new Branch.set_parent and tests
777
    def set_parent(self, url):
1495.1.2 by Jelmer Vernooij
Move some generic methods of NativeBranch to Branch.
778
        """See Branch.set_parent."""
1150 by Martin Pool
- add new Branch.set_parent and tests
779
        # TODO: Maybe delete old location files?
780
        from bzrlib.atomicfile import AtomicFile
1185.65.11 by Robert Collins
Disable inheritance for getting at LockableFiles, rather use composition.
781
        f = AtomicFile(self.control_files.controlfilename('parent'))
1150 by Martin Pool
- add new Branch.set_parent and tests
782
        try:
1442.1.63 by Robert Collins
Remove self.lock_*...finally: self.unlock() dead chickens from branch.py.
783
            f.write(url + '\n')
784
            f.commit()
1150 by Martin Pool
- add new Branch.set_parent and tests
785
        finally:
1442.1.63 by Robert Collins
Remove self.lock_*...finally: self.unlock() dead chickens from branch.py.
786
            f.close()
1150 by Martin Pool
- add new Branch.set_parent and tests
787
1185.35.11 by Aaron Bentley
Added support for branch nicks
788
    def tree_config(self):
789
        return TreeConfig(self)
790
1185.66.8 by Aaron Bentley
Applied Jelmer's patch to make clone a branch operation
791
    def _get_truncated_history(self, revision_id):
792
        history = self.revision_history()
793
        if revision_id is None:
794
            return history
795
        try:
796
            idx = history.index(revision_id)
797
        except ValueError:
798
            raise InvalidRevisionId(revision_id=revision, branch=self)
799
        return history[:idx+1]
800
801
    @needs_read_lock
802
    def _clone_weave(self, to_location, revision=None, basis_branch=None):
803
        assert isinstance(to_location, basestring)
804
        if basis_branch is not None:
805
            note("basis_branch is not supported for fast weave copy yet.")
806
807
        history = self._get_truncated_history(revision)
808
        if not bzrlib.osutils.lexists(to_location):
809
            os.mkdir(to_location)
810
        branch_to = Branch.initialize(to_location)
811
        mutter("copy branch from %s to %s", self, branch_to)
812
        branch_to.working_tree().set_root_id(self.get_root_id())
813
814
        self.storage.copy(branch_to.storage)
974.1.54 by aaron.bentley at utoronto
Fixed the revno bug in log
815
        
1185.65.15 by Robert Collins
Merge from integration.
816
        # must be done *after* history is copied across
817
        # FIXME duplicate code with base .clone().
818
        # .. would template method be useful here.  RBC 20051207
1185.66.8 by Aaron Bentley
Applied Jelmer's patch to make clone a branch operation
819
        branch_to.set_parent(self.base)
1185.65.15 by Robert Collins
Merge from integration.
820
        branch_to.append_revision(*history)
821
        # circular import protection
822
        from bzrlib.merge import build_working_dir
823
        build_working_dir(to_location)
1185.66.8 by Aaron Bentley
Applied Jelmer's patch to make clone a branch operation
824
        mutter("copied")
825
        return branch_to
826
827
    def clone(self, to_location, revision=None, basis_branch=None, to_branch_type=None):
828
        if to_branch_type is None:
829
            to_branch_type = BzrBranch
830
831
        if to_branch_type == BzrBranch \
832
            and self.storage.weave_store.listable() \
833
            and self.storage.revision_store.listable():
834
            return self._clone_weave(to_location, revision, basis_branch)
835
836
        return Branch.clone(self, to_location, revision, basis_branch, to_branch_type)
1185.35.11 by Aaron Bentley
Added support for branch nicks
837
1495.1.5 by Jelmer Vernooij
Rename NativeBranch -> BzrBranch
838
class ScratchBranch(BzrBranch):
1 by mbp at sourcefrog
import from baz patch-364
839
    """Special test class: a branch that cleans up after itself.
840
841
    >>> b = ScratchBranch()
842
    >>> isdir(b.base)
843
    True
844
    >>> bd = b.base
1185.65.11 by Robert Collins
Disable inheritance for getting at LockableFiles, rather use composition.
845
    >>> b.control_files._transport.__del__()
1 by mbp at sourcefrog
import from baz patch-364
846
    >>> isdir(bd)
847
    False
848
    """
1442.1.42 by Robert Collins
rebuild ScratchBranch on top of ScratchTransport
849
850
    def __init__(self, files=[], dirs=[], transport=None):
1 by mbp at sourcefrog
import from baz patch-364
851
        """Make a test branch.
852
853
        This creates a temporary directory and runs init-tree in it.
854
855
        If any files are listed, they are created in the working copy.
856
        """
1442.1.42 by Robert Collins
rebuild ScratchBranch on top of ScratchTransport
857
        if transport is None:
858
            transport = bzrlib.transport.local.ScratchTransport()
859
            super(ScratchBranch, self).__init__(transport, init=True)
860
        else:
861
            super(ScratchBranch, self).__init__(transport)
862
100 by mbp at sourcefrog
- add test case for ignore files
863
        for d in dirs:
1185.65.11 by Robert Collins
Disable inheritance for getting at LockableFiles, rather use composition.
864
            self.control_files._transport.mkdir(d)
100 by mbp at sourcefrog
- add test case for ignore files
865
            
1 by mbp at sourcefrog
import from baz patch-364
866
        for f in files:
1185.65.11 by Robert Collins
Disable inheritance for getting at LockableFiles, rather use composition.
867
            self.control_files._transport.put(f, 'content of %s' % f)
1 by mbp at sourcefrog
import from baz patch-364
868
622 by Martin Pool
Updated merge patch from Aaron
869
    def clone(self):
870
        """
871
        >>> orig = ScratchBranch(files=["file1", "file2"])
872
        >>> clone = orig.clone()
1185.1.40 by Robert Collins
Merge what applied of Alexander Belchenko's win32 patch.
873
        >>> if os.name != 'nt':
874
        ...   os.path.samefile(orig.base, clone.base)
875
        ... else:
876
        ...   orig.base == clone.base
877
        ...
622 by Martin Pool
Updated merge patch from Aaron
878
        False
879
        >>> os.path.isfile(os.path.join(clone.base, "file1"))
880
        True
881
        """
800 by Martin Pool
Merge John's import-speedup branch:
882
        from shutil import copytree
883
        from tempfile import mkdtemp
884
        base = mkdtemp()
622 by Martin Pool
Updated merge patch from Aaron
885
        os.rmdir(base)
800 by Martin Pool
Merge John's import-speedup branch:
886
        copytree(self.base, base, symlinks=True)
1442.1.42 by Robert Collins
rebuild ScratchBranch on top of ScratchTransport
887
        return ScratchBranch(
888
            transport=bzrlib.transport.local.ScratchTransport(base))
1 by mbp at sourcefrog
import from baz patch-364
889
    
890
891
######################################################################
892
# predicates
893
894
895
def is_control_file(filename):
896
    ## FIXME: better check
897
    filename = os.path.normpath(filename)
898
    while filename != '':
899
        head, tail = os.path.split(filename)
900
        ## mutter('check %r for control file' % ((head, tail), ))
901
        if tail == bzrlib.BZRDIR:
902
            return True
70 by mbp at sourcefrog
Prepare for smart recursive add.
903
        if filename == head:
904
            break
1 by mbp at sourcefrog
import from baz patch-364
905
        filename = head
906
    return False