~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/branch.py

Merge bzr.dev.

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
16
 
17
17
 
 
18
from cStringIO import StringIO
 
19
 
 
20
from bzrlib.lazy_import import lazy_import
 
21
lazy_import(globals(), """
18
22
from copy import deepcopy
19
 
from cStringIO import StringIO
20
23
from unittest import TestSuite
21
24
from warnings import warn
22
25
 
26
29
        cache_utf8,
27
30
        errors,
28
31
        lockdir,
 
32
        lockable_files,
29
33
        osutils,
30
 
        revision,
 
34
        revision as _mod_revision,
31
35
        transport,
32
36
        tree,
33
37
        ui,
34
38
        urlutils,
35
39
        )
36
 
from bzrlib.config import TreeConfig
 
40
from bzrlib.config import BranchConfig, TreeConfig
 
41
from bzrlib.lockable_files import LockableFiles, TransportLock
 
42
""")
 
43
 
37
44
from bzrlib.decorators import needs_read_lock, needs_write_lock
38
 
import bzrlib.errors as errors
39
 
from bzrlib.errors import (BzrError, BzrCheckError, DivergedBranches, 
40
 
                           HistoryMissing, InvalidRevisionId, 
41
 
                           InvalidRevisionNumber, LockError, NoSuchFile, 
 
45
from bzrlib.errors import (BzrError, BzrCheckError, DivergedBranches,
 
46
                           HistoryMissing, InvalidRevisionId,
 
47
                           InvalidRevisionNumber, LockError, NoSuchFile,
42
48
                           NoSuchRevision, NoWorkingTree, NotVersionedError,
43
 
                           NotBranchError, UninitializableFormat, 
44
 
                           UnlistableStore, UnlistableBranch, 
 
49
                           NotBranchError, UninitializableFormat,
 
50
                           UnlistableStore, UnlistableBranch,
45
51
                           )
46
 
from bzrlib.lockable_files import LockableFiles, TransportLock
47
52
from bzrlib.symbol_versioning import (deprecated_function,
48
53
                                      deprecated_method,
49
54
                                      DEPRECATED_PARAMETER,
138
143
        """
139
144
        return bzrdir.BzrDir.create_standalone_workingtree(base).branch
140
145
 
 
146
    @deprecated_function(zero_eight)
141
147
    def setup_caching(self, cache_root):
142
148
        """Subclasses that care about caching should override this, and set
143
149
        up cached stores located under cache_root.
 
150
        
 
151
        NOTE: This is unused.
144
152
        """
145
 
        # seems to be unused, 2006-01-13 mbp
146
 
        warn('%s is deprecated' % self.setup_caching)
147
 
        self.cache_root = cache_root
 
153
        pass
148
154
 
149
155
    def get_config(self):
150
 
        return bzrlib.config.BranchConfig(self)
 
156
        return BranchConfig(self)
151
157
 
152
158
    def _get_nick(self):
153
159
        return self.get_config().get_nickname()
221
227
                    last_revision = from_history[-1]
222
228
                else:
223
229
                    # no history in the source branch
224
 
                    last_revision = revision.NULL_REVISION
 
230
                    last_revision = _mod_revision.NULL_REVISION
225
231
            return self.repository.fetch(from_branch.repository,
226
232
                                         revision_id=last_revision,
227
233
                                         pb=nested_pb)
293
299
 
294
300
    def revision_history(self):
295
301
        """Return sequence of revision hashes on to this branch."""
296
 
        raise NotImplementedError('revision_history is abstract')
 
302
        raise NotImplementedError(self.revision_history)
297
303
 
298
304
    def revno(self):
299
305
        """Return current revision number for this branch.
580
586
            mainline_parent_id = revision_id
581
587
        return BranchCheckResult(self)
582
588
 
 
589
    def _get_checkout_format(self):
 
590
        """Return the most suitable metadir for a checkout of this branch.
 
591
        Weaves are used if this branch's repostory uses weaves.
 
592
        """
 
593
        if isinstance(self.bzrdir, bzrdir.BzrDirPreSplitOut):
 
594
            from bzrlib import repository
 
595
            format = bzrdir.BzrDirMetaFormat1()
 
596
            format.repository_format = repository.RepositoryFormat7()
 
597
        else:
 
598
            format = self.repository.bzrdir.cloning_metadir()
 
599
        return format
 
600
 
583
601
    def create_checkout(self, to_location, revision_id=None, 
584
602
                        lightweight=False):
585
603
        """Create a checkout of a branch.
590
608
        produce a bound branch (heavyweight checkout)
591
609
        :return: The tree of the created checkout
592
610
        """
 
611
        t = transport.get_transport(to_location)
 
612
        try:
 
613
            t.mkdir('.')
 
614
        except errors.FileExists:
 
615
            pass
593
616
        if lightweight:
594
 
            t = transport.get_transport(to_location)
595
 
            try:
596
 
                t.mkdir('.')
597
 
            except errors.FileExists:
598
 
                pass
599
617
            checkout = bzrdir.BzrDirMetaFormat1().initialize_on_transport(t)
600
618
            BranchReferenceFormat().initialize(checkout, self)
601
619
        else:
 
620
            format = self._get_checkout_format()
602
621
            checkout_branch = bzrdir.BzrDir.create_branch_convenience(
603
 
                to_location, force_new_tree=False)
 
622
                to_location, force_new_tree=False, format=format)
604
623
            checkout = checkout_branch.bzrdir
605
624
            checkout_branch.bind(self)
606
 
            if revision_id is not None:
607
 
                rh = checkout_branch.revision_history()
608
 
                new_rh = rh[:rh.index(revision_id) + 1]
609
 
                checkout_branch.set_revision_history(new_rh)
 
625
            # pull up to the specified revision_id to set the initial 
 
626
            # branch tip correctly, and seed it with history.
 
627
            checkout_branch.pull(self, stop_revision=revision_id)
610
628
        return checkout.create_workingtree(revision_id)
611
629
 
612
630
 
716
734
        utf8_files = [('revision-history', ''),
717
735
                      ('branch-name', ''),
718
736
                      ]
719
 
        control_files = LockableFiles(branch_transport, 'branch-lock',
720
 
                                      TransportLock)
 
737
        control_files = lockable_files.LockableFiles(branch_transport,
 
738
                             'branch-lock', lockable_files.TransportLock)
721
739
        control_files.create_lock()
722
740
        control_files.lock_write()
723
741
        try:
777
795
        utf8_files = [('revision-history', ''),
778
796
                      ('branch-name', ''),
779
797
                      ]
780
 
        control_files = LockableFiles(branch_transport, 'lock', lockdir.LockDir)
 
798
        control_files = lockable_files.LockableFiles(branch_transport, 'lock',
 
799
                                                     lockdir.LockDir)
781
800
        control_files.create_lock()
782
801
        control_files.lock_write()
783
802
        control_files.put_utf8('format', self.get_format_string())
802
821
            format = BranchFormat.find_format(a_bzrdir)
803
822
            assert format.__class__ == self.__class__
804
823
        transport = a_bzrdir.get_branch_transport(None)
805
 
        control_files = LockableFiles(transport, 'lock', lockdir.LockDir)
 
824
        control_files = lockable_files.LockableFiles(transport, 'lock',
 
825
                                                     lockdir.LockDir)
806
826
        return BzrBranch5(_format=self,
807
827
                          _control_files=control_files,
808
828
                          a_bzrdir=a_bzrdir,
958
978
 
959
979
    __repr__ = __str__
960
980
 
961
 
    def __del__(self):
962
 
        # TODO: It might be best to do this somewhere else,
963
 
        # but it is nice for a Branch object to automatically
964
 
        # cache it's information.
965
 
        # Alternatively, we could have the Transport objects cache requests
966
 
        # See the earlier discussion about how major objects (like Branch)
967
 
        # should never expect their __del__ function to run.
968
 
        # XXX: cache_root seems to be unused, 2006-01-13 mbp
969
 
        if hasattr(self, 'cache_root') and self.cache_root is not None:
970
 
            try:
971
 
                osutils.rmtree(self.cache_root)
972
 
            except:
973
 
                pass
974
 
            self.cache_root = None
975
 
 
976
981
    def _get_base(self):
977
982
        return self._base
978
983
 
1131
1136
        # make a new revision history from the graph
1132
1137
        current_rev_id = revision_id
1133
1138
        new_history = []
1134
 
        while current_rev_id not in (None, revision.NULL_REVISION):
 
1139
        while current_rev_id not in (None, _mod_revision.NULL_REVISION):
1135
1140
            new_history.append(current_rev_id)
1136
1141
            current_rev_id_parents = stop_graph[current_rev_id]
1137
1142
            try:
1187
1192
        try:
1188
1193
            old_count = len(self.revision_history())
1189
1194
            try:
1190
 
                self.update_revisions(source,stop_revision)
 
1195
                self.update_revisions(source, stop_revision)
1191
1196
            except DivergedBranches:
1192
1197
                if not overwrite:
1193
1198
                    raise
1328
1333
 
1329
1334
    @needs_write_lock
1330
1335
    def bind(self, other):
1331
 
        """Bind the local branch the other branch.
 
1336
        """Bind this branch to the branch other.
1332
1337
 
 
1338
        This does not push or pull data between the branches, though it does
 
1339
        check for divergence to raise an error when the branches are not
 
1340
        either the same, or one a prefix of the other. That behaviour may not
 
1341
        be useful, so that check may be removed in future.
 
1342
        
1333
1343
        :param other: The branch to bind to
1334
1344
        :type other: Branch
1335
1345
        """
1340
1350
        #       but binding itself may not be.
1341
1351
        #       Since we *have* to check at commit time, we don't
1342
1352
        #       *need* to check here
1343
 
        self.pull(other)
1344
 
 
1345
 
        # we are now equal to or a suffix of other.
1346
 
 
1347
 
        # Since we have 'pulled' from the remote location,
1348
 
        # now we should try to pull in the opposite direction
1349
 
        # in case the local tree has more revisions than the
1350
 
        # remote one.
1351
 
        # There may be a different check you could do here
1352
 
        # rather than actually trying to install revisions remotely.
1353
 
        # TODO: capture an exception which indicates the remote branch
1354
 
        #       is not writable. 
1355
 
        #       If it is up-to-date, this probably should not be a failure
1356
 
        
1357
 
        # lock other for write so the revision-history syncing cannot race
1358
 
        other.lock_write()
1359
 
        try:
1360
 
            other.pull(self)
1361
 
            # if this does not error, other now has the same last rev we do
1362
 
            # it can only error if the pull from other was concurrent with
1363
 
            # a commit to other from someone else.
1364
 
 
1365
 
            # until we ditch revision-history, we need to sync them up:
1366
 
            self.set_revision_history(other.revision_history())
1367
 
            # now other and self are up to date with each other and have the
1368
 
            # same revision-history.
1369
 
        finally:
1370
 
            other.unlock()
1371
 
 
 
1353
 
 
1354
        # we want to raise diverged if:
 
1355
        # last_rev is not in the other_last_rev history, AND
 
1356
        # other_last_rev is not in our history, and do it without pulling
 
1357
        # history around
 
1358
        last_rev = self.last_revision()
 
1359
        if last_rev is not None:
 
1360
            other.lock_read()
 
1361
            try:
 
1362
                other_last_rev = other.last_revision()
 
1363
                if other_last_rev is not None:
 
1364
                    # neither branch is new, we have to do some work to
 
1365
                    # ascertain diversion.
 
1366
                    remote_graph = other.repository.get_revision_graph(
 
1367
                        other_last_rev)
 
1368
                    local_graph = self.repository.get_revision_graph(last_rev)
 
1369
                    if (last_rev not in remote_graph and
 
1370
                        other_last_rev not in local_graph):
 
1371
                        raise errors.DivergedBranches(self, other)
 
1372
            finally:
 
1373
                other.unlock()
1372
1374
        self.set_bound_location(other.base)
1373
1375
 
1374
1376
    @needs_write_lock