/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/branch.py

merge bzr.dev r4054

Show diffs side-by-side

added added

removed removed

Lines of Context:
45
45
 
46
46
from bzrlib.decorators import needs_read_lock, needs_write_lock
47
47
from bzrlib.hooks import Hooks
 
48
from bzrlib.inter import InterObject
 
49
from bzrlib import registry
48
50
from bzrlib.symbol_versioning import (
49
51
    deprecated_in,
50
52
    deprecated_method,
134
136
    @staticmethod
135
137
    def open_containing(url, possible_transports=None):
136
138
        """Open an existing branch which contains url.
137
 
        
 
139
 
138
140
        This probes for a branch at url, and searches upwards from there.
139
141
 
140
142
        Basically we keep looking up until we find the control directory or
141
143
        run into the root.  If there isn't one, raises NotBranchError.
142
 
        If there is one and it is either an unrecognised format or an unsupported 
 
144
        If there is one and it is either an unrecognised format or an unsupported
143
145
        format, UnknownFormatError or UnsupportedFormatError are raised.
144
146
        If there is one, it is returned, along with the unused portion of url.
145
147
        """
147
149
                                                         possible_transports)
148
150
        return control.open_branch(), relpath
149
151
 
 
152
    def _push_should_merge_tags(self):
 
153
        """Should _basic_push merge this branch's tags into the target?
 
154
 
 
155
        The default implementation returns False if this branch has no tags,
 
156
        and True the rest of the time.  Subclasses may override this.
 
157
        """
 
158
        return self.tags.supports_tags() and self.tags.get_tag_dict()
 
159
 
150
160
    def get_config(self):
151
161
        return BranchConfig(self)
152
162
 
174
184
    def is_locked(self):
175
185
        raise NotImplementedError(self.is_locked)
176
186
 
 
187
    def _lefthand_history(self, revision_id, last_rev=None,
 
188
                          other_branch=None):
 
189
        if 'evil' in debug.debug_flags:
 
190
            mutter_callsite(4, "_lefthand_history scales with history.")
 
191
        # stop_revision must be a descendant of last_revision
 
192
        graph = self.repository.get_graph()
 
193
        if last_rev is not None:
 
194
            if not graph.is_ancestor(last_rev, revision_id):
 
195
                # our previous tip is not merged into stop_revision
 
196
                raise errors.DivergedBranches(self, other_branch)
 
197
        # make a new revision history from the graph
 
198
        parents_map = graph.get_parent_map([revision_id])
 
199
        if revision_id not in parents_map:
 
200
            raise errors.NoSuchRevision(self, revision_id)
 
201
        current_rev_id = revision_id
 
202
        new_history = []
 
203
        check_not_reserved_id = _mod_revision.check_not_reserved_id
 
204
        # Do not include ghosts or graph origin in revision_history
 
205
        while (current_rev_id in parents_map and
 
206
               len(parents_map[current_rev_id]) > 0):
 
207
            check_not_reserved_id(current_rev_id)
 
208
            new_history.append(current_rev_id)
 
209
            current_rev_id = parents_map[current_rev_id][0]
 
210
            parents_map = graph.get_parent_map([current_rev_id])
 
211
        new_history.reverse()
 
212
        return new_history
 
213
 
177
214
    def lock_write(self):
178
215
        raise NotImplementedError(self.lock_write)
179
216
 
228
265
    @needs_read_lock
229
266
    def revision_id_to_dotted_revno(self, revision_id):
230
267
        """Given a revision id, return its dotted revno.
231
 
        
 
268
 
232
269
        :return: a tuple like (1,) or (400,1,3).
233
270
        """
234
271
        return self._do_revision_id_to_dotted_revno(revision_id)
398
435
    def leave_lock_in_place(self):
399
436
        """Tell this branch object not to release the physical lock when this
400
437
        object is unlocked.
401
 
        
 
438
 
402
439
        If lock_write doesn't return a token, then this method is not supported.
403
440
        """
404
441
        self.control_files.leave_in_place()
460
497
        branch.
461
498
        """
462
499
        return None
463
 
    
 
500
 
464
501
    def get_old_bound_location(self):
465
502
        """Return the URL of the branch we used to be bound to
466
503
        """
467
504
        raise errors.UpgradeRequired(self.base)
468
505
 
469
 
    def get_commit_builder(self, parents, config=None, timestamp=None, 
470
 
                           timezone=None, committer=None, revprops=None, 
 
506
    def get_commit_builder(self, parents, config=None, timestamp=None,
 
507
                           timezone=None, committer=None, revprops=None,
471
508
                           revision_id=None):
472
509
        """Obtain a CommitBuilder for this branch.
473
 
        
 
510
 
