/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: Vincent Ladeuil
  • Date: 2012-01-18 14:09:19 UTC
  • mto: This revision was merged to the branch mainline in revision 6468.
  • Revision ID: v.ladeuil+lp@free.fr-20120118140919-rlvdrhpc0nq1lbwi
Change set/remove to require a lock for the branch config files.

This means that tests (or any plugin for that matter) do not requires an
explicit lock on the branch anymore to change a single option. This also
means the optimisation becomes "opt-in" and as such won't be as
spectacular as it may be and/or harder to get right (nothing fails
anymore).

This reduces the diff by ~300 lines.

Code/tests that were updating more than one config option is still taking
a lock to at least avoid some IOs and demonstrate the benefits through
the decreased number of hpss calls.

The duplication between BranchStack and BranchOnlyStack will be removed
once the same sharing is in place for local config files, at which point
the Stack class itself may be able to host the changes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
39
39
    repository,
40
40
    revision as _mod_revision,
41
41
    rio,
42
 
    shelf,
43
42
    tag as _mod_tag,
44
43
    transport,
45
44
    ui,
252
251
        """
253
252
        raise NotImplementedError(self._get_config)
254
253
 
255
 
    def store_uncommitted(self, creator):
256
 
        """Store uncommitted changes from a ShelfCreator.
257
 
 
258
 
        :param creator: The ShelfCreator containing uncommitted changes, or
259
 
            None to delete any stored changes.
260
 
        :raises: ChangesAlreadyStored if the branch already has changes.
261
 
        """
262
 
        raise NotImplementedError(self.store_uncommitted)
263
 
 
264
 
    def get_unshelver(self, tree):
265
 
        """Return a shelf.Unshelver for this branch and tree.
266
 
 
267
 
        :param tree: The tree to use to construct the Unshelver.
268
 
        :return: an Unshelver or None if no changes are stored.
269
 
        """
270
 
        raise NotImplementedError(self.get_unshelver)
271
 
 
272
254
    def _get_fallback_repository(self, url, possible_transports):
273
255
        """Get the repository we fallback to at url."""
274
256
        url = urlutils.join(self.base, url)
784
766
        """Print `file` to stdout."""
785
767
        raise NotImplementedError(self.print_file)
786
768
 
 
769
    @deprecated_method(deprecated_in((2, 4, 0)))
 
770
    def set_revision_history(self, rev_history):
 
771
        """See Branch.set_revision_history."""
 
772
        self._set_revision_history(rev_history)
 
773
 
 
774
    @needs_write_lock
 
775
    def _set_revision_history(self, rev_history):
 
776
        if len(rev_history) == 0:
 
777
            revid = _mod_revision.NULL_REVISION
 
778
        else:
 
779
            revid = rev_history[-1]
 
780
        if rev_history != self._lefthand_history(revid):
 
781
            raise errors.NotLefthandHistory(rev_history)
 
782
        self.set_last_revision_info(len(rev_history), revid)
 
783
        self._cache_revision_history(rev_history)
 
784
        for hook in Branch.hooks['set_rh']:
 
785
            hook(self, rev_history)
 
786
 
787
787
    @needs_write_lock
788
788
    def set_last_revision_info(self, revno, revision_id):
789
789
        """Set the last revision of this branch.
986
986
        This means the next call to revision_history will need to call
987
987
        _gen_revision_history.
988
988
 
989
 
        This API is semi-public; it is only for use by subclasses, all other
990
 
        code should consider it to be private.
 
989
        This API is semi-public; it only for use by subclasses, all other code
 
990
        should consider it to be private.
991
991
        """
992
992
        self._revision_history_cache = None
993
993
        self._revision_id_to_revno_cache = None
1013
1013
        """
1014
1014
        raise NotImplementedError(self._gen_revision_history)
1015
1015
 
 
1016
    @deprecated_method(deprecated_in((2, 5, 0)))
 
