~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/branch.py

  • Committer: Ian Clatworthy
  • Date: 2007-11-21 07:39:16 UTC
  • mto: (3054.1.1 ianc-integration)
  • mto: This revision was merged to the branch mainline in revision 3055.
  • Revision ID: ian.clatworthy@internode.on.net-20071121073916-qlpp5gvcf0639r38
1st cut at the 'Personal version control' chapter

Show diffs side-by-side

added added

removed removed

Lines of Context:
425
425
        That is equivalent to the number of revisions committed to
426
426
        this branch.
427
427
        """
428
 
        return self.last_revision_info()[0]
 
428
        return len(self.revision_history())
429
429
 
430
430
    def unbind(self):
431
431
        """Older format branches cannot bind or unbind."""
757
757
        return format
758
758
 
759
759
    def create_checkout(self, to_location, revision_id=None,
760
 
                        lightweight=False, accelerator_tree=None):
 
760
                        lightweight=False):
761
761
        """Create a checkout of a branch.
762
762
        
763
763
        :param to_location: The url to produce the checkout at
764
764
        :param revision_id: The revision to check out
765
765
        :param lightweight: If True, produce a lightweight checkout, otherwise,
766
766
        produce a bound branch (heavyweight checkout)
767
 
        :param accelerator_tree: A tree which can be used for retrieving file
768
 
            contents more quickly than the revision tree, i.e. a workingtree.
769
 
            The revision tree will be used for cases where accelerator_tree's
770
 
            content is different.
771
767
        :return: The tree of the created checkout
772
768
        """
773
769
        t = transport.get_transport(to_location)
775
771
        if lightweight:
776
772
            format = self._get_checkout_format()
777
773
            checkout = format.initialize_on_transport(t)
778
 
            from_branch = BranchReferenceFormat().initialize(checkout, self)
 
774
            BranchReferenceFormat().initialize(checkout, self)
779
775
        else:
780
776
            format = self._get_checkout_format()
781
777
            checkout_branch = bzrdir.BzrDir.create_branch_convenience(
785
781
            # pull up to the specified revision_id to set the initial 
786
782
            # branch tip correctly, and seed it with history.
787
783
            checkout_branch.pull(self, stop_revision=revision_id)
788
 
            from_branch=None
789
 
        tree = checkout.create_workingtree(revision_id,
790
 
                                           from_branch=from_branch,
791
 
                                           accelerator_tree=accelerator_tree)
 
784
        tree = checkout.create_workingtree(revision_id)
792
785
        basis_tree = tree.basis_tree()
793
786
        basis_tree.lock_read()
794
787
        try:
873
866
        """
874
867
        return None
875
868
 
876
 
    @classmethod
877
 
    def set_reference(self, a_bzrdir, to_branch):
878
 
        """Set the target reference of the branch in a_bzrdir.
879
 
 
880
 
        format probing must have been completed before calling
881
 
        this method - it is assumed that the format of the branch
882
 
        in a_bzrdir is correct.
883
 
 
884
 
        :param a_bzrdir: The bzrdir to set the branch reference for.
885
 
        :param to_branch: branch that the checkout is to reference
886
 
        """
887
 
        raise NotImplementedError(self.set_reference)
888
 
 
889
869
    def get_format_string(self):
890
870
        """Return the ASCII format string that identifies this format."""
891
871
        raise NotImplementedError(self.get_format_string)
1166
1146
    def initialize(self, a_bzrdir):
1167
1147
        """Create a branch of this format in a_bzrdir."""
1168
1148
        utf8_files = [('last-revision', '0 null:\n'),
 
1149
                      ('branch-name', ''),
1169
1150
                      ('branch.conf', ''),
1170
1151
                      ('tags', ''),
1171
1152
                      ]
1210
1191
    def get_format_description(self):
1211
1192
        """See BranchFormat.get_format_description()."""
1212
1193
        return "Checkout reference format 1"
1213
 
 
 
1194
        