474
511
        :param parents: Revision ids of the parents of the new revision.
475
512
        :param config: Optional configuration to use.
476
513
        :param timestamp: Optional timestamp recorded for commit.
482
519
 
483
520
        if config is None:
484
521
            config = self.get_config()
485
 
        
 
522
 
486
523
        return self.repository.get_commit_builder(self, parents, config,
487
524
            timestamp, timezone, committer, revprops, revision_id)
488
525
 
489
526
    def get_master_branch(self, possible_transports=None):
490
527
        """Return the branch we are bound to.
491
 
        
 
528
 
492
529
        :return: Either a Branch, or None
493
530
        """
494
531
        return None
565
602
 
566
603
    def _gen_revision_history(self):
567
604
        """Return sequence of revision hashes on to this branch.
568
 
        
 
605
 
569
606
        Unlike revision_history, this method always regenerates or rereads the
570
607
        revision history, i.e. it does not cache the result, so repeated calls
571
608
        may be expensive.
572
609
 
573
610
        Concrete subclasses should override this instead of revision_history so
574
611
        that subclasses do not need to deal with caching logic.
575
 
        
 
612
 
576
613
        This API is semi-public; it only for use by subclasses, all other code
577
614
        should consider it to be private.
578
615
        """
581
618
    @needs_read_lock
582
619
    def revision_history(self):
583
620
        """Return sequence of revision ids on this branch.
584
 
        
 
621
 
585
622
        This method will cache the revision history for as long as it is safe to
586
623
        do so.
587
624
        """
635
672
    @deprecated_method(deprecated_in((1, 6, 0)))
636
673
    def missing_revisions(self, other, stop_revision=None):
637
674
        """Return a list of new revisions that would perfectly fit.
638
 
        
 
675
 
639
676
        If self and other have not diverged, return a list of the revisions
640
677
        present in other, but missing from self.
641
678
        """
668
705
            information. This can be None.
669
706
        :return: None
670
707
        """
671
 
        other.lock_read()
672
 
        try:
673
 
            other_revno, other_last_revision = other.last_revision_info()
674
 
            stop_revno = None # unknown
675
 
            if stop_revision is None:
676
 
                stop_revision = other_last_revision
677
 
                if _mod_revision.is_null(stop_revision):
678
 
                    # if there are no commits, we're done.
679
 
                    return
680
 
                stop_revno = other_revno
681
 
 
682
 
            # what's the current last revision, before we fetch [and change it
683
 
            # possibly]
684
 
            last_rev = _mod_revision.ensure_null(self.last_revision())
685
 
            # we fetch here so that we don't process data twice in the common
686
 
            # case of having something to pull, and so that the check for 
687
 
            # already merged can operate on the just fetched graph, which will
688
 
            # be cached in memory.
689
 
            self.fetch(other, stop_revision)
690
 
            # Check to see if one is an ancestor of the other
691
 
            if not overwrite:
692
 
                if graph is None:
693
 
                    graph = self.repository.get_graph()
694
 
                if self._check_if_descendant_or_diverged(
695
 
                        stop_revision, last_rev, graph, other):
696
 
                    # stop_revision is a descendant of last_rev, but we aren't
697
 
                    # overwriting, so we're done.
698
 
                    return
699
 
            if stop_revno is None:
700
 
                if graph is None:
701
 
                    graph = self.repository.get_graph()
702
 
                this_revno, this_last_revision = self.last_revision_info()
703
 
                stop_revno = graph.find_distance_to_null(stop_revision,
704
 
                                [(other_last_revision, other_revno),
705
 
                                 (this_last_revision, this_revno)])
706
 
            self.set_last_revision_info(stop_revno, stop_revision)
707
 
        finally:
708
 
            other.unlock()
 
708
        return InterBranch.get(other, self).update_revisions(stop_revision,
 
709
            overwrite, graph)
709
710
 
710
711
    def revision_id_to_revno(self, revision_id):
711
712
        """Given a revision id, return its revno"""
751
752
    def get_parent(self):
752
753
        """Return the parent location of the branch.
753
754
 
754
 
        This is the default location for push/pull/missing.  The usual
 
755
        This is the default location for pull/missing.  The usual
755
756
        pattern is that the user can override it by specifying a
756
757
        location.