1017
    @needs_read_lock
 
1018
    def revision_history(self):
 
1019
        """Return sequence of revision ids on this branch.
 
1020
 
 
1021
        This method will cache the revision history for as long as it is safe to
 
1022
        do so.
 
1023
        """
 
1024
        return self._revision_history()
 
1025
 
1016
1026
    def _revision_history(self):
1017
1027
        if 'evil' in debug.debug_flags:
1018
1028
            mutter_callsite(3, "revision_history scales with history.")
1052
1062
    def _read_last_revision_info(self):
1053
1063
        raise NotImplementedError(self._read_last_revision_info)
1054
1064
 
 
1065
    @deprecated_method(deprecated_in((2, 4, 0)))
 
1066
    def import_last_revision_info(self, source_repo, revno, revid):
 
1067
        """Set the last revision info, importing from another repo if necessary.
 
1068
 
 
1069
        :param source_repo: Source repository to optionally fetch from
 
1070
        :param revno: Revision number of the new tip
 
1071
        :param revid: Revision id of the new tip
 
1072
        """
 
1073
        if not self.repository.has_same_location(source_repo):
 
1074
            self.repository.fetch(source_repo, revision_id=revid)
 
1075
        self.set_last_revision_info(revno, revid)
 
1076
 
1055
1077
    def import_last_revision_info_and_tags(self, source, revno, revid,
1056
1078
                                           lossy=False):
1057
1079
        """Set the last revision info, importing from another repo if necessary.
1435
1457
        t = transport.get_transport(to_location)
1436
1458
        t.ensure_base()
1437
1459
        format = self._get_checkout_format(lightweight=lightweight)
1438
 
        try:
 
1460
        if lightweight:
1439
1461
            checkout = format.initialize_on_transport(t)
1440
 
        except errors.AlreadyControlDirError:
1441
 
            # It's fine if the control directory already exists,
1442
 
            # as long as there is no existing branch and working tree.
1443
 
            checkout = controldir.ControlDir.open_from_transport(t)
1444
 
            try:
1445
 
                checkout.open_branch()
1446
 
            except errors.NotBranchError:
1447
 
                pass
1448
 
            else:
1449
 
                raise errors.AlreadyControlDirError(t.base)
1450
 
            if checkout.control_transport.base == self.bzrdir.control_transport.base:
1451
 
                # When checking out to the same control directory,
1452
 
                # always create a lightweight checkout
1453
 
                lightweight = True
1454
 
 
1455
 
        if lightweight:
1456
 
            from_branch = checkout.set_branch_reference(target_branch=self)
 
1462
            from_branch = BranchReferenceFormat().initialize(checkout, 
 
1463
                target_branch=self)
1457
1464
        else:
1458
 
            policy = checkout.determine_repository_policy()
1459
 
            repo = policy.acquire_repository()[0]
1460
 
            checkout_branch = checkout.create_branch()
 
1465
            checkout_branch = controldir.ControlDir.create_branch_convenience(
 
1466
                to_location, force_new_tree=False, format=format)
 
1467
            checkout = checkout_branch.bzrdir
1461
1468
            checkout_branch.bind(self)
1462
1469
            # pull up to the specified revision_id to set the initial
1463
1470
            # branch tip correctly, and seed it with history.
1464
1471
            checkout_branch.pull(self, stop_revision=revision_id)
1465
 
            from_branch = None
 
1472
            from_branch=None
1466
1473
        tree = checkout.create_workingtree(revision_id,
1467
1474
                                           from_branch=from_branch,
1468
1475
                                           accelerator_tree=accelerator_tree,
1595
1602
    def __ne__(self, other):
1596
1603
        return not (self == other)
1597
1604
 
 
1605
    @classmethod
 
1606
    @deprecated_method(deprecated_in((2, 4, 0)))
 
1607
    def get_default_format(klass):
 
1608
        """Return the current default format."""
 
1609
        return format_registry.get_default()
 
1610
 
 
1611
    @classmethod
 
1612
    @deprecated_method(deprecated_in((2, 4, 0)))
 
1613
    def get_formats(klass):
 
1614
        """Get all the known formats.
 
