/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

  • Committer: Jelmer Vernooij
  • Date: 2009-02-25 14:36:59 UTC
  • mfrom: (4048 +trunk)
  • mto: This revision was merged to the branch mainline in revision 4049.
  • Revision ID: jelmer@samba.org-20090225143659-vx6cbqtmyicuzfyf
Merge bzr.dev.

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 import registry
48
49
from bzrlib.symbol_versioning import (
49
50
    deprecated_in,
50
51
    deprecated_method,
134
135
    @staticmethod
135
136
    def open_containing(url, possible_transports=None):
136
137
        """Open an existing branch which contains url.
137
 
        
 
138
 
138
139
        This probes for a branch at url, and searches upwards from there.
139
140
 
140
141
        Basically we keep looking up until we find the control directory or
141
142
        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 
 
143
        If there is one and it is either an unrecognised format or an unsupported
143
144
        format, UnknownFormatError or UnsupportedFormatError are raised.
144
145
        If there is one, it is returned, along with the unused portion of url.
145
146
        """
147
148
                                                         possible_transports)
148
149
        return control.open_branch(), relpath
149
150
 
 
151
    def _push_should_merge_tags(self):
 
152
        """Should _basic_push merge this branch's tags into the target?
 
153
 
 
154
        The default implementation returns False if this branch has no tags,
 
155
        and True the rest of the time.  Subclasses may override this.
 
156
        """
 
157
        return self.tags.supports_tags() and self.tags.get_tag_dict()
 
158
 
150
159
    def get_config(self):
151
160
        return BranchConfig(self)
152
161
 
174
183
    def is_locked(self):
175
184
        raise NotImplementedError(self.is_locked)
176
185
 
 
186
    def _lefthand_history(self, revision_id, last_rev=None,
 
187
                          other_branch=None):
 
188
        if 'evil' in debug.debug_flags:
 
189
            mutter_callsite(4, "_lefthand_history scales with history.")
 
190
        # stop_revision must be a descendant of last_revision
 
191
        graph = self.repository.get_graph()
 
192
        if last_rev is not None:
 
193
            if not graph.is_ancestor(last_rev, revision_id):
 
194
                # our previous tip is not merged into stop_revision
 
195
                raise errors.DivergedBranches(self, other_branch)
 
196
        # make a new revision history from the graph
 
197
        parents_map = graph.get_parent_map([revision_id])
 
198
        if revision_id not in parents_map:
 
199
            raise errors.NoSuchRevision(self, revision_id)
 
200
        current_rev_id = revision_id
 
201
        new_history = []
 
202
        check_not_reserved_id = _mod_revision.check_not_reserved_id
 
203
        # Do not include ghosts or graph origin in revision_history
 
204
        while (current_rev_id in parents_map and
 
205
               len(parents_map[current_rev_id]) > 0):
 
206
            check_not_reserved_id(current_rev_id)
 
207
            new_history.append(current_rev_id)
 
208
            current_rev_id = parents_map[current_rev_id][0]
 
209
            parents_map = graph.get_parent_map([current_rev_id])
 
210
        new_history.reverse()
 
211
        return new_history
 
212
 
177
213
    def lock_write(self):
178
214
        raise NotImplementedError(self.lock_write)
179
215
 
228
264
    @needs_read_lock
229
265
    def revision_id_to_dotted_revno(self, revision_id):
230
266
        """Given a revision id, return its dotted revno.
231
 
        
 
267
 
232
268
        :return: a tuple like (1,) or (400,1,3).
233
269
        """
234
270
        return self._do_revision_id_to_dotted_revno(revision_id)
398
434
    def leave_lock_in_place(self):
399
435
        """Tell this branch object not to release the physical lock when this
400
436
        object is unlocked.
401
 
        
 
437
 
402
438
        If lock_write doesn't return a token, then this method is not supported.
403
439
        """
404
440
        self.control_files.leave_in_place()
460
496
        branch.
461
497
        """
462
498
        return None
463
 
    
 
499
 
464
500
    def get_old_bound_location(self):
465
501
        """Return the URL of the branch we used to be bound to
466
502
        """
467
503
        raise errors.UpgradeRequired(self.base)
468
504
 
469
 
    def get_commit_builder(self, parents, config=None, timestamp=None, 
470
 
                           timezone=None, committer=None, revprops=None, 
 
505
    def get_commit_builder(self, parents, config=None, timestamp=None,
 
506
                           timezone=None, committer=None, revprops=None,
471
507
                           revision_id=None):
472
508
        """Obtain a CommitBuilder for this branch.