757
758
        """
819
820
        """Set a new push location for this branch."""
820
821
        raise NotImplementedError(self.set_push_location)
821
822
 
 
823
    def _run_post_change_branch_tip_hooks(self, old_revno, old_revid):
 
824
        """Run the post_change_branch_tip hooks."""
 
825
        hooks = Branch.hooks['post_change_branch_tip']
 
826
        if not hooks:
 
827
            return
 
828
        new_revno, new_revid = self.last_revision_info()
 
829
        params = ChangeBranchTipParams(
 
830
            self, old_revno, new_revno, old_revid, new_revid)
 
831
        for hook in hooks:
 
832
            hook(params)
 
833
 
 
834
    def _run_pre_change_branch_tip_hooks(self, new_revno, new_revid):
 
835
        """Run the pre_change_branch_tip hooks."""
 
836
        hooks = Branch.hooks['pre_change_branch_tip']
 
837
        if not hooks:
 
838
            return
 
839
        old_revno, old_revid = self.last_revision_info()
 
840
        params = ChangeBranchTipParams(
 
841
            self, old_revno, new_revno, old_revid, new_revid)
 
842
        for hook in hooks:
 
843
            try:
 
844
                hook(params)
 
845
            except errors.TipChangeRejected:
 
846
                raise
 
847
            except Exception:
 
848
                exc_info = sys.exc_info()
 
849
                hook_name = Branch.hooks.get_hook_name(hook)
 
850
                raise errors.HookFailed(
 
851
                    'pre_change_branch_tip', hook_name, exc_info)
 
852
 
822
853
    def set_parent(self, url):
823
854
        raise NotImplementedError(self.set_parent)
824
855
 
825
856
    @needs_write_lock
826
857
    def update(self):
827
 
        """Synchronise this branch with the master branch if any. 
 
858
        """Synchronise this branch with the master branch if any.
828
859
 
829
860
        :return: None or the last_revision pivoted out during the update.
830
861
        """
837
868
        """
838
869
        if revno != 0:
839
870
            self.check_real_revno(revno)
840
 
            
 
871
 
841
872
    def check_real_revno(self, revno):
842
873
        """\
843
874
        Check whether a revno corresponds to a real revision.
847
878
            raise errors.InvalidRevisionNumber(revno)
848
879
 
849
880
    @needs_read_lock
850
 
    def clone(self, to_bzrdir, revision_id=None):
 
881
    def clone(self, to_bzrdir, revision_id=None, repository_policy=None):
851
882
        """Clone this branch into to_bzrdir preserving all semantic values.
852
 
        
 
883
 
 
884
        Most API users will want 'create_clone_on_transport', which creates a
 
885
        new bzrdir and branch on the fly.
 
886
 
853
887
        revision_id: if not None, the revision history in the new branch will
854
888
                     be truncated to end with revision_id.
855
889
        """
856
890
        result = to_bzrdir.create_branch()
 
891
        if repository_policy is not None:
 
892
            repository_policy.configure_branch(result)
857
893
        self.copy_content_into(result, revision_id=revision_id)
858
894
        return  result
859
895
 
899
935
            revno = len(list(self.repository.iter_reverse_revision_history(
900
936
                                                                revision_id)))
901
937
        destination.set_last_revision_info(revno, revision_id)
902
 
    
 
938
 
903
939
    @needs_read_lock
904
940
    def copy_content_into(self, destination, revision_id=None):
905
941
        """Copy the content of self into destination.
915
951
        else:
916
952
            if parent:
917
953
                destination.set_parent(parent)
918
 
        self.tags.merge_to(destination.tags)
 
954
        if self._push_should_merge_tags():
 
955
            self.tags.merge_to(destination.tags)
919
956
 
920
957
    @needs_read_lock
921
958
    def check(self):
922
959
        """Check consistency of the branch.
923
960
 
924
961
        In particular this checks that revisions given in the revision-history
925
 
        do actually match up in the revision graph, and that they're all 
 
962
        do actually match up in the revision graph, and that they're all
926
963
        present in the repository.
927
 
        
 
964
 
928
965
        Callers will typically also want to check the repository.
929
966
 
930
967
        :return: A BranchCheckResult.
969
1006
            format.set_branch_format(self._format)
970
1007
        return format
971
1008
 
 
1009
    def create_clone_on_transport(self, to_transport, revision_id=None,
 
1010
        stacked_on=None):
 
1011
        """Create a clone of this branch and its bzrdir.
 
1012
 
 
1013
        :param to_transport: The transport to clone onto.
 
1014
        :param revision_id: The revision id to use as tip in the new branch.
 
1015
            If None the tip is obtained from this branch.
 
1016
        :param stacked_on: An optional URL to stack the clone on.
 
1017
        """
 
1018
        # XXX: Fix the bzrdir API to allow getting the branch back from the
 
1019
        # clone call. Or something. 20090224 RBC/spiv.
 
1020
        dir_to = self.bzrdir.clone_on_transport(to_transport,
 
1021
            revision_id=revision_id, stacked_on=stacked_on)
 
1022
        return dir_to.open_branch()
 
1023
 