1615
 
 
1616
        Warning: This triggers a load of all lazy registered formats: do not
 
1617
        use except when that is desireed.
 
1618
        """
 
1619
        return format_registry._get_all()
 
1620
 
1598
1621
    def get_reference(self, controldir, name=None):
1599
1622
        """Get the target reference of the branch in controldir.
1600
1623
 
1688
1711
        """
1689
1712
        raise NotImplementedError(self.open)
1690
1713
 
 
1714
    @classmethod
 
1715
    @deprecated_method(deprecated_in((2, 4, 0)))
 
1716
    def register_format(klass, format):
 
1717
        """Register a metadir format.
 
1718
 
 
1719
        See MetaDirBranchFormatFactory for the ability to register a format
 
1720
        without loading the code the format needs until it is actually used.
 
1721
        """
 
1722
        format_registry.register(format)
 
1723
 
 
1724
    @classmethod
 
1725
    @deprecated_method(deprecated_in((2, 4, 0)))
 
1726
    def set_default_format(klass, format):
 
1727
        format_registry.set_default(format)
 
1728
 
1691
1729
    def supports_set_append_revisions_only(self):
1692
1730
        """True if this format supports set_append_revisions_only."""
1693
1731
        return False
1700
1738
        """True if this format supports leaving locks in place."""
1701
1739
        return False # by default
1702
1740
 
 
1741
    @classmethod
 
1742
    @deprecated_method(deprecated_in((2, 4, 0)))
 
1743
    def unregister_format(klass, format):
 
1744
        format_registry.remove(format)
 
1745
 
1703
1746
    def __str__(self):
1704
1747
        return self.get_format_description().rstrip()
1705
1748
 
1747
1790
class BranchHooks(Hooks):
1748
1791
    """A dictionary mapping hook name to a list of callables for branch hooks.
1749
1792
 
1750
 
    e.g. ['post_push'] Is the list of items to be called when the
1751
 
    push function is invoked.
 
1793
    e.g. ['set_rh'] Is the list of items to be called when the
 
1794
    set_revision_history function is invoked.
1752
1795
    """
1753
1796
 
1754
1797
    def __init__(self):
1758
1801
        notified.
1759
1802
        """
1760
1803
        Hooks.__init__(self, "bzrlib.branch", "Branch.hooks")
 
1804
        self.add_hook('set_rh',
 
1805
            "Invoked whenever the revision history has been set via "
 
1806
            "set_revision_history. The api signature is (branch, "
 
1807
            "revision_history), and the branch will be write-locked. "
 
1808
            "The set_rh hook can be expensive for bzr to trigger, a better "
 
1809
            "hook to use is Branch.post_change_branch_tip.", (0, 15))
1761
1810
        self.add_hook('open',
1762
1811
            "Called with the Branch object that has been opened after a "
1763
1812
            "branch is opened.", (1, 8))
1981
2030
 
1982
2031
    def _initialize_helper(self, a_bzrdir, utf8_files, name=None,
1983
2032
                           repository=None):
1984
 
        """Initialize a branch in a control dir, with specified files
 
2033
        """Initialize a branch in a bzrdir, with specified files
1985
2034
 
1986
2035
        :param a_bzrdir: The bzrdir to initialize the branch in
1987
2036
        :param utf8_files: The files to create as a list of
1989
2038
        :param name: Name of colocated branch to create, if any
1990
2039
        :return: a branch in this format