473
 
        
 
509
 
474
510
        :param parents: Revision ids of the parents of the new revision.
475
511
        :param config: Optional configuration to use.
476
512
        :param timestamp: Optional timestamp recorded for commit.
482
518
 
483
519
        if config is None:
484
520
            config = self.get_config()
485
 
        
 
521
 
486
522
        return self.repository.get_commit_builder(self, parents, config,
487
523
            timestamp, timezone, committer, revprops, revision_id)
488
524
 
489
525
    def get_master_branch(self, possible_transports=None):
490
526
        """Return the branch we are bound to.
491
 
        
 
527
 
492
528
        :return: Either a Branch, or None
493
529
        """
494
530
        return None
565
601
 
566
602
    def _gen_revision_history(self):
567
603
        """Return sequence of revision hashes on to this branch.
568
 
        
 
604
 
569
605
        Unlike revision_history, this method always regenerates or rereads the
570
606
        revision history, i.e. it does not cache the result, so repeated calls
571
607
        may be expensive.
572
608
 
573
609
        Concrete subclasses should override this instead of revision_history so
574
610
        that subclasses do not need to deal with caching logic.
575
 
        
 
611
 
576
612
        This API is semi-public; it only for use by subclasses, all other code
577
613
        should consider it to be private.
578
614
        """
581
617
    @needs_read_lock
582
618
    def revision_history(self):
583
619
        """Return sequence of revision ids on this branch.
584
 
        
 
620
 
585
621
        This method will cache the revision history for as long as it is safe to
586
622
        do so.
587
623
        """
635
671
    @deprecated_method(deprecated_in((1, 6, 0)))
636
672
    def missing_revisions(self, other, stop_revision=None):
637
673
        """Return a list of new revisions that would perfectly fit.
638
 
        
 
674
 
639
675
        If self and other have not diverged, return a list of the revisions
640
676
        present in other, but missing from self.
641
677
        """
683
719
            # possibly]
684
720
            last_rev = _mod_revision.ensure_null(self.last_revision())
685
721
            # 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 
 
722
            # case of having something to pull, and so that the check for
687
723
            # already merged can operate on the just fetched graph, which will
688
724
            # be cached in memory.
689
725
            self.fetch(other, stop_revision)
751
787
    def get_parent(self):
752
788
        """Return the parent location of the branch.
753
789
 
754
 
        This is the default location for push/pull/missing.  The usual
 
790
        This is the default location for pull/missing.  The usual
755
791
        pattern is that the user can override it by specifying a
756
792
        location.
757
793
        """
819
855
        """Set a new push location for this branch."""
820
856
        raise NotImplementedError(self.set_push_location)
821
857
 
 
858
    def _run_post_change_branch_tip_hooks(self, old_revno, old_revid):
 
859
        """Run the post_change_branch_tip hooks."""
 
860
        hooks = Branch.hooks['post_change_branch_tip']
 
861
        if not hooks:
 
862
            return
 
863
        new_revno, new_revid = self.last_revision_info()
 
864
        params = ChangeBranchTipParams(
 
865
            self, old_revno, new_revno, old_revid, new_revid)
 
866
        for hook in hooks:
 
867
            hook(params)
 
868
 
 
869
    def _run_pre_change_branch_tip_hooks(self, new_revno, new_revid):
 
870
        """Run the pre_change_branch_tip hooks."""
 
871
        hooks = Branch.hooks['pre_change_branch_tip']
 
872
        if not hooks:
 
873
            return
 
874
        old_revno, old_revid = self.last_revision_info()
 
875
        params = ChangeBranchTipParams(
 
876
            self, old_revno, new_revno, old_revid, new_revid)
 
877
        for hook in hooks:
 
878
            try:
 
879
                hook(params)
 
880
            except errors.TipChangeRejected:
 
881
                raise
 
882
            except Exception:
 
883
                exc_info = sys.exc_info()
 
884
                hook_name = Branch.hooks.get_hook_name(hook)
 
885
                raise errors.HookFailed(
 
886
                    'pre_change_branch_tip', hook_name, exc_info)
 
887
 
822
888
    def set_parent(self, url):
823
889
        raise NotImplementedError(self.set_parent)
824
890
 
825
891
    @needs_write_lock
826
892
    def update(self):