972
1024
    def create_checkout(self, to_location, revision_id=None,
973
1025
                        lightweight=False, accelerator_tree=None,
974
1026
                        hardlink=False):
975
1027
        """Create a checkout of a branch.
976
 
        
 
1028
 
977
1029
        :param to_location: The url to produce the checkout at
978
1030
        :param revision_id: The revision to check out
979
1031
        :param lightweight: If True, produce a lightweight checkout, otherwise,
998
1050
                to_location, force_new_tree=False, format=format)
999
1051
            checkout = checkout_branch.bzrdir
1000
1052
            checkout_branch.bind(self)
1001
 
            # pull up to the specified revision_id to set the initial 
 
1053
            # pull up to the specified revision_id to set the initial
1002
1054
            # branch tip correctly, and seed it with history.
1003
1055
            checkout_branch.pull(self, stop_revision=revision_id)
1004
1056
            from_branch=None
1043
1095
        """Ensure that revision_b is a descendant of revision_a.
1044
1096
 
1045
1097
        This is a helper function for update_revisions.
1046
 
        
 
1098
 
1047
1099
        :raises: DivergedBranches if revision_b has diverged from revision_a.
1048
1100
        :returns: True if revision_b is a descendant of revision_a.
1049
1101
        """
1059
1111
 
1060
1112
    def _revision_relations(self, revision_a, revision_b, graph):
1061
1113
        """Determine the relationship between two revisions.
1062
 
        
 
1114
 
1063
1115
        :returns: One of: 'a_descends_from_b', 'b_descends_from_a', 'diverged'
1064
1116
        """
1065
1117
        heads = graph.heads([revision_a, revision_b])
1082
1134
     * a format string,
1083
1135
     * an open routine.
1084
1136
 
1085
 
    Formats are placed in an dict by their format string for reference 
 
1137
    Formats are placed in an dict by their format string for reference
1086
1138
    during branch opening. Its not required that these be instances, they
1087
 
    can be classes themselves with class methods - it simply depends on 
 
1139
    can be classes themselves with class methods - it simply depends on
1088
1140
    whether state is needed for a given format or not.
1089
1141
 
1090
1142
    Once a format is deprecated, just deprecate the initialize and open
1091
 
    methods on the format class. Do not deprecate the object, as the 
 
1143
    methods on the format class. Do not deprecate the object, as the
1092
1144
    object will be created every time regardless.
1093
1145
    """
1094
1146
 
1196
1248
        """Is this format supported?
1197
1249
 
1198
1250
        Supported formats can be initialized and opened.
1199
 
        Unsupported formats may not support initialization or committing or 
 
1251
        Unsupported formats may not support initialization or committing or
1200
1252
        some other features depending on the reason for not being supported.
1201
1253
        """
1202
1254
        return True
1203
1255
 
 
1256
    def network_name(self):
 
1257
        """A simple byte string uniquely identifying this format for RPC calls.
 
1258
 
 
1259
        MetaDir branch formats use their disk format string to identify the
 
1260
        repository over the wire. All in one formats such as bzr < 0.8, and
 
1261
        foreign formats like svn/git and hg should use some marker which is
 
1262
        unique and immutable.
 
1263
        """
 
1264
        raise NotImplementedError(self.network_name)
 
1265
 
1204
1266
    def open(self, a_bzrdir, _found=False):
1205
1267
        """Return the branch object for a_bzrdir
1206
1268
 
1211
1273
 
1212
1274
    @classmethod
1213
1275
    def register_format(klass, format):
 
1276
        """Register a metadir format."""
1214
1277
        klass._formats[format.get_format_string()] = format
 
1278
        # Metadir formats have a network name of their format string.
 
1279
        network_format_registry.register(format.get_format_string(), format)
1215
1280
 
1216
1281
    @classmethod
1217
1282
    def set_default_format(klass, format):
1226
1291
        del klass._formats[format.get_format_string()]
1227
1292
 
1228
1293
    def __str__(self):
1229
 
        return self.get_format_string().rstrip()
 
1294
        return self.get_format_description().rstrip()
1230
1295
 
1231
1296
    def supports_tags(self):
1232
1297
        """True if this format supports tags stored in the branch"""
1235
1300
 
1236
1301
class BranchHooks(Hooks):
1237
1302
    """A dictionary mapping hook name to a list of callables for branch hooks.
1238
 
    
 
1303
 
1239
1304
    e.g. ['set_rh'] Is the list of items to be called when the
1240
1305
    set_revision_history function is invoked.