1214
1195
    def get_reference(self, a_bzrdir):
1215
1196
        """See BranchFormat.get_reference()."""
1216
1197
        transport = a_bzrdir.get_branch_transport(None)
1217
1198
        return transport.get('location').read()
1218
1199
 
1219
 
    def set_reference(self, a_bzrdir, to_branch):
1220
 
        """See BranchFormat.set_reference()."""
1221
 
        transport = a_bzrdir.get_branch_transport(None)
1222
 
        location = transport.put_bytes('location', to_branch.base)
1223
 
 
1224
1200
    def initialize(self, a_bzrdir, target_branch=None):
1225
1201
        """Create a branch of this format in a_bzrdir."""
1226
1202
        if target_branch is None:
1232
1208
        branch_transport.put_bytes('location',
1233
1209
            target_branch.bzrdir.root_transport.base)
1234
1210
        branch_transport.put_bytes('format', self.get_format_string())
1235
 
        return self.open(
1236
 
            a_bzrdir, _found=True,
1237
 
            possible_transports=[target_branch.bzrdir.root_transport])
 
1211
        return self.open(a_bzrdir, _found=True)
1238
1212
 
1239
1213
    def __init__(self):
1240
1214
        super(BranchReferenceFormat, self).__init__()
1250
1224
            # emit some sort of warning/error to the caller ?!
1251
1225
        return clone
1252
1226
 
1253
 
    def open(self, a_bzrdir, _found=False, location=None,
1254
 
             possible_transports=None):
 
1227
    def open(self, a_bzrdir, _found=False, location=None):