827
 
        """Synchronise this branch with the master branch if any. 
 
893
        """Synchronise this branch with the master branch if any.
828
894
 
829
895
        :return: None or the last_revision pivoted out during the update.
830
896
        """
837
903
        """
838
904
        if revno != 0:
839
905
            self.check_real_revno(revno)
840
 
            
 
906
 
841
907
    def check_real_revno(self, revno):
842
908
        """\
843
909
        Check whether a revno corresponds to a real revision.
849
915
    @needs_read_lock
850
916
    def clone(self, to_bzrdir, revision_id=None):
851
917
        """Clone this branch into to_bzrdir preserving all semantic values.
852
 
        
 
918
 
 
919
        Most API users will want 'create_clone_on_transport', which creates a
 
920
        new bzrdir and branch on the fly.
 
921
 
853
922
        revision_id: if not None, the revision history in the new branch will
854
923
                     be truncated to end with revision_id.
855
924
        """
899
968
            revno = len(list(self.repository.iter_reverse_revision_history(
900
969
                                                                revision_id)))
901
970
        destination.set_last_revision_info(revno, revision_id)
902
 
    
 
971
 
903
972
    @needs_read_lock
904
973
    def copy_content_into(self, destination, revision_id=None):
905
974
        """Copy the content of self into destination.
915
984
        else:
916
985
            if parent:
917
986
                destination.set_parent(parent)
918
 
        self.tags.merge_to(destination.tags)
 
987
        if self._push_should_merge_tags():
 
988
            self.tags.merge_to(destination.tags)
919
989
 
920
990
    @needs_read_lock
921
991
    def check(self):
922
992
        """Check consistency of the branch.
923
993
 
924
994
        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 
 
995
        do actually match up in the revision graph, and that they're all
926
996
        present in the repository.
927
 
        
 
997
 
928
998
        Callers will typically also want to check the repository.
929
999
 
930
1000
        :return: A BranchCheckResult.
969
1039
            format.set_branch_format(self._format)
970
1040
        return format
971
1041
 
 
1042
    def create_clone_on_transport(self, to_transport, revision_id=None,
 
1043
        stacked_on=None):
 
1044
        """Create a clone of this branch and its bzrdir.
 
1045
 
 
1046
        :param to_transport: The transport to clone onto.
 
1047
        :param revision_id: The revision id to use as tip in the new branch.
 
1048
            If None the tip is obtained from this branch.
 
1049
        :param stacked_on: An optional URL to stack the clone on.
 
1050
        """
 
1051
        # XXX: Fix the bzrdir API to allow getting the branch back from the
 
1052
        # clone call. Or something. 20090224 RBC/spiv.
 
1053
        dir_to = self.bzrdir.clone_on_transport(to_transport,
 
1054
            revision_id=revision_id, stacked_on=stacked_on)
 
1055
        return dir_to.open_branch()
 
1056
 
972
1057
    def create_checkout(self, to_location, revision_id=None,
973
1058
                        lightweight=False, accelerator_tree=None,
974
1059
                        hardlink=False):
975
1060
        """Create a checkout of a branch.
976
 
        
 
1061
 
977
1062
        :param to_location: The url to produce the checkout at
978
1063
        :param revision_id: The revision to check out
979
1064
        :param lightweight: If True, produce a lightweight checkout, otherwise,
998
1083
                to_location, force_new_tree=False, format=format)
999
1084
            checkout = checkout_branch.bzrdir
1000
1085
            checkout_branch.bind(self)
1001
 
            # pull up to the specified revision_id to set the initial 
 
1086
            # pull up to the specified revision_id to set the initial
1002
1087
            # branch tip correctly, and seed it with history.
1003
1088
            checkout_branch.pull(self, stop_revision=revision_id)
1004
1089
            from_branch=None
1043
1128
        """Ensure that revision_b is a descendant of revision_a.
1044
1129
 
1045
1130
        This is a helper function for update_revisions.
1046
 
        
 
1131
 
1047
1132
        :raises: DivergedBranches if revision_b has diverged from revision_a.
1048
1133
        :returns: True if revision_b is a descendant of revision_a.
1049
1134
        """
1059
1144
 
1060
1145
    def _revision_relations(self, revision_a, revision_b, graph):
1061
1146
        """Determine the relationship between two revisions.
1062
 
        
 
1147
 
1063
1148
        :returns: One of: 'a_descends_from_b', 'b_descends_from_a', 'diverged'
1064
1149
        """