1241
1306
    """
1260
1325
        # (push_result)
1261
1326
        # containing the members
1262
1327
        # (source, local, master, old_revno, old_revid, new_revno, new_revid)
1263
 
        # where local is the local target branch or None, master is the target 
 
1328
        # where local is the local target branch or None, master is the target
1264
1329
        # master branch, and the rest should be self explanatory. The source
1265
1330
        # is read locked and the target branches write locked. Source will
1266
1331
        # be the local low-latency branch.
1270
1335
        # (pull_result)
1271
1336
        # containing the members
1272
1337
        # (source, local, master, old_revno, old_revid, new_revno, new_revid)
1273
 
        # where local is the local branch or None, master is the target 
 
1338
        # where local is the local branch or None, master is the target
1274
1339
        # master branch, and the rest should be self explanatory. The source
1275
1340
        # is read locked and the target branches write locked. The local
1276
1341
        # branch is the low-latency branch.
1286
1351
        # CommitBuilder.revision_tree() and hooks MUST NOT modify this tree
1287
1352
        self['pre_commit'] = []
1288
1353
        # invoked after a commit operation completes.
1289
 
        # the api signature is 
 
1354
        # the api signature is
1290
1355
        # (local, master, old_revno, old_revid, new_revno, new_revid)
1291
1356
        # old_revid is NULL_REVISION for the first commit to a branch.
1292
1357
        self['post_commit'] = []
1353
1418
 
1354
1419
    def __eq__(self, other):
1355
1420
        return self.__dict__ == other.__dict__
1356
 
    
 
1421
 
1357
1422
    def __repr__(self):
1358
1423
        return "<%s of %s from (%s, %s) to (%s, %s)>" % (
1359
 
            self.__class__.__name__, self.branch, 
 
1424
            self.__class__.__name__, self.branch,
1360
1425
            self.old_revno, self.old_revid, self.new_revno, self.new_revid)
1361
1426
 
1362
1427
 
1384
1449
        super(BzrBranchFormat4, self).__init__()
1385
1450
        self._matchingbzrdir = bzrdir.BzrDirFormat6()
1386
1451
 
 
1452
    def network_name(self):
 
1453
        """The network name for this format is the control dirs disk label."""
 
1454
        return self._matchingbzrdir.get_format_string()
 
1455
 
1387
1456
    def open(self, a_bzrdir, _found=False):
1388
1457
        """Return the branch object for a_bzrdir
1389
1458
 
1409
1478
        """What class to instantiate on open calls."""
1410
1479
        raise NotImplementedError(self._branch_class)
1411
1480
 
 
1481
    def network_name(self):
 
1482
        """A simple byte string uniquely identifying this format for RPC calls.
 
1483
 
 
1484
        Metadir branch formats use their format string.
 
1485
        """
 
1486
        return self.get_format_string()
 
1487
 
1412
1488
    def open(self, a_bzrdir, _found=False):
1413
1489
        """Return the branch object for a_bzrdir.
1414
1490
 
1463
1539
    def get_format_description(self):
1464
1540
        """See BranchFormat.get_format_description()."""
1465
1541
        return "Branch format 5"
1466
 
        
 
1542
 
1467
1543
    def initialize(self, a_bzrdir):
1468
1544
        """Create a branch of this format in a_bzrdir."""
1469
1545
        utf8_files = [('revision-history', ''),
1594
1670
 
1595
1671
    def _make_reference_clone_function(format, a_branch):
1596
1672
        """Create a clone() routine for a branch dynamically."""
1597
 
        def clone(to_bzrdir, revision_id=None):
 
1673
        def clone(to_bzrdir, revision_id=None,
 
1674
            repository_policy=None):
1598
1675
            """See Branch.clone()."""
1599
1676
            return format.initialize(to_bzrdir, a_branch)
1600
1677
            # cannot obey revision_id limits when cloning a reference ...
1631
1708
        return result
1632
1709
 
1633
1710
 
 
1711
network_format_registry = registry.FormatRegistry()
 
1712
"""Registry of formats indexed by their network name.
 
1713
 
 
1714
The network name for a repository format is an identifier that can be used when
 
1715
referring to formats with smart server operations. See
 
1716
BranchFormat.network_name() for more detail.
 
1717
"""
 
1718
 
 
1719
 
1634
1720
# formats which have no format string are not discoverable
1635
1721
# and not independently creatable, so are not registered.
1636
1722
__format5 = BzrBranchFormat5()
1642
1728
BranchFormat.register_format(__format7)
1643
1729
BranchFormat.set_default_format(__format6)
1644
1730
_legacy_formats = [BzrBranchFormat4(),
1645
 
                   ]
 
1731
    ]
 
1732
network_format_registry.register(
 
1733
    _legacy_formats[0].network_name(), _legacy_formats[0])
 
1734
 
1646
1735
 
1647
1736
class BzrBranch(Branch):
1648
1737
    """A branch stored in the actual filesystem.