1255
1228
        """Return the branch that the branch reference in a_bzrdir points at.
1256
1229
 
1257
1230
        _found is a private parameter, do not use it. It is used to indicate
1262
1235
            assert format.__class__ == self.__class__
1263
1236
        if location is None:
1264
1237
            location = self.get_reference(a_bzrdir)
1265
 
        real_bzrdir = bzrdir.BzrDir.open(
1266
 
            location, possible_transports=possible_transports)
 
1238
        real_bzrdir = bzrdir.BzrDir.open(location)
1267
1239
        result = real_bzrdir.open_branch()
1268
1240
        # this changes the behaviour of result.clone to create a new reference
1269
1241
        # rather than a copy of the content of the branch.
1336
1308
    def get_root_id(self):
1337
1309
        """See Branch.get_root_id."""
1338
1310
        tree = self.repository.revision_tree(self.last_revision())
1339
 
        return tree.get_root_id()
 
1311
        return tree.inventory.root.file_id
1340
1312
 
1341
1313
    def is_locked(self):
1342
1314
        return self.control_files.is_locked()
1462
1434
            last_rev, other_branch))
1463
1435
 
1464
1436
    @needs_write_lock
1465
 
    def update_revisions(self, other, stop_revision=None, overwrite=False):
 
1437
    def update_revisions(self, other, stop_revision=None):
1466
1438
        """See Branch.update_revisions."""
1467
1439
        other.lock_read()
1468
1440
        try:
1469
 
            other_last_revno, other_last_revision = other.last_revision_info()
1470
1441
            if stop_revision is None:
1471
 
                stop_revision = other_last_revision
1472
 
                if _mod_revision.is_null(stop_revision):
 
1442
                stop_revision = other.last_revision()
 
1443
                if stop_revision is None:
1473
1444
                    # if there are no commits, we're done.
1474
1445
                    return
1475
1446
            # whats the current last revision, before we fetch [and change it
1480
1451
            # already merged can operate on the just fetched graph, which will
1481
1452
            # be cached in memory.
1482
1453
            self.fetch(other, stop_revision)
1483
 
            # Check to see if one is an ancestor of the other
1484
 
            if not overwrite:
1485
 
                heads = self.repository.get_graph().heads([stop_revision,
1486
 
                                                           last_rev])
1487
 
                if heads == set([last_rev]):
1488
 
                    # The current revision is a decendent of the target,
1489
 
                    # nothing to do
1490
 
                    return
1491
 
                elif heads == set([stop_revision, last_rev]):
1492
 
                    # These branches have diverged
1493
 
                    raise errors.DivergedBranches(self, other)
1494
 
                assert heads == set([stop_revision])
1495
 
            if other_last_revision == stop_revision:
1496
 
                self.set_last_revision_info(other_last_revno,
1497
 
                                            other_last_revision)
1498
 
            else:
1499
 
                # TODO: jam 2007-11-29 Is there a way to determine the
1500
 
                #       revno without searching all of history??
1501
 
                if overwrite:
1502
 
                    self.generate_revision_history(stop_revision)
1503
 
                else:
1504
 
                    self.generate_revision_history(stop_revision,
1505
 
                        last_rev=last_rev, other_branch=other)
 
1454
            if self.repository.get_graph().is_ancestor(stop_revision,
 
1455
                                                       last_rev):
 
1456
                return
 
1457
            self.generate_revision_history(stop_revision, last_rev=last_rev,
 
1458
                other_branch=other)
1506
1459
        finally:
1507
1460
            other.unlock()
1508
1461
 
1527
1480
        source.lock_read()
1528
1481
        try:
1529
1482
            result.old_revno, result.old_revid = self.last_revision_info()
1530
 
            self.update_revisions(source, stop_revision, overwrite=overwrite)
 
1483
            try:
 
1484
                self.update_revisions(source, stop_revision)
 
1485
            except DivergedBranches:
 
1486
                if not overwrite:
 
1487
                    raise
 
1488
            if overwrite:
 
1489
                if stop_revision is None:
 
1490
                    stop_revision = source.last_revision()
 
1491
                self.generate_revision_history(stop_revision)
1531
1492
            result.tag_conflicts = source.tags.merge_to(self.tags, overwrite)
1532
1493
            result.new_revno, result.new_revid = self.last_revision_info()
1533
1494
            if _hook_master:
1799
1760
        # last_rev is not in the other_last_rev history, AND
1800
1761
        # other_last_rev is not in our history, and do it without pulling
1801
1762
        # history around
 
1763
        last_rev = _mod_revision.ensure_null(self.last_revision())
 
1764
        if last_rev != _mod_revision.NULL_REVISION:
 
1765
            other.lock_read()
 
1766
            try:
 
1767
                other_last_rev = other.last_revision()
 
1768
                if not _mod_revision.is_null(other_last_rev):
 
1769
                    # neither branch is new, we have to do some work to
 
1770
                    # ascertain diversion.
 
1771
                    remote_graph = other.repository.get_revision_graph(
 
1772
                        other_last_rev)
 
1773
                    local_graph = self.repository.get_revision_graph(last_rev)
 
1774
                    if (last_rev not in remote_graph and
 
1775
                        other_last_rev not in local_graph):
 
1776
                        raise errors.DivergedBranches(self, other)
 
1777
            finally:
 
1778
                other.unlock()
1802
1779
        self.set_bound_location(other.base)
1803
1780
 
1804
1781
    @needs_write_lock
1867
1844
        return None
1868
1845
 
1869
1846
    @classmethod
1870
 
    def set_reference(self, a_bzrdir, to_branch):
1871
 
        """Set the target reference of the branch in a_bzrdir.
1872
 
 
1873
 
        format probing must have been completed before calling
1874
 
        this method - it is assumed that the format of the branch
1875
 
        in a_bzrdir is correct.
1876
 
 
1877
 
        :param a_bzrdir: The bzrdir to set the branch reference for.
1878
 
        :param to_branch: branch that the checkout is to reference
1879
 
        """
1880
 
        raise NotImplementedError(self.set_reference)
1881
 
 
1882
 
    @classmethod
1883
1847
    def _initialize_control_files(cls, a_bzrdir, utf8_files, lock_filename,
1884
1848
            lock_class):
1885
1849
        branch_transport = a_bzrdir.get_branch_transport(cls)