1065
1150
        heads = graph.heads([revision_a, revision_b])
1082
1167
     * a format string,
1083
1168
     * an open routine.
1084
1169
 
1085
 
    Formats are placed in an dict by their format string for reference 
 
1170
    Formats are placed in an dict by their format string for reference
1086
1171
    during branch opening. Its not required that these be instances, they
1087
 
    can be classes themselves with class methods - it simply depends on 
 
1172
    can be classes themselves with class methods - it simply depends on
1088
1173
    whether state is needed for a given format or not.
1089
1174
 
1090
1175
    Once a format is deprecated, just deprecate the initialize and open
1091
 
    methods on the format class. Do not deprecate the object, as the 
 
1176
    methods on the format class. Do not deprecate the object, as the
1092
1177
    object will be created every time regardless.
1093
1178
    """
1094
1179
 
1196
1281
        """Is this format supported?
1197
1282
 
1198
1283
        Supported formats can be initialized and opened.
1199
 
        Unsupported formats may not support initialization or committing or 
 
1284
        Unsupported formats may not support initialization or committing or
1200
1285
        some other features depending on the reason for not being supported.
1201
1286
        """
1202
1287
        return True
1203
1288
 
 
1289
    def network_name(self):
 
1290
        """A simple byte string uniquely identifying this format for RPC calls.
 
1291
 
 
1292
        MetaDir branch formats use their disk format string to identify the
 
1293
        repository over the wire. All in one formats such as bzr < 0.8, and
 
1294
        foreign formats like svn/git and hg should use some marker which is
 
1295
        unique and immutable.
 
1296
        """
 
1297
        raise NotImplementedError(self.network_name)
 
1298
 
1204
1299
    def open(self, a_bzrdir, _found=False):
1205
1300
        """Return the branch object for a_bzrdir
1206
1301
 
1211
1306
 
1212
1307
    @classmethod
1213
1308
    def register_format(klass, format):
 
1309
        """Register a metadir format."""
1214
1310
        klass._formats[format.get_format_string()] = format
 
1311
        # Metadir formats have a network name of their format string.
 
1312
        network_format_registry.register(format.get_format_string(), format)
1215
1313
 
1216
1314
    @classmethod
1217
1315
    def set_default_format(klass, format):
1226
1324
        del klass._formats[format.get_format_string()]
1227
1325
 
1228
1326
    def __str__(self):
1229
 
        return self.get_format_string().rstrip()
 
1327
        return self.get_format_description().rstrip()
1230
1328
 
1231
1329
    def supports_tags(self):
1232
1330
        """True if this format supports tags stored in the branch"""
1235
1333
 
1236
1334
class BranchHooks(Hooks):
1237
1335
    """A dictionary mapping hook name to a list of callables for branch hooks.
1238
 
    
 
1336
 
1239
1337
    e.g. ['set_rh'] Is the list of items to be called when the
1240
1338
    set_revision_history function is invoked.
1241
1339
    """
1260
1358
        # (push_result)
1261
1359
        # containing the members
1262
1360
        # (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 
 
1361
        # where local is the local target branch or None, master is the target
1264
1362
        # master branch, and the rest should be self explanatory. The source
1265
1363
        # is read locked and the target branches write locked. Source will
1266
1364
        # be the local low-latency branch.
1270
1368
        # (pull_result)
1271
1369
        # containing the members
1272
1370
        # (source, local, master, old_revno, old_revid, new_revno, new_revid)
1273
 
        # where local is the local branch or None, master is the target 
 
1371
        # where local is the local branch or None, master is the target
1274
1372
        # master branch, and the rest should be self explanatory. The source
1275
1373
        # is read locked and the target branches write locked. The local
1276
1374
        # branch is the low-latency branch.
1286
1384
        # CommitBuilder.revision_tree() and hooks MUST NOT modify this tree
1287
1385
        self['pre_commit'] = []
1288
1386
        # invoked after a commit operation completes.
1289
 
        # the api signature is 
 
1387
        # the api signature is
1290
1388
        # (local, master, old_revno, old_revid, new_revno, new_revid)
1291
1389
        # old_revid is NULL_REVISION for the first commit to a branch.
1292
1390
        self['post_commit'] = []
1353
1451
 
1354
1452
    def __eq__(self, other):
1355
1453
        return self.__dict__ == other.__dict__
1356
 
    
 