1651
1740
    really matter if it's on an nfs/smb/afs/coda/... share, as long as
1652
1741
    it's writable, and can be accessed via the normal filesystem API.
1653
1742
 
1654
 
    :ivar _transport: Transport for file operations on this branch's 
 
1743
    :ivar _transport: Transport for file operations on this branch's
1655
1744
        control files, typically pointing to the .bzr/branch directory.
1656
1745
    :ivar repository: Repository for this branch.
1657
 
    :ivar base: The url of the base directory for this branch; the one 
 
1746
    :ivar base: The url of the base directory for this branch; the one
1658
1747
        containing the .bzr directory.
1659
1748
    """
1660
 
    
 
1749
 
1661
1750
    def __init__(self, _format=None,
1662
1751
                 _control_files=None, a_bzrdir=None, _repository=None):
1663
1752
        """Create new branch object at a particular location."""
1717
1806
        if not self.control_files.is_locked():
1718
1807
            # we just released the lock
1719
1808
            self._clear_cached_state()
1720
 
        
 
1809
 
1721
1810
    def peek_lock_mode(self):
1722
1811
        if self.control_files._lock_count == 0:
1723
1812
            return None
1795
1884
                new_history = rev.get_history(self.repository)[1:]
1796
1885
        destination.set_revision_history(new_history)
1797
1886
 
1798
 
    def _run_pre_change_branch_tip_hooks(self, new_revno, new_revid):
1799
 
        """Run the pre_change_branch_tip hooks."""
1800
 
        hooks = Branch.hooks['pre_change_branch_tip']
1801
 
        if not hooks:
1802
 
            return
1803
 
        old_revno, old_revid = self.last_revision_info()
1804
 
        params = ChangeBranchTipParams(
1805
 
            self, old_revno, new_revno, old_revid, new_revid)
1806
 
        for hook in hooks:
1807
 
            try:
1808
 
                hook(params)
1809
 
            except errors.TipChangeRejected:
1810
 
                raise
1811
 
            except Exception:
1812
 
                exc_info = sys.exc_info()
1813
 
                hook_name = Branch.hooks.get_hook_name(hook)
1814
 
                raise errors.HookFailed(
1815
 
                    'pre_change_branch_tip', hook_name, exc_info)
1816
 
 
1817
 
    def _run_post_change_branch_tip_hooks(self, old_revno, old_revid):
1818
 
        """Run the post_change_branch_tip hooks."""
1819
 
        hooks = Branch.hooks['post_change_branch_tip']
1820
 
        if not hooks:
1821
 
            return
1822
 
        new_revno, new_revid = self.last_revision_info()
1823
 
        params = ChangeBranchTipParams(
1824
 
            self, old_revno, new_revno, old_revid, new_revid)
1825
 
        for hook in hooks:
1826
 
            hook(params)
1827
 
 
1828
1887
    @needs_write_lock
1829
1888
    def set_last_revision_info(self, revno, revision_id):
1830
1889
        """Set the last revision of this branch.
1833
1892
        for this revision id.
1834
1893
 
1835
1894
        It may be possible to set the branch last revision to an id not
1836
 
        present in the repository.  However, branches can also be 
 
1895
        present in the repository.  However, branches can also be
1837
1896
        configured to check constraints on history, in which case this may not
1838
1897
        be permitted.
1839
1898
        """
1853
1912
            history.pop()
1854
1913
        return history
1855
1914
 
1856
 
    def _lefthand_history(self, revision_id, last_rev=None,
1857
 
                          other_branch=None):
1858
 
        if 'evil' in debug.debug_flags:
1859
 
            mutter_callsite(4, "_lefthand_history scales with history.")
1860
 
        # stop_revision must be a descendant of last_revision
1861
 
        graph = self.repository.get_graph()
1862
 
        if last_rev is not None:
1863
 
            if not graph.is_ancestor(last_rev, revision_id):
1864
 
                # our previous tip is not merged into stop_revision
1865
 
                raise errors.DivergedBranches(self, other_branch)
1866
 
        # make a new revision history from the graph
1867
 
        parents_map = graph.get_parent_map([revision_id])
1868
 
        if revision_id not in parents_map:
1869
 
            raise errors.NoSuchRevision(self, revision_id)
1870
 
        current_rev_id = revision_id
1871
 
        new_history = []
1872
 
        check_not_reserved_id = _mod_revision.check_not_reserved_id
1873
 
        # Do not include ghosts or graph origin in revision_history
1874
 
        while (current_rev_id in parents_map and
1875
 
               len(parents_map[current_rev_id]) > 0):
1876
 
            check_not_reserved_id(current_rev_id)
1877
 
            new_history.append(current_rev_id)
1878
 
            current_rev_id = parents_map[current_rev_id][0]
1879
 
            parents_map = graph.get_parent_map([current_rev_id])
1880
 
        new_history.reverse()
1881
 
        return new_history
1882
 
 
1883
1915
    @needs_write_lock
1884
1916
    def generate_revision_history(self, revision_id, last_rev=None,
1885
1917
        other_branch=None):
1904
1936
             _override_hook_target=None):
1905
1937
        """See Branch.pull.
1906
1938
 
1907
 
        :param _hook_master: Private parameter - set the branch to 
 
1939
        :param _hook_master: Private parameter - set the branch to
1908
1940
            be supplied as the master to pull hooks.
1909
1941
        :param run_hooks: Private parameter - if false, this branch
1910
1942
            is being called because it's the master of the primary branch,
1958
1990
        This is the basic concrete implementation of push()
1959
1991
 
1960
1992
        :param _override_hook_source_branch: If specified, run
1961
 
        the hooks passing this Branch as the source, rather than self.  
 
1993
        the hooks passing this Branch as the source, rather than self.
1962
1994
        This is for use of RemoteBranch, where push is delegated to the
1963
 
        underlying vfs-based Branch. 
 
1995
        underlying vfs-based Branch.
1964
1996
        """
1965
1997
        # TODO: Public option to disable running hooks - should be trivial but
1966
1998
        # needs tests.
1973
2005
            stop_revision,
1974
2006
            _override_hook_source_branch=None):
1975
2007
        """Push from self into target, and into target's master if any.
1976
 
        
1977
 
        This is on the base BzrBranch class even though it doesn't support 
 
2008
 
 
2009
        This is on the base BzrBranch class even though it doesn't support
1978
2010
        bound branches because the *target* might be bound.
1979
2011
        """
1980
2012
        def _run_hooks():
2035
2067
        result.new_revno, result.new_revid = target.last_revision_info()
2036
2068
        return result
2037
2069
 
2038
 
    def _push_should_merge_tags(self):
2039
 
        """Should _basic_push merge this branch's tags into the target?
2040
 
        
2041
 
        The default implementation returns False if this branch has no tags,
2042
 
        and True the rest of the time.  Subclasses may override this.
2043
 
        """
2044
 
        return self.tags.supports_tags() and self.tags.get_tag_dict()
2045
 
 
2046
2070
    def get_parent(self):
2047
2071
        """See Branch.get_parent."""
2048
2072
        parent = self._get_parent_location()
2106
2130
             run_hooks=True, possible_transports=None,
2107
2131
             _override_hook_target=None):
2108
2132
        """Pull from source into self, updating my master if any.
2109
 
        
 
2133
 
2110
2134
        :param run_hooks: Private parameter - if false, this branch
2111
2135
            is being called because it's the master of the primary branch,
2112
2136
            so it should not run its hooks.
2139
2163
    @needs_read_lock
2140
2164
    def get_master_branch(self, possible_transports=None):
2141
2165
        """Return the branch we are bound to.
2142
 
        
 
2166
 
2143
2167
        :return: Either a Branch, or None
2144
2168
 
2145
2169
        This could memoise the branch, but if thats done
2181
2205
        check for divergence to raise an error when the branches are not
2182
2206
        either the same, or one a prefix of the other. That behaviour may not
2183
2207
        be useful, so that check may be removed in future.
2184
 
        
 
2208
 
2185
2209
        :param other: The branch to bind to
2186
2210
        :type other: Branch
2187
2211
        """
2206
2230
 
2207
2231
    @needs_write_lock
2208
2232
    def update(self, possible_transports=None):
2209
 
        """Synchronise this branch with the master branch if any. 
 
2233
        """Synchronise this branch with the master branch if any.
2210
2234
 
2211
2235
        :return: None or the last_revision that was pivoted out during the
2212
2236
                 update.
2303
2327
 
2304
2328
    def _synchronize_history(self, destination, revision_id):
2305
2329
        """Synchronize last revision and revision history between branches.
2306
 
        
 
2330
 
2307
2331
        :see: Branch._synchronize_history
2308
2332
        """
2309
2333
        # XXX: The base Branch has a fast implementation of this method based
2589
2613
    def report(self, to_file):
2590
2614
        """Write a human-readable description of the result."""
2591
2615
        if self.old_revid == self.new_revid:
2592
 
            to_file.write('No new revisions to push.\n')
 
2616
            note('No new revisions to push.')
2593
2617
        else:
2594
 
            to_file.write('Pushed up to revision %d.\n' % self.new_revno)
 
2618
            note('Pushed up to revision %d.' % self.new_revno)
2595
2619
        self._show_tag_conficts(to_file)
2596
2620
 
2597
2621
 