1991
2040
        """
1992
 
        if name is None:
1993
 
            name = a_bzrdir._get_selected_branch()
1994
2041
        mutter('creating branch %r in %s', self, a_bzrdir.user_url)
1995
2042
        branch_transport = a_bzrdir.get_branch_transport(self, name=name)
1996
2043
        control_files = lockable_files.LockableFiles(branch_transport,
2013
2060
    def open(self, a_bzrdir, name=None, _found=False, ignore_fallbacks=False,
2014
2061
            found_repository=None, possible_transports=None):
2015
2062
        """See BranchFormat.open()."""
2016
 
        if name is None:
2017
 
            name = a_bzrdir._get_selected_branch()
2018
2063
        if not _found:
2019
2064
            format = BranchFormatMetadir.find_format(a_bzrdir, name=name)
2020
2065
            if format.__class__ != self.__class__:
2057
2102
            recommend_upgrade=recommend_upgrade, basedir=basedir)
2058
2103
 
2059
2104
 
 
2105
class BzrBranchFormat5(BranchFormatMetadir):
 
2106
    """Bzr branch format 5.
 
2107
 
 
2108
    This format has:
 
2109
     - a revision-history file.
 
2110
     - a format string
 
2111
     - a lock dir guarding the branch itself
 
2112
     - all of this stored in a branch/ subdirectory
 
2113
     - works with shared repositories.
 
2114
 
 
2115
    This format is new in bzr 0.8.
 
2116
    """
 
2117
 
 
2118
    def _branch_class(self):
 
2119
        return BzrBranch5
 
2120
 
 
2121
    @classmethod
 
2122
    def get_format_string(cls):
 
2123
        """See BranchFormat.get_format_string()."""
 
2124
        return "Bazaar-NG branch format 5\n"
 
2125
 
 
2126
    def get_format_description(self):
 
2127
        """See BranchFormat.get_format_description()."""
 
2128
        return "Branch format 5"
 
2129
 
 
2130
    def initialize(self, a_bzrdir, name=None, repository=None,
 
2131
                   append_revisions_only=None):
 
2132
        """Create a branch of this format in a_bzrdir."""
 
2133
        if append_revisions_only:
 
2134
            raise errors.UpgradeRequired(a_bzrdir.user_url)
 
2135
        utf8_files = [('revision-history', ''),
 
2136
                      ('branch-name', ''),
 
2137
                      ]
 
2138
        return self._initialize_helper(a_bzrdir, utf8_files, name, repository)
 
2139
 
 
2140
    def supports_tags(self):
 
2141
        return False
 
2142
 
 
2143
 
2060
2144
class BzrBranchFormat6(BranchFormatMetadir):
2061
2145
    """Branch format with last-revision and tags.
2062
2146
 
2221
2305
        mutter('creating branch reference in %s', a_bzrdir.user_url)
2222
2306
        if a_bzrdir._format.fixed_components:
2223
2307
            raise errors.IncompatibleFormat(self, a_bzrdir._format)
2224
 
        if name is None:
2225
 
            name = a_bzrdir._get_selected_branch()
2226
2308
        branch_transport = a_bzrdir.get_branch_transport(self, name=name)
2227
2309
        branch_transport.put_bytes('location',
2228
2310
            target_branch.user_url)
2229
2311
        branch_transport.put_bytes('format', self.as_string())