1454
 
1357
1455
    def __repr__(self):
1358
1456
        return "<%s of %s from (%s, %s) to (%s, %s)>" % (
1359
 
            self.__class__.__name__, self.branch, 
 
1457
            self.__class__.__name__, self.branch,
1360
1458
            self.old_revno, self.old_revid, self.new_revno, self.new_revid)
1361
1459
 
1362
1460
 
1384
1482
        super(BzrBranchFormat4, self).__init__()
1385
1483
        self._matchingbzrdir = bzrdir.BzrDirFormat6()
1386
1484
 
 
1485
    def network_name(self):
 
1486
        """The network name for this format is the control dirs disk label."""
 
1487
        return self._matchingbzrdir.get_format_string()
 
1488
 
1387
1489
    def open(self, a_bzrdir, _found=False):
1388
1490
        """Return the branch object for a_bzrdir
1389
1491
 
1409
1511
        """What class to instantiate on open calls."""
1410
1512
        raise NotImplementedError(self._branch_class)
1411
1513
 
 
1514
    def network_name(self):
 
1515
        """A simple byte string uniquely identifying this format for RPC calls.
 
1516
 
 
1517
        Metadir branch formats use their format string.
 
1518
        """
 
1519
        return self.get_format_string()
 
1520
 
1412
1521
    def open(self, a_bzrdir, _found=False):
1413
1522
        """Return the branch object for a_bzrdir.
1414
1523
 
1463
1572
    def get_format_description(self):
1464
1573
        """See BranchFormat.get_format_description()."""
1465
1574
        return "Branch format 5"
1466
 
        
 
1575
 
1467
1576
    def initialize(self, a_bzrdir):
1468
1577
        """Create a branch of this format in a_bzrdir."""
1469
1578
        utf8_files = [('revision-history', ''),
1631
1740
        return result
1632
1741
 
1633
1742
 
 
1743
network_format_registry = registry.FormatRegistry()
 
1744
"""Registry of formats indexed by their network name.
 
1745
 
 
1746
The network name for a repository format is an identifier that can be used when
 
1747
referring to formats with smart server operations. See
 
1748
BranchFormat.network_name() for more detail.
 
1749
"""
 
1750
 
 
1751
 
1634
1752
# formats which have no format string are not discoverable
1635
1753
# and not independently creatable, so are not registered.
1636
1754
__format5 = BzrBranchFormat5()
1642
1760
BranchFormat.register_format(__format7)
1643
1761
BranchFormat.set_default_format(__format6)
1644
1762
_legacy_formats = [BzrBranchFormat4(),
1645
 
                   ]
 
1763
    ]
 
1764
network_format_registry.register(
 
1765
    _legacy_formats[0].network_name(), _legacy_formats[0])
 
1766
 
1646
1767
 
1647
1768
class BzrBranch(Branch):
1648
1769
    """A branch stored in the actual filesystem.
1651
1772
    really matter if it's on an nfs/smb/afs/coda/... share, as long as
1652
1773
    it's writable, and can be accessed via the normal filesystem API.
1653
1774
 
1654
 
    :ivar _transport: Transport for file operations on this branch's 
 
1775
    :ivar _transport: Transport for file operations on this branch's
1655
1776
        control files, typically pointing to the .bzr/branch directory.
1656
1777
    :ivar repository: Repository for this branch.
1657
 
    :ivar base: The url of the base directory for this branch; the one 
 
1778
    :ivar base: The url of the base directory for this branch; the one
1658
1779
        containing the .bzr directory.
1659
1780
    """
1660
 
    
 
1781
 
1661
1782
    def __init__(self, _format=None,
1662
1783
                 _control_files=None, a_bzrdir=None, _repository=None):
1663
1784
        """Create new branch object at a particular location."""
1717
1838
        if not self.control_files.is_locked():
1718
1839
            # we just released the lock
1719
1840
            self._clear_cached_state()
1720
 
        
 
1841
 
1721
1842
    def peek_lock_mode(self):
1722
1843
        if self.control_files._lock_count == 0:
1723
1844
            return None
1795
1916
                new_history = rev.get_history(self.repository)[1:]
1796
1917
        destination.set_revision_history(new_history)
1797
1918
 
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
1919
    @needs_write_lock
1829
1920
    def set_last_revision_info(self, revno, revision_id):
1830
1921
        """Set the last revision of this branch.
1833
1924
        for this revision id.
1834
1925
 
1835
1926
        It may be possible to set the branch last revision to an id not
1836
 
        present in the repository.  However, branches can also be 
 
1927
        present in the repository.  However, branches can also be
1837
1928
        configured to check constraints on history, in which case this may not
1838
1929
        be permitted.
1839
1930
        """
1853
1944
            history.pop()
1854
1945
        return history
1855
1946
 
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
1947
    @needs_write_lock
1884
1948
    def generate_revision_history(self, revision_id, last_rev=None,
1885
1949
        other_branch=None):
1904
1968
             _override_hook_target=None):
1905
1969
        """See Branch.pull.
1906
1970
 
1907
 
        :param _hook_master: Private parameter - set the branch to 
 
1971
        :param _hook_master: Private parameter - set the branch to
1908
1972
            be supplied as the master to pull hooks.
1909
1973
        :param run_hooks: Private parameter - if false, this branch
1910
1974
            is being called because it's the master of the primary branch,
1958
2022
        This is the basic concrete implementation of push()
1959
2023
 
1960
2024
        :param _override_hook_source_branch: If specified, run
1961
 
        the hooks passing this Branch as the source, rather than self.  
 
2025
        the hooks passing this Branch as the source, rather than self.
1962
2026
        This is for use of RemoteBranch, where push is delegated to the
1963
 
        underlying vfs-based Branch. 
 
2027
        underlying vfs-based Branch.
1964
2028
        """
1965
2029
        # TODO: Public option to disable running hooks - should be trivial but
1966
2030
        # needs tests.
1973
2037
            stop_revision,
1974
2038
            _override_hook_source_branch=None):
1975
2039
        """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 
 
2040
 
 
2041
        This is on the base BzrBranch class even though it doesn't support
1978
2042
        bound branches because the *target* might be bound.
1979
2043
        """
1980
2044
        def _run_hooks():
2035
2099
        result.new_revno, result.new_revid = target.last_revision_info()
2036
2100
        return result
2037
2101
 
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
2102
    def get_parent(self):
2047
2103
        """See Branch.get_parent."""
2048
2104
        parent = self._get_parent_location()
2106
2162
             run_hooks=True, possible_transports=None,
2107
2163
             _override_hook_target=None):
2108
2164
        """Pull from source into self, updating my master if any.
2109
 
        
 
2165
 
2110
2166
        :param run_hooks: Private parameter - if false, this branch
2111
2167
            is being called because it's the master of the primary branch,
2112
2168
            so it should not run its hooks.
2139
2195
    @needs_read_lock
2140
2196
    def get_master_branch(self, possible_transports=None):
2141
2197
        """Return the branch we are bound to.
2142
 
        
 
2198
 
2143
2199
        :return: Either a Branch, or None
2144
2200
 
2145
2201
        This could memoise the branch, but if thats done
2181
2237
        check for divergence to raise an error when the branches are not
2182
2238
        either the same, or one a prefix of the other. That behaviour may not
2183
2239
        be useful, so that check may be removed in future.
2184
 
        
 
2240
 
2185
2241
        :param other: The branch to bind to
2186
2242
        :type other: Branch
2187
2243
        """
2206
2262
 
2207
2263
    @needs_write_lock
2208
2264
    def update(self, possible_transports=None):
2209
 
        """Synchronise this branch with the master branch if any. 
 
2265
        """Synchronise this branch with the master branch if any.
2210
2266
 
2211
2267
        :return: None or the last_revision that was pivoted out during the
2212
2268
                 update.
2303
2359
 
2304
2360
    def _synchronize_history(self, destination, revision_id):
2305
2361
        """Synchronize last revision and revision history between branches.
2306
 
        
 
2362
 
2307
2363
        :see: Branch._synchronize_history
2308
2364
        """
2309
2365
        # XXX: The base Branch has a fast implementation of this method based
2606
2662
 
2607
2663
    def report_results(self, verbose):
2608
2664
        """Report the check results via trace.note.
2609
 
        
 
2665
 
2610
2666
        :param verbose: Requests more detailed display of what was checked,
2611
2667
            if any.
2612
2668
        """
2672
2728
            return callable(*args, **kwargs)
2673
2729
        finally:
2674
2730
            target.unlock()
2675
 
    
 
2731
 
2676
2732
    """
2677
2733
    # This is very similar to bzrlib.decorators.needs_write_lock.  Perhaps they
2678
2734
    # should share code?