2606
2630
 
2607
2631
    def report_results(self, verbose):
2608
2632
        """Report the check results via trace.note.
2609
 
        
 
2633
 
2610
2634
        :param verbose: Requests more detailed display of what was checked,
2611
2635
            if any.
2612
2636
        """
2672
2696
            return callable(*args, **kwargs)
2673
2697
        finally:
2674
2698
            target.unlock()
2675
 
    
 
2699
 
2676
2700
    """
2677
2701
    # This is very similar to bzrlib.decorators.needs_write_lock.  Perhaps they
2678
2702
    # should share code?
2688
2712
    else:
2689
2713
        target.unlock()
2690
2714
        return result
 
2715
 
 
2716
 
 
2717
class InterBranch(InterObject):
 
2718
    """This class represents operations taking place between two branches.
 
2719
 
 
2720
    Its instances have methods like pull() and push() and contain
 
2721
    references to the source and target repositories these operations
 
2722
    can be carried out on.
 
2723
    """
 
2724
 
 
2725
    _optimisers = []
 
2726
    """The available optimised InterBranch types."""
 
2727
 
 
2728
    @staticmethod
 
2729
    def _get_branch_formats_to_test():
 
2730
        """Return a tuple with the Branch formats to use when testing."""
 
2731
        raise NotImplementedError(self._get_branch_formats_to_test)
 
2732
 
 
2733
    def update_revisions(self, stop_revision=None, overwrite=False,
 
2734
                         graph=None):
 
2735
        """Pull in new perfect-fit revisions.
 
2736
 
 
2737
        :param stop_revision: Updated until the given revision
 
2738
        :param overwrite: Always set the branch pointer, rather than checking
 
2739
            to see if it is a proper descendant.
 
2740
        :param graph: A Graph object that can be used to query history
 
2741
            information. This can be None.
 
2742
        :return: None
 
2743
        """
 
2744
        raise NotImplementedError(self.update_revisions)
 
2745
 
 
2746
 
 
2747
class GenericInterBranch(InterBranch):
 
2748
    """InterBranch implementation that uses public Branch functions.
 
2749
    """
 
2750
 
 
2751
    @staticmethod
 
2752
    def _get_branch_formats_to_test():
 
2753
        return BranchFormat._default_format, BranchFormat._default_format
 
2754
 
 
2755
    def update_revisions(self, stop_revision=None, overwrite=False,
 
2756
        graph=None):
 
2757
        """See InterBranch.update_revisions()."""
 
2758
        self.source.lock_read()
 
2759
        try:
 
2760
            other_revno, other_last_revision = self.source.last_revision_info()
 
2761
            stop_revno = None # unknown
 
2762
            if stop_revision is None:
 
2763
                stop_revision = other_last_revision
 
2764
                if _mod_revision.is_null(stop_revision):
 
2765
                    # if there are no commits, we're done.
 
2766
                    return
 
2767
                stop_revno = other_revno
 
2768
 
 
2769
            # what's the current last revision, before we fetch [and change it
 
2770
            # possibly]
 
2771
            last_rev = _mod_revision.ensure_null(self.target.last_revision())
 
2772
            # we fetch here so that we don't process data twice in the common
 
2773
            # case of having something to pull, and so that the check for
 
2774
            # already merged can operate on the just fetched graph, which will
 
2775
            # be cached in memory.
 
2776
            self.target.fetch(self.source, stop_revision)
 
2777
            # Check to see if one is an ancestor of the other
 
2778
            if not overwrite:
 
2779
                if graph is None:
 
2780
                    graph = self.target.repository.get_graph()
 
2781
                if self.target._check_if_descendant_or_diverged(
 
2782
                        stop_revision, last_rev, graph, self.source):
 
2783
                    # stop_revision is a descendant of last_rev, but we aren't
 
2784
                    # overwriting, so we're done.
 
2785
                    return
 
2786
            if stop_revno is None:
 
2787
                if graph is None:
 
2788
                    graph = self.target.repository.get_graph()
 
2789
                this_revno, this_last_revision = \
 
2790
                        self.target.last_revision_info()
 
2791
                stop_revno = graph.find_distance_to_null(stop_revision,
 
2792
                                [(other_last_revision, other_revno),
 
2793
                                 (this_last_revision, this_revno)])
 
2794
            self.target.set_last_revision_info(stop_revno, stop_revision)
 
2795
        finally:
 
2796
            self.source.unlock()
 
2797
 
 
2798
    @classmethod
 
2799
    def is_compatible(self, source, target):
 
2800
        # GenericBranch uses the public API, so always compatible
 
2801
        return True
 
2802
 
 
2803
 
 
2804
InterBranch.register_optimiser(GenericInterBranch)