2230
 
        branch = self.open(a_bzrdir, name, _found=True,
 
2312
        branch = self.open(
 
2313
            a_bzrdir, name, _found=True,
2231
2314
            possible_transports=[target_branch.bzrdir.root_transport])
2232
2315
        self._run_post_branch_init_hooks(a_bzrdir, name, branch)
2233
2316
        return branch
2259
2342
            a_bzrdir.
2260
2343
        :param possible_transports: An optional reusable transports list.
2261
2344
        """
2262
 
        if name is None:
2263
 
            name = a_bzrdir._get_selected_branch()
2264
2345
        if not _found:
2265
2346
            format = BranchFormatMetadir.find_format(a_bzrdir, name=name)
2266
2347
            if format.__class__ != self.__class__:
2270
2351
            location = self.get_reference(a_bzrdir, name)
2271
2352
        real_bzrdir = controldir.ControlDir.open(
2272
2353
            location, possible_transports=possible_transports)
2273
 
        result = real_bzrdir.open_branch(ignore_fallbacks=ignore_fallbacks,
 
2354
        result = real_bzrdir.open_branch(name=name, 
 
2355
            ignore_fallbacks=ignore_fallbacks,
2274
2356
            possible_transports=possible_transports)
2275
2357
        # this changes the behaviour of result.clone to create a new reference
2276
2358
        # rather than a copy of the content of the branch.
2311
2393
 
2312
2394
# formats which have no format string are not discoverable
2313
2395
# and not independently creatable, so are not registered.
 
2396
__format5 = BzrBranchFormat5()
2314
2397
__format6 = BzrBranchFormat6()
2315
2398
__format7 = BzrBranchFormat7()
2316
2399
__format8 = BzrBranchFormat8()
2317
 
format_registry.register_lazy(
2318
 
    "Bazaar-NG branch format 5\n", "bzrlib.branchfmt.fullhistory", "BzrBranchFormat5")
 
2400
format_registry.register(__format5)
2319
2401
format_registry.register(BranchReferenceFormat())
2320
2402
format_registry.register(__format6)
2321
2403
format_registry.register(__format7)
2363
2445
        """Create new branch object at a particular location."""
2364
2446
        if a_bzrdir is None:
2365
2447
            raise ValueError('a_bzrdir must be supplied')
2366
 
        if name is None:
2367
 
            raise ValueError('name must be supplied')
2368
 
        self.bzrdir = a_bzrdir
 
2448
        else:
 
2449
            self.bzrdir = a_bzrdir
2369
2450
        self._user_transport = self.bzrdir.transport.clone('..')
2370
 
        if name != "":
 
2451
        if name is not None:
2371
2452
            self._user_transport.set_segment_parameter(
2372
2453
                "branch", urlutils.escape(name))
2373
2454
        self._base = self._user_transport.base
2404
2485
            self.conf_store =  _mod_config.BranchStore(self)
2405
2486
        return self.conf_store
2406
2487
 
2407
 
    def _uncommitted_branch(self):
2408
 
        """Return the branch that may contain uncommitted changes."""
2409
 
        master = self.get_master_branch()
2410
 
        if master is not None:
2411
 
            return master
2412
 
        else:
2413
 
            return self
2414
 
 
2415
 
    def store_uncommitted(self, creator):
2416
 
        """Store uncommitted changes from a ShelfCreator.
2417
 
 
2418
 
        :param creator: The ShelfCreator containing uncommitted changes, or
2419
 
            None to delete any stored changes.
2420
 
        :raises: ChangesAlreadyStored if the branch already has changes.
2421
 
        """
2422
 
        branch = self._uncommitted_branch()
2423
 
        if creator is None:
2424
 
            branch._transport.delete('stored-transform')
2425
 
            return
2426
 
        if branch._transport.has('stored-transform'):
2427
 
            raise errors.ChangesAlreadyStored
2428
 
        transform = StringIO()
2429
 
        creator.write_shelf(transform)
2430
 
        transform.seek(0)
2431
 
        branch._transport.put_file('stored-transform', transform)
2432
 
 
2433
 
    def get_unshelver(self, tree):
2434
 
        """Return a shelf.Unshelver for this branch and tree.
2435
 
 
2436
 
        :param tree: The tree to use to construct the Unshelver.
2437
 
        :return: an Unshelver or None if no changes are stored.
2438
 
        """
2439
 
        branch = self._uncommitted_branch()
2440
 
        try:
2441
 
            transform = branch._transport.get('stored-transform')
2442
 
        except errors.NoSuchFile:
2443
 
            return None
2444
 
        return shelf.Unshelver.from_tree_and_shelf(tree, transform)
2445
 
 
2446
2488
    def is_locked(self):
2447
2489
        return self.control_files.is_locked()
2448
2490
 
2455
2497
        """
2456
2498
        if not self.is_locked():
2457
2499
            self._note_lock('w')
 
2500
        # All-in-one needs to always unlock/lock.
 
2501
        repo_control = getattr(self.repository, 'control_files', None)
 
2502
        if self.control_files == repo_control or not self.is_locked():
2458
2503
            self.repository._warn_if_deprecated(self)
2459
2504
            self.repository.lock_write()
2460
2505
            took_lock = True
2475
2520
        """
2476
2521
        if not self.is_locked():
2477
2522
            self._note_lock('r')
 
2523
        # All-in-one needs to always unlock/lock.
 
2524
        repo_control = getattr(self.repository, 'control_files', None)
 
2525
        if self.control_files == repo_control or not self.is_locked():
2478
2526
            self.repository._warn_if_deprecated(self)
2479
2527
            self.repository.lock_read()
2480
2528
            took_lock = True
2490
2538
 
2491
2539
    @only_raises(errors.LockNotHeld, errors.LockBroken)
2492
2540
    def unlock(self):
2493
 
        if self.control_files._lock_count == 1 and self.conf_store is not None:
 
2541
        if self.conf_store is not None:
2494
2542
            self.conf_store.save_changes()
2495
2543
        try:
2496
2544
            self.control_files.unlock()
2497
2545
        finally:
 
2546
            # All-in-one needs to always unlock/lock.
 
2547
            repo_control = getattr(self.repository, 'control_files', None)
 
2548
            if (self.control_files == repo_control or
 
2549
                not self.control_files.is_locked()):
 
2550
                self.repository.unlock()
2498
2551
            if not self.control_files.is_locked():
2499
 
                self.repository.unlock()
2500
2552
                # we just released the lock
2501
2553
                self._clear_cached_state()
2502
2554
 
2680
2732
        self.control_transport.put_bytes('format', self._format.as_string())
2681
2733
 
2682
2734
 
 
2735
class FullHistoryBzrBranch(BzrBranch):
 
2736
    """Bzr branch which contains the full revision history."""
 
2737
 
 
2738
    @needs_write_lock
 
2739
    def set_last_revision_info(self, revno, revision_id):
 
2740
        if not revision_id or not isinstance(revision_id, basestring):
 
2741
            raise errors.InvalidRevisionId(revision_id=revision_id, branch=self)
 
2742
        revision_id = _mod_revision.ensure_null(revision_id)
 
2743
        # this old format stores the full history, but this api doesn't
 
2744
        # provide it, so we must generate, and might as well check it's
 
2745
        # correct
 
2746
        history = self._lefthand_history(revision_id)
 
2747
        if len(history) != revno:
 
2748
            raise AssertionError('%d != %d' % (len(history), revno))
 
2749
        self._set_revision_history(history)
 
2750
 
 
2751
    def _read_last_revision_info(self):
 
2752
        rh = self._revision_history()
 
2753
        revno = len(rh)
 
2754
        if revno:
 
2755
            return (revno, rh[-1])
 
2756
        else:
 
2757
            return (0, _mod_revision.NULL_REVISION)
 
2758
 
 
2759
    @deprecated_method(deprecated_in((2, 4, 0)))
 
2760
    @needs_write_lock
 
2761
    def set_revision_history(self, rev_history):
 
2762
        """See Branch.set_revision_history."""
 
2763
        self._set_revision_history(rev_history)
 
2764
 
 
2765
    def _set_revision_history(self, rev_history):
 
2766
        if 'evil' in debug.debug_flags:
 
2767
            mutter_callsite(3, "set_revision_history scales with history.")
 
2768
        check_not_reserved_id = _mod_revision.check_not_reserved_id
 
2769
        for rev_id in rev_history:
 
2770
            check_not_reserved_id(rev_id)
 
2771
        if Branch.hooks['post_change_branch_tip']:
 
2772
            # Don't calculate the last_revision_info() if there are no hooks
 
2773
            # that will use it.
 
2774
            old_revno, old_revid = self.last_revision_info()
 
2775
        if len(rev_history) == 0:
 
2776
            revid = _mod_revision.NULL_REVISION
 
2777
        else:
 
2778
            revid = rev_history[-1]
 
2779
        self._run_pre_change_branch_tip_hooks(len(rev_history), revid)
 
2780
        self._write_revision_history(rev_history)
 
2781
        self._clear_cached_state()
 
2782
        self._cache_revision_history(rev_history)
 
2783
        for hook in Branch.hooks['set_rh']:
 
2784
            hook(self, rev_history)
 
2785
        if Branch.hooks['post_change_branch_tip']:
 
2786
            self._run_post_change_branch_tip_hooks(old_revno, old_revid)
 
2787
 
 
2788
    def _write_revision_history(self, history):
 
2789
        """Factored out of set_revision_history.
 
2790
 
 
2791
        This performs the actual writing to disk.
 
2792
        It is intended to be called by set_revision_history."""
 
2793
        self._transport.put_bytes(
 
2794
            'revision-history', '\n'.join(history),
 
2795
            mode=self.bzrdir._get_file_mode())
 
2796
 
 
2797
    def _gen_revision_history(self):
 
2798
        history = self._transport.get_bytes('revision-history').split('\n')
 
2799
        if history[-1:] == ['']:
 
2800
            # There shouldn't be a trailing newline, but just in case.
 
2801
            history.pop()
 
2802
        return history
 
2803
 
 
2804
    def _synchronize_history(self, destination, revision_id):
 
2805
        if not isinstance(destination, FullHistoryBzrBranch):
 
2806
            super(BzrBranch, self)._synchronize_history(
 
2807
                destination, revision_id)
 
2808
            return
 
2809
        if revision_id == _mod_revision.NULL_REVISION:
 
2810
            new_history = []
 
2811
        else:
 
2812
            new_history = self._revision_history()
 
2813
        if revision_id is not None and new_history != []:
 
2814
            try:
 
2815
                new_history = new_history[:new_history.index(revision_id) + 1]
 
2816
            except ValueError:
 
2817
                rev = self.repository.get_revision(revision_id)
 
2818
                new_history = rev.get_history(self.repository)[1:]
 
2819
        destination._set_revision_history(new_history)
 
2820
 
 
2821
    @needs_write_lock
 
2822
    def generate_revision_history(self, revision_id, last_rev=None,
 
2823
        other_branch=None):
 
2824
        """Create a new revision history that will finish with revision_id.
 
2825
 
 
2826
        :param revision_id: the new tip to use.
 
2827
        :param last_rev: The previous last_revision. If not None, then this
 
2828
            must be a ancestory of revision_id, or DivergedBranches is raised.
 
2829
        :param other_branch: The other branch that DivergedBranches should
 
2830
            raise with respect to.
 
2831
        """
 
2832
        self._set_revision_history(self._lefthand_history(revision_id,
 
2833
            last_rev, other_branch))
 
2834
 
 
2835
 
 
2836
class BzrBranch5(FullHistoryBzrBranch):
 
2837
    """A format 5 branch. This supports new features over plain branches.
 
2838
 
 
2839
    It has support for a master_branch which is the data for bound branches.
 
2840
    """
 
2841
 
 
2842
 
2683
2843
class BzrBranch8(BzrBranch):
2684
2844
    """A branch that stores tree-reference locations."""
2685
2845
 
2965
3125
    :ivar tag_updates: A dict with new tags, see BasicTags.merge_to
2966
3126
    """
2967
3127
 
 
3128
    @deprecated_method(deprecated_in((2, 3, 0)))
 
3129
    def __int__(self):
 
3130
        """Return the relative change in revno.
 
3131
 
 
3132
        :deprecated: Use `new_revno` and `old_revno` instead.
 
3133
        """
 
3134
        return self.new_revno - self.old_revno
 
3135
 
2968
3136
    def report(self, to_file):
2969
3137
        tag_conflicts = getattr(self, "tag_conflicts", None)
2970
3138
        tag_updates = getattr(self, "tag_updates", None)
3000
3168
        target, otherwise it will be None.
3001
3169
    """
3002
3170
 
 
3171
    @deprecated_method(deprecated_in((2, 3, 0)))
 
3172
    def __int__(self):
 
3173
        """Return the relative change in revno.
 
3174
 
 
3175
        :deprecated: Use `new_revno` and `old_revno` instead.
 
3176
        """
 
3177
        return self.new_revno - self.old_revno
 
3178
 
3003
3179
    def report(self, to_file):
3004
3180
        # TODO: This function gets passed a to_file, but then
3005
3181
        # ignores it and calls note() instead. This is also
3161
3337
        raise NotImplementedError(self.fetch)
3162
3338
 
3163
3339
 
3164
 
def _fix_overwrite_type(overwrite):
3165
 
    if isinstance(overwrite, bool):
3166
 
        if overwrite:
3167
 
            return ["history", "tags"]
3168
 
        else:
3169
 
            return []
3170
 
    return overwrite
3171
 
 
3172
 
 
3173
3340
class GenericInterBranch(InterBranch):
3174
3341
    """InterBranch implementation that uses public Branch functions."""
3175
3342
 
3340
3507
        result.target_branch = self.target
3341
3508
        result.old_revno, result.old_revid = self.target.last_revision_info()
3342
3509
        self.source.update_references(self.target)
3343
 
        overwrite = _fix_overwrite_type(overwrite)
3344
3510
        if result.old_revid != stop_revision:
3345
3511
            # We assume that during 'push' this repository is closer than
3346
3512
            # the target.
3347
3513
            graph = self.source.repository.get_graph(self.target.repository)
3348
 
            self._update_revisions(stop_revision,
3349
 
                overwrite=("history" in overwrite),
3350
 
                graph=graph)
 
3514
            self._update_revisions(stop_revision, overwrite=overwrite,
 
3515
                    graph=graph)
3351
3516
        if self.source._push_should_merge_tags():
3352
3517
            result.tag_updates, result.tag_conflicts = (
3353
 
                self.source.tags.merge_to(
3354
 
                self.target.tags, "tags" in overwrite))
 
3518
                self.source.tags.merge_to(self.target.tags, overwrite))
3355
3519
        result.new_revno, result.new_revid = self.target.last_revision_info()
3356
3520
        return result
3357
3521
 
3435
3599
            # -- JRV20090506
3436
3600
            result.old_revno, result.old_revid = \
3437
3601
                self.target.last_revision_info()
3438
 
            overwrite = _fix_overwrite_type(overwrite)
3439
 
            self._update_revisions(stop_revision,
3440
 
                overwrite=("history" in overwrite),
 
3602
            self._update_revisions(stop_revision, overwrite=overwrite,
3441
3603
                graph=graph)
3442
3604
            # TODO: The old revid should be specified when merging tags, 
3443
3605
            # so a tags implementation that versions tags can only 
3444
3606
            # pull in the most recent changes. -- JRV20090506
3445
3607
            result.tag_updates, result.tag_conflicts = (
3446
 
                self.source.tags.merge_to(self.target.tags,
3447
 
                    "tags" in overwrite,
 
3608
                self.source.tags.merge_to(self.target.tags, overwrite,
3448
3609
                    ignore_master=not merge_tags_to_master))
3449
3610
            result.new_revno, result.new_revid = self.target.last_revision_info()
3450
3611
            if _hook_master: