~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/branch.py

  • Committer: Jelmer Vernooij
  • Date: 2011-06-16 11:57:36 UTC
  • mto: This revision was merged to the branch mainline in revision 5987.
  • Revision ID: jelmer@samba.org-20110616115736-5xuzwdf87qb81su4
Use iter_ancestry rather than get_ancestry.

Show diffs side-by-side

added added

removed removed

Lines of Context:
14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
 
import bzrlib.bzrdir
18
17
 
19
18
from cStringIO import StringIO
 
19
import sys
20
20
 
21
21
from bzrlib.lazy_import import lazy_import
22
22
lazy_import(globals(), """
23
 
import itertools
 
23
from itertools import chain
24
24
from bzrlib import (
25
 
    bzrdir,
26
 
    controldir,
27
 
    cache_utf8,
28
 
    cleanup,
29
 
    config as _mod_config,
30
 
    debug,
31
 
    errors,
32
 
    fetch,
33
 
    graph as _mod_graph,
34
 
    lockdir,
35
 
    lockable_files,
36
 
    remote,
37
 
    repository,
38
 
    revision as _mod_revision,
39
 
    rio,
40
 
    tag as _mod_tag,
41
 
    transport,
42
 
    ui,
43
 
    urlutils,
 
25
        bzrdir,
 
26
        cache_utf8,
 
27
        cleanup,
 
28
        config as _mod_config,
 
29
        debug,
 
30
        errors,
 
31
        fetch,
 
32
        graph as _mod_graph,
 
33
        lockdir,
 
34
        lockable_files,
 
35
        remote,
 
36
        repository,
 
37
        revision as _mod_revision,
 
38
        rio,
 
39
        transport,
 
40
        ui,
 
41
        urlutils,
 
42
        )
 
43
from bzrlib.config import BranchConfig, TransportConfig
 
44
from bzrlib.tag import (
 
45
    BasicTags,
 
46
    DisabledTags,
44
47
    )
45
 
from bzrlib.i18n import gettext, ngettext
46
48
""")
47
49
 
48
50
from bzrlib import (
64
66
from bzrlib.trace import mutter, mutter_callsite, note, is_quiet
65
67
 
66
68
 
 
69
BZR_BRANCH_FORMAT_4 = "Bazaar-NG branch, format 0.0.4\n"
 
70
BZR_BRANCH_FORMAT_5 = "Bazaar-NG branch, format 5\n"
 
71
BZR_BRANCH_FORMAT_6 = "Bazaar Branch Format 6 (bzr 0.15)\n"
 
72
 
 
73
 
67
74
class Branch(controldir.ControlComponent):
68
75
    """Branch holding a history of revisions.
69
76
 
109
116
        for existing_fallback_repo in self.repository._fallback_repositories:
110
117
            if existing_fallback_repo.user_url == url:
111
118
                # This fallback is already configured.  This probably only
112
 
                # happens because ControlDir.sprout is a horrible mess.  To avoid
 
119
                # happens because BzrDir.sprout is a horrible mess.  To avoid
113
120
                # confusing _unstack we don't add this a second time.
114
121
                mutter('duplicate activation of fallback %r on %r', url, self)
115
122
                return
173
180
        For instance, if the branch is at URL/.bzr/branch,
174
181
        Branch.open(URL) -> a Branch instance.
175
182
        """
176
 
        control = controldir.ControlDir.open(base, _unsupported,
 
183
        control = bzrdir.BzrDir.open(base, _unsupported,
177
184
                                     possible_transports=possible_transports)
178
185
        return control.open_branch(unsupported=_unsupported)
179
186
 
180
187
    @staticmethod
181
188
    def open_from_transport(transport, name=None, _unsupported=False):
182
189
        """Open the branch rooted at transport"""
183
 
        control = controldir.ControlDir.open_from_transport(transport, _unsupported)
 
190
        control = bzrdir.BzrDir.open_from_transport(transport, _unsupported)
184
191
        return control.open_branch(name=name, unsupported=_unsupported)
185
192
 
186
193
    @staticmethod
195
202
        format, UnknownFormatError or UnsupportedFormatError are raised.
196
203
        If there is one, it is returned, along with the unused portion of url.
197
204
        """
198
 
        control, relpath = controldir.ControlDir.open_containing(url,
 
205
        control, relpath = bzrdir.BzrDir.open_containing(url,
199
206
                                                         possible_transports)
200
207
        return control.open_branch(), relpath
201
208
 
215
222
 
216
223
        :return: A bzrlib.config.BranchConfig.
217
224
        """
218
 
        return _mod_config.BranchConfig(self)
219
 
 
220
 
    def get_config_stack(self):
221
 
        """Get a bzrlib.config.BranchStack for this Branch.
222
 
 
223
 
        This can then be used to get and set configuration options for the
224
 
        branch.
225
 
 
226
 
        :return: A bzrlib.config.BranchStack.
227
 
        """
228
 
        return _mod_config.BranchStack(self)
 
225
        return BranchConfig(self)
229
226
 
230
227
    def _get_config(self):
231
228
        """Get the concrete config for just the config in this branch.
516
513
        rev_iter = iter(merge_sorted_revisions)
517
514
        if start_revision_id is not None:
518
515
            for node in rev_iter:
519
 
                rev_id = node.key
 
516
                rev_id = node.key[-1]
520
517
                if rev_id != start_revision_id:
521
518
                    continue
522
519
                else:
523
520
                    # The decision to include the start or not
524
521
                    # depends on the stop_rule if a stop is provided
525
522
                    # so pop this node back into the iterator
526
 
                    rev_iter = itertools.chain(iter([node]), rev_iter)
 
523
                    rev_iter = chain(iter([node]), rev_iter)
527
524
                    break
528
525
        if stop_revision_id is None:
529
526
            # Yield everything
530
527
            for node in rev_iter:
531
 
                rev_id = node.key
 
528
                rev_id = node.key[-1]
532
529
                yield (rev_id, node.merge_depth, node.revno,
533
530
                       node.end_of_merge)
534
531
        elif stop_rule == 'exclude':
535
532
            for node in rev_iter:
536
 
                rev_id = node.key
 
533
                rev_id = node.key[-1]
537
534
                if rev_id == stop_revision_id:
538
535
                    return
539
536
                yield (rev_id, node.merge_depth, node.revno,
540
537
                       node.end_of_merge)
541
538
        elif stop_rule == 'include':
542
539
            for node in rev_iter:
543
 
                rev_id = node.key
 
540
                rev_id = node.key[-1]
544
541
                yield (rev_id, node.merge_depth, node.revno,
545
542
                       node.end_of_merge)
546
543
                if rev_id == stop_revision_id:
552
549
            ancestors = graph.find_unique_ancestors(start_revision_id,
553
550
                                                    [stop_revision_id])
554
551
            for node in rev_iter:
555
 
                rev_id = node.key
 
552
                rev_id = node.key[-1]
556
553
                if rev_id not in ancestors:
557
554
                    continue
558
555
                yield (rev_id, node.merge_depth, node.revno,
568
565
            reached_stop_revision_id = False
569
566
            revision_id_whitelist = []
570
567
            for node in rev_iter:
571
 
                rev_id = node.key
 
568
                rev_id = node.key[-1]
572
569
                if rev_id == left_parent:
573
570
                    # reached the left parent after the stop_revision
574
571
                    return
654
651
        """
655
652
        raise errors.UpgradeRequired(self.user_url)
656
653
 
657
 
    def get_append_revisions_only(self):
658
 
        """Whether it is only possible to append revisions to the history.
659
 
        """
660
 
        if not self._format.supports_set_append_revisions_only():
661
 
            return False
662
 
        return self.get_config(
663
 
            ).get_user_option_as_bool('append_revisions_only')
664
 
 
665
654
    def set_append_revisions_only(self, enabled):
666
655
        if not self._format.supports_set_append_revisions_only():
667
656
            raise errors.UpgradeRequired(self.user_url)
735
724
        """
736
725
        return None
737
726
 
738
 
    @deprecated_method(deprecated_in((2, 5, 0)))
739
727
    def get_revision_delta(self, revno):
740
728
        """Return the delta for one revision.
741
729
 
742
730
        The delta is relative to its mainline predecessor, or the
743
731
        empty tree for revision 1.
744
732
        """
745
 
        try:
746
 
            revid = self.get_rev_id(revno)
747
 
        except errors.NoSuchRevision:
 
733
        rh = self.revision_history()
 
734
        if not (1 <= revno <= len(rh)):
748
735
            raise errors.InvalidRevisionNumber(revno)
749
 
        return self.repository.get_revision_delta(revid)
 
736
        return self.repository.get_revision_delta(rh[revno-1])
750
737
 
751
738
    def get_stacked_on_url(self):
752
739
        """Get the URL this branch is stacked against.
798
785
                                  other_branch=None):
799
786
        """See Branch.generate_revision_history"""
800
787
        graph = self.repository.get_graph()
801
 
        (last_revno, last_revid) = self.last_revision_info()
802
788
        known_revision_ids = [
803
 
            (last_revid, last_revno),
 
789
            self.last_revision_info(),
804
790
            (_mod_revision.NULL_REVISION, 0),
805
791
            ]
806
792
        if last_rev is not None:
863
849
        """
864
850
        pb = ui.ui_factory.nested_progress_bar()
865
851
        try:
866
 
            pb.update(gettext("Unstacking"))
 
852
            pb.update("Unstacking")
867
853
            # The basic approach here is to fetch the tip of the branch,
868
854
            # including all available ghosts, from the existing stacked
869
855
            # repository into a new repository object without the fallbacks. 
883
869
            # stream from one of them to the other.  This does mean doing
884
870
            # separate SSH connection setup, but unstacking is not a
885
871
            # common operation so it's tolerable.
886
 
            new_bzrdir = controldir.ControlDir.open(
887
 
                self.bzrdir.root_transport.base)
 
872
            new_bzrdir = bzrdir.BzrDir.open(self.bzrdir.root_transport.base)
888
873
            new_repository = new_bzrdir.find_repository()
889
874
            if new_repository._fallback_repositories:
890
875
                raise AssertionError("didn't expect %r to have "
1007
992
        """
1008
993
        raise NotImplementedError(self._gen_revision_history)
1009
994
 
1010
 
    @deprecated_method(deprecated_in((2, 5, 0)))
1011
995
    @needs_read_lock
1012
996
    def revision_history(self):
1013
997
        """Return sequence of revision ids on this branch.
1015
999
        This method will cache the revision history for as long as it is safe to
1016
1000
        do so.
1017
1001
        """
1018
 
        return self._revision_history()
1019
 
 
1020
 
    def _revision_history(self):
1021
1002
        if 'evil' in debug.debug_flags:
1022
1003
            mutter_callsite(3, "revision_history scales with history.")
1023
1004
        if self._revision_history_cache is not None:
1093
1074
        """Given a revision id, return its revno"""
1094
1075
        if _mod_revision.is_null(revision_id):
1095
1076
            return 0
1096
 
        history = self._revision_history()
 
1077
        history = self.revision_history()
1097
1078
        try:
1098
1079
            return history.index(revision_id) + 1
1099
1080
        except ValueError:
1312
1293
            if repository_policy is not None:
1313
1294
                repository_policy.configure_branch(result)
1314
1295
            self.copy_content_into(result, revision_id=revision_id)
1315
 
            master_url = self.get_bound_location()
1316
 
            if master_url is None:
 
1296
            master_branch = self.get_master_branch()
 
1297
            if master_branch is None:
1317
1298
                result.set_parent(self.bzrdir.root_transport.base)
1318
1299
            else:
1319
 
                result.set_parent(master_url)
 
1300
                result.set_parent(master_branch.bzrdir.root_transport.base)
1320
1301
        finally:
1321
1302
            result.unlock()
1322
1303
        return result
1396
1377
        # TODO: We should probably also check that self.revision_history
1397
1378
        # matches the repository for older branch formats.
1398
1379
        # If looking for the code that cross-checks repository parents against
1399
 
        # the Graph.iter_lefthand_ancestry output, that is now a repository
 
1380
        # the iter_reverse_revision_history output, that is now a repository
1400
1381
        # specific check.
1401
1382
        return result
1402
1383
 
1403
 
    def _get_checkout_format(self, lightweight=False):
 
1384
    def _get_checkout_format(self):
1404
1385
        """Return the most suitable metadir for a checkout of this branch.
1405
1386
        Weaves are used if this branch's repository uses weaves.
1406
1387
        """
1452
1433
        """
1453
1434
        t = transport.get_transport(to_location)
1454
1435
        t.ensure_base()
1455
 
        format = self._get_checkout_format(lightweight=lightweight)
1456
1436
        if lightweight:
 
1437
            format = self._get_checkout_format()
1457
1438
            checkout = format.initialize_on_transport(t)
1458
1439
            from_branch = BranchReferenceFormat().initialize(checkout, 
1459
1440
                target_branch=self)
1460
1441
        else:
1461
 
            checkout_branch = controldir.ControlDir.create_branch_convenience(
 
1442
            format = self._get_checkout_format()
 
1443
            checkout_branch = bzrdir.BzrDir.create_branch_convenience(
1462
1444
                to_location, force_new_tree=False, format=format)
1463
1445
            checkout = checkout_branch.bzrdir
1464
1446
            checkout_branch.bind(self)
1563
1545
        # For bzr native formats must_fetch is just the tip, and if_present_fetch
1564
1546
        # are the tags.
1565
1547
        must_fetch = set([self.last_revision()])
1566
 
        if_present_fetch = set()
1567
 
        c = self.get_config()
1568
 
        include_tags = c.get_user_option_as_bool('branch.fetch_tags',
1569
 
                                                 default=False)
1570
 
        if include_tags:
1571
 
            try:
1572
 
                if_present_fetch = set(self.tags.get_reverse_tag_dict())
1573
 
            except errors.TagsNotSupported:
1574
 
                pass
 
1548
        try:
 
1549
            if_present_fetch = set(self.tags.get_reverse_tag_dict())
 
1550
        except errors.TagsNotSupported:
 
1551
            if_present_fetch = set()
1575
1552
        must_fetch.discard(_mod_revision.NULL_REVISION)
1576
1553
        if_present_fetch.discard(_mod_revision.NULL_REVISION)
1577
1554
        return must_fetch, if_present_fetch
1595
1572
    object will be created every time regardless.
1596
1573
    """
1597
1574
 
 
1575
    can_set_append_revisions_only = True
 
1576
 
1598
1577
    def __eq__(self, other):
1599
1578
        return self.__class__ is other.__class__
1600
1579
 
1602
1581
        return not (self == other)
1603
1582
 
1604
1583
    @classmethod
1605
 
    def find_format(klass, controldir, name=None):
1606
 
        """Return the format for the branch object in controldir."""
 
1584
    def find_format(klass, a_bzrdir, name=None):
 
1585
        """Return the format for the branch object in a_bzrdir."""
1607
1586
        try:
1608
 
            transport = controldir.get_branch_transport(None, name=name)
 
1587
            transport = a_bzrdir.get_branch_transport(None, name=name)
1609
1588
            format_string = transport.get_bytes("format")
1610
1589
            return format_registry.get(format_string)
1611
1590
        except errors.NoSuchFile:
1612
 
            raise errors.NotBranchError(path=transport.base, bzrdir=controldir)
 
1591
            raise errors.NotBranchError(path=transport.base, bzrdir=a_bzrdir)
1613
1592
        except KeyError:
1614
1593
            raise errors.UnknownFormatError(format=format_string, kind='branch')
1615
1594
 
1629
1608
        """
1630
1609
        return format_registry._get_all()
1631
1610
 
1632
 
    def get_reference(self, controldir, name=None):
1633
 
        """Get the target reference of the branch in controldir.
 
1611
    def get_reference(self, a_bzrdir, name=None):
 
1612
        """Get the target reference of the branch in a_bzrdir.
1634
1613
 
1635
1614
        format probing must have been completed before calling
1636
1615
        this method - it is assumed that the format of the branch
1637
 
        in controldir is correct.
 
1616
        in a_bzrdir is correct.
1638
1617
 
1639
 
        :param controldir: The controldir to get the branch data from.
 
1618
        :param a_bzrdir: The bzrdir to get the branch data from.
1640
1619
        :param name: Name of the colocated branch to fetch
1641
1620
        :return: None if the branch is not a reference branch.
1642
1621
        """
1643
1622
        return None
1644
1623
 
1645
1624
    @classmethod
1646
 
    def set_reference(self, controldir, name, to_branch):
1647
 
        """Set the target reference of the branch in controldir.
 
1625
    def set_reference(self, a_bzrdir, name, to_branch):
 
1626
        """Set the target reference of the branch in a_bzrdir.
1648
1627
 
1649
1628
        format probing must have been completed before calling
1650
1629
        this method - it is assumed that the format of the branch
1651
 
        in controldir is correct.
 
1630
        in a_bzrdir is correct.
1652
1631
 
1653
 
        :param controldir: The controldir to set the branch reference for.
 
1632
        :param a_bzrdir: The bzrdir to set the branch reference for.
1654
1633
        :param name: Name of colocated branch to set, None for default
1655
1634
        :param to_branch: branch that the checkout is to reference
1656
1635
        """
1664
1643
        """Return the short format description for this format."""
1665
1644
        raise NotImplementedError(self.get_format_description)
1666
1645
 
1667
 
    def _run_post_branch_init_hooks(self, controldir, name, branch):
 
1646
    def _run_post_branch_init_hooks(self, a_bzrdir, name, branch):
1668
1647
        hooks = Branch.hooks['post_branch_init']
1669
1648
        if not hooks:
1670
1649
            return
1671
 
        params = BranchInitHookParams(self, controldir, name, branch)
 
1650
        params = BranchInitHookParams(self, a_bzrdir, name, branch)
1672
1651
        for hook in hooks:
1673
1652
            hook(params)
1674
1653
 
1675
 
    def initialize(self, controldir, name=None, repository=None,
1676
 
                   append_revisions_only=None):
1677
 
        """Create a branch of this format in controldir.
1678
 
 
 
1654
    def initialize(self, a_bzrdir, name=None, repository=None):
 
1655
        """Create a branch of this format in a_bzrdir.
 
1656
        
1679
1657
        :param name: Name of the colocated branch to create.
1680
1658
        """
1681
1659
        raise NotImplementedError(self.initialize)
1701
1679
        Note that it is normal for branch to be a RemoteBranch when using tags
1702
1680
        on a RemoteBranch.
1703
1681
        """
1704
 
        return _mod_tag.DisabledTags(branch)
 
1682
        return DisabledTags(branch)
1705
1683
 
1706
1684
    def network_name(self):
1707
1685
        """A simple byte string uniquely identifying this format for RPC calls.
1713
1691
        """
1714
1692
        raise NotImplementedError(self.network_name)
1715
1693
 
1716
 
    def open(self, controldir, name=None, _found=False, ignore_fallbacks=False,
 
1694
    def open(self, a_bzrdir, name=None, _found=False, ignore_fallbacks=False,
1717
1695
            found_repository=None):
1718
 
        """Return the branch object for controldir.
 
1696
        """Return the branch object for a_bzrdir
1719
1697
 
1720
 
        :param controldir: A ControlDir that contains a branch.
 
1698
        :param a_bzrdir: A BzrDir that contains a branch.
1721
1699
        :param name: Name of colocated branch to open
1722
1700
        :param _found: a private parameter, do not use it. It is used to
1723
1701
            indicate if format probing has already be done.
1765
1743
        """True if this format supports tags stored in the branch"""
1766
1744
        return False  # by default
1767
1745
 
1768
 
    def tags_are_versioned(self):
1769
 
        """Whether the tag container for this branch versions tags."""
1770
 
        return False
1771
 
 
1772
 
    def supports_tags_referencing_ghosts(self):
1773
 
        """True if tags can reference ghost revisions."""
1774
 
        return True
1775
 
 
1776
1746
 
1777
1747
class MetaDirBranchFormatFactory(registry._LazyObjectGetter):
1778
1748
    """A factory for a BranchFormat object, permitting simple lazy registration.
1943
1913
    There are 4 fields that hooks may wish to access:
1944
1914
 
1945
1915
    :ivar format: the branch format
1946
 
    :ivar bzrdir: the ControlDir where the branch will be/has been initialized
 
1916
    :ivar bzrdir: the BzrDir where the branch will be/has been initialized
1947
1917
    :ivar name: name of colocated branch, if any (or None)
1948
1918
    :ivar branch: the branch created
1949
1919
 
1952
1922
    branch, which refer to the original branch.
1953
1923
    """
1954
1924
 
1955
 
    def __init__(self, format, controldir, name, branch):
 
1925
    def __init__(self, format, a_bzrdir, name, branch):
1956
1926
        """Create a group of BranchInitHook parameters.
1957
1927
 
1958
1928
        :param format: the branch format
1959
 
        :param controldir: the ControlDir where the branch will be/has been
 
1929
        :param a_bzrdir: the BzrDir where the branch will be/has been
1960
1930
            initialized
1961
1931
        :param name: name of colocated branch, if any (or None)
1962
1932
        :param branch: the branch created
1966
1936
        in branch, which refer to the original branch.
1967
1937
        """
1968
1938
        self.format = format
1969
 
        self.bzrdir = controldir
 
1939
        self.bzrdir = a_bzrdir
1970
1940
        self.name = name
1971
1941
        self.branch = branch
1972
1942
 
1982
1952
 
1983
1953
    There are 4 fields that hooks may wish to access:
1984
1954
 
1985
 
    :ivar control_dir: ControlDir of the checkout to change
 
1955
    :ivar control_dir: BzrDir of the checkout to change
1986
1956
    :ivar to_branch: branch that the checkout is to reference
1987
1957
    :ivar force: skip the check for local commits in a heavy checkout
1988
1958
    :ivar revision_id: revision ID to switch to (or None)
1991
1961
    def __init__(self, control_dir, to_branch, force, revision_id):
1992
1962
        """Create a group of SwitchHook parameters.
1993
1963
 
1994
 
        :param control_dir: ControlDir of the checkout to change
 
1964
        :param control_dir: BzrDir of the checkout to change
1995
1965
        :param to_branch: branch that the checkout is to reference
1996
1966
        :param force: skip the check for local commits in a heavy checkout
1997
1967
        :param revision_id: revision ID to switch to (or None)
2017
1987
        """What class to instantiate on open calls."""
2018
1988
        raise NotImplementedError(self._branch_class)
2019
1989
 
2020
 
    def _get_initial_config(self, append_revisions_only=None):
2021
 
        if append_revisions_only:
2022
 
            return "append_revisions_only = True\n"
2023
 
        else:
2024
 
            # Avoid writing anything if append_revisions_only is disabled,
2025
 
            # as that is the default.
2026
 
            return ""
2027
 
 
2028
1990
    def _initialize_helper(self, a_bzrdir, utf8_files, name=None,
2029
1991
                           repository=None):
2030
1992
        """Initialize a branch in a bzrdir, with specified files
2084
2046
        except errors.NoSuchFile:
2085
2047
            raise errors.NotBranchError(path=transport.base, bzrdir=a_bzrdir)
2086
2048
 
2087
 
    @property
2088
 
    def _matchingbzrdir(self):
2089
 
        ret = bzrdir.BzrDirMetaFormat1()
2090
 
        ret.set_branch_format(self)
2091
 
        return ret
 
2049
    def __init__(self):
 
2050
        super(BranchFormatMetadir, self).__init__()
 
2051
        self._matchingbzrdir = bzrdir.BzrDirMetaFormat1()
 
2052
        self._matchingbzrdir.set_branch_format(self)
2092
2053
 
2093
2054
    def supports_tags(self):
2094
2055
        return True
2121
2082
        """See BranchFormat.get_format_description()."""
2122
2083
        return "Branch format 5"
2123
2084
 
2124
 
    def initialize(self, a_bzrdir, name=None, repository=None,
2125
 
                   append_revisions_only=None):
 
2085
    def initialize(self, a_bzrdir, name=None, repository=None):
2126
2086
        """Create a branch of this format in a_bzrdir."""
2127
 
        if append_revisions_only:
2128
 
            raise errors.UpgradeRequired(a_bzrdir.user_url)
2129
2087
        utf8_files = [('revision-history', ''),
2130
2088
                      ('branch-name', ''),
2131
2089
                      ]
2157
2115
        """See BranchFormat.get_format_description()."""
2158
2116
        return "Branch format 6"
2159
2117
 
2160
 
    def initialize(self, a_bzrdir, name=None, repository=None,
2161
 
                   append_revisions_only=None):
 
2118
    def initialize(self, a_bzrdir, name=None, repository=None):
2162
2119
        """Create a branch of this format in a_bzrdir."""
2163
2120
        utf8_files = [('last-revision', '0 null:\n'),
2164
 
                      ('branch.conf',
2165
 
                          self._get_initial_config(append_revisions_only)),
 
2121
                      ('branch.conf', ''),
2166
2122
                      ('tags', ''),
2167
2123
                      ]
2168
2124
        return self._initialize_helper(a_bzrdir, utf8_files, name, repository)
2169
2125
 
2170
2126
    def make_tags(self, branch):
2171
2127
        """See bzrlib.branch.BranchFormat.make_tags()."""
2172
 
        return _mod_tag.BasicTags(branch)
 
2128
        return BasicTags(branch)
2173
2129
 
2174
2130
    def supports_set_append_revisions_only(self):
2175
2131
        return True
2189
2145
        """See BranchFormat.get_format_description()."""
2190
2146
        return "Branch format 8"
2191
2147
 
2192
 
    def initialize(self, a_bzrdir, name=None, repository=None,
2193
 
                   append_revisions_only=None):
 
2148
    def initialize(self, a_bzrdir, name=None, repository=None):
2194
2149
        """Create a branch of this format in a_bzrdir."""
2195
2150
        utf8_files = [('last-revision', '0 null:\n'),
2196
 
                      ('branch.conf',
2197
 
                          self._get_initial_config(append_revisions_only)),
 
2151
                      ('branch.conf', ''),
2198
2152
                      ('tags', ''),
2199
2153
                      ('references', '')
2200
2154
                      ]
2202
2156
 
2203
2157
    def make_tags(self, branch):
2204
2158
        """See bzrlib.branch.BranchFormat.make_tags()."""
2205
 
        return _mod_tag.BasicTags(branch)
 
2159
        return BasicTags(branch)
2206
2160
 
2207
2161
    def supports_set_append_revisions_only(self):
2208
2162
        return True
2222
2176
    This format was introduced in bzr 1.6.
2223
2177
    """
2224
2178
 
2225
 
    def initialize(self, a_bzrdir, name=None, repository=None,
2226
 
                   append_revisions_only=None):
 
2179
    def initialize(self, a_bzrdir, name=None, repository=None):
2227
2180
        """Create a branch of this format in a_bzrdir."""
2228
2181
        utf8_files = [('last-revision', '0 null:\n'),
2229
 
                      ('branch.conf',
2230
 
                          self._get_initial_config(append_revisions_only)),
 
2182
                      ('branch.conf', ''),
2231
2183
                      ('tags', ''),
2232
2184
                      ]
2233
2185
        return self._initialize_helper(a_bzrdir, utf8_files, name, repository)
2251
2203
 
2252
2204
    def make_tags(self, branch):
2253
2205
        """See bzrlib.branch.BranchFormat.make_tags()."""
2254
 
        return _mod_tag.BasicTags(branch)
 
2206
        return BasicTags(branch)
2255
2207
 
2256
2208
    supports_reference_locations = False
2257
2209
 
2258
2210
 
2259
 
class BranchReferenceFormat(BranchFormatMetadir):
 
2211
class BranchReferenceFormat(BranchFormat):
2260
2212
    """Bzr branch reference format.
2261
2213
 
2262
2214
    Branch references are used in implementing checkouts, they
2286
2238
        location = transport.put_bytes('location', to_branch.base)
2287
2239
 
2288
2240
    def initialize(self, a_bzrdir, name=None, target_branch=None,
2289
 
            repository=None, append_revisions_only=None):
 
2241
            repository=None):
2290
2242
        """Create a branch of this format in a_bzrdir."""
2291
2243
        if target_branch is None:
2292
2244
            # this format does not implement branch itself, thus the implicit
2293
2245
            # creation contract must see it as uninitializable
2294
2246
            raise errors.UninitializableFormat(self)
2295
2247
        mutter('creating branch reference in %s', a_bzrdir.user_url)
2296
 
        if a_bzrdir._format.fixed_components:
2297
 
            raise errors.IncompatibleFormat(self, a_bzrdir._format)
2298
2248
        branch_transport = a_bzrdir.get_branch_transport(self, name=name)
2299
2249
        branch_transport.put_bytes('location',
2300
2250
            target_branch.bzrdir.user_url)
2305
2255
        self._run_post_branch_init_hooks(a_bzrdir, name, branch)
2306
2256
        return branch
2307
2257
 
 
2258
    def __init__(self):
 
2259
        super(BranchReferenceFormat, self).__init__()
 
2260
        self._matchingbzrdir = bzrdir.BzrDirMetaFormat1()
 
2261
        self._matchingbzrdir.set_branch_format(self)
 
2262
 
2308
2263
    def _make_reference_clone_function(format, a_branch):
2309
2264
        """Create a clone() routine for a branch dynamically."""
2310
2265
        def clone(to_bzrdir, revision_id=None,
2339
2294
                    (format, self))
2340
2295
        if location is None:
2341
2296
            location = self.get_reference(a_bzrdir, name)
2342
 
        real_bzrdir = controldir.ControlDir.open(
 
2297
        real_bzrdir = bzrdir.BzrDir.open(
2343
2298
            location, possible_transports=possible_transports)
2344
2299
        result = real_bzrdir.open_branch(name=name, 
2345
2300
            ignore_fallbacks=ignore_fallbacks)
2464
2419
    base = property(_get_base, doc="The URL for the root of this branch.")
2465
2420
 
2466
2421
    def _get_config(self):
2467
 
        return _mod_config.TransportConfig(self._transport, 'branch.conf')
 
2422
        return TransportConfig(self._transport, 'branch.conf')
2468
2423
 
2469
2424
    def is_locked(self):
2470
2425
        return self.control_files.is_locked()
2551
2506
            raise errors.InvalidRevisionId(revision_id=revision_id, branch=self)
2552
2507
        revision_id = _mod_revision.ensure_null(revision_id)
2553
2508
        old_revno, old_revid = self.last_revision_info()
2554
 
        if self.get_append_revisions_only():
 
2509
        if self._get_append_revisions_only():
2555
2510
            self._check_history_violation(revision_id)
2556
2511
        self._run_pre_change_branch_tip_hooks(revno, revision_id)
2557
2512
        self._write_last_revision_info(revno, revision_id)
2718
2673
        self._set_revision_history(history)
2719
2674
 
2720
2675
    def _read_last_revision_info(self):
2721
 
        rh = self._revision_history()
 
2676
        rh = self.revision_history()
2722
2677
        revno = len(rh)
2723
2678
        if revno:
2724
2679
            return (revno, rh[-1])
2778
2733
        if revision_id == _mod_revision.NULL_REVISION:
2779
2734
            new_history = []
2780
2735
        else:
2781
 
            new_history = self._revision_history()
 
2736
            new_history = self.revision_history()
2782
2737
        if revision_id is not None and new_history != []:
2783
2738
            try:
2784
2739
                new_history = new_history[:new_history.index(revision_id) + 1]
2987
2942
        # you can always ask for the URL; but you might not be able to use it
2988
2943
        # if the repo can't support stacking.
2989
2944
        ## self._check_stackable_repo()
2990
 
        # stacked_on_location is only ever defined in branch.conf, so don't
2991
 
        # waste effort reading the whole stack of config files.
2992
 
        config = self.get_config()._get_branch_data_config()
2993
 
        stacked_url = self._get_config_location('stacked_on_location',
2994
 
            config=config)
 
2945
        stacked_url = self._get_config_location('stacked_on_location')
2995
2946
        if stacked_url is None:
2996
2947
            raise errors.NotStacked(self)
2997
2948
        return stacked_url
2998
2949
 
 
2950
    def _get_append_revisions_only(self):
 
2951
        return self.get_config(
 
2952
            ).get_user_option_as_bool('append_revisions_only')
 
2953
 
2999
2954
    @needs_read_lock
3000
2955
    def get_rev_id(self, revno, history=None):
3001
2956
        """Find the revision id of the specified revno."""
3087
3042
    :ivar local_branch: target branch if there is a Master, else None
3088
3043
    :ivar target_branch: Target/destination branch object. (write locked)
3089
3044
    :ivar tag_conflicts: A list of tag conflicts, see BasicTags.merge_to
3090
 
    :ivar tag_updates: A dict with new tags, see BasicTags.merge_to
3091
3045
    """
3092
3046
 
3093
3047
    @deprecated_method(deprecated_in((2, 3, 0)))
3099
3053
        return self.new_revno - self.old_revno
3100
3054
 
3101
3055
    def report(self, to_file):
3102
 
        tag_conflicts = getattr(self, "tag_conflicts", None)
3103
 
        tag_updates = getattr(self, "tag_updates", None)
3104
3056
        if not is_quiet():
3105
 
            if self.old_revid != self.new_revid:
 
3057
            if self.old_revid == self.new_revid:
 
3058
                to_file.write('No revisions to pull.\n')
 
3059
            else:
3106
3060
                to_file.write('Now on revision %d.\n' % self.new_revno)
3107
 
            if tag_updates:
3108
 
                to_file.write('%d tag(s) updated.\n' % len(tag_updates))
3109
 
            if self.old_revid == self.new_revid and not tag_updates:
3110
 
                if not tag_conflicts:
3111
 
                    to_file.write('No revisions or tags to pull.\n')
3112
 
                else:
3113
 
                    to_file.write('No revisions to pull.\n')
3114
3061
        self._show_tag_conficts(to_file)
3115
3062
 
3116
3063
 
3142
3089
        return self.new_revno - self.old_revno
3143
3090
 
3144
3091
    def report(self, to_file):
3145
 
        # TODO: This function gets passed a to_file, but then
3146
 
        # ignores it and calls note() instead. This is also
3147
 
        # inconsistent with PullResult(), which writes to stdout.
3148
 
        # -- JRV20110901, bug #838853
3149
 
        tag_conflicts = getattr(self, "tag_conflicts", None)
3150
 
        tag_updates = getattr(self, "tag_updates", None)
3151
 
        if not is_quiet():
3152
 
            if self.old_revid != self.new_revid:
3153
 
                note(gettext('Pushed up to revision %d.') % self.new_revno)
3154
 
            if tag_updates:
3155
 
                note(ngettext('%d tag updated.', '%d tags updated.', len(tag_updates)) % len(tag_updates))
3156
 
            if self.old_revid == self.new_revid and not tag_updates:
3157
 
                if not tag_conflicts:
3158
 
                    note(gettext('No new revisions or tags to push.'))
3159
 
                else:
3160
 
                    note(gettext('No new revisions to push.'))
 
3092
        """Write a human-readable description of the result."""
 
3093
        if self.old_revid == self.new_revid:
 
3094
            note('No new revisions to push.')
 
3095
        else:
 
3096
            note('Pushed up to revision %d.' % self.new_revno)
3161
3097
        self._show_tag_conficts(to_file)
3162
3098
 
3163
3099
 
3177
3113
        :param verbose: Requests more detailed display of what was checked,
3178
3114
            if any.
3179
3115
        """
3180
 
        note(gettext('checked branch {0} format {1}').format(
3181
 
                                self.branch.user_url, self.branch._format))
 
3116
        note('checked branch %s format %s', self.branch.user_url,
 
3117
            self.branch._format)
3182
3118
        for error in self.errors:
3183
 
            note(gettext('found error:%s'), error)
 
3119
            note('found error:%s', error)
3184
3120
 
3185
3121
 
3186
3122
class Converter5to6(object):
3225
3161
 
3226
3162
 
3227
3163
class Converter7to8(object):
3228
 
    """Perform an in-place upgrade of format 7 to format 8"""
 
3164
    """Perform an in-place upgrade of format 6 to format 7"""
3229
3165
 
3230
3166
    def convert(self, branch):
3231
3167
        format = BzrBranchFormat8()
3404
3340
        if local and not bound_location:
3405
3341
            raise errors.LocalRequiresBoundBranch()
3406
3342
        master_branch = None
3407
 
        source_is_master = False
3408
 
        if bound_location:
3409
 
            # bound_location comes from a config file, some care has to be
3410
 
            # taken to relate it to source.user_url
3411
 
            normalized = urlutils.normalize_url(bound_location)
3412
 
            try:
3413
 
                relpath = self.source.user_transport.relpath(normalized)
3414
 
                source_is_master = (relpath == '')
3415
 
            except (errors.PathNotChild, errors.InvalidURL):
3416
 
                source_is_master = False
 
3343
        source_is_master = (self.source.user_url == bound_location)
3417
3344
        if not local and bound_location and not source_is_master:
3418
3345
            # not pulling from master, so we need to update master.
3419
3346
            master_branch = self.target.get_master_branch(possible_transports)
3471
3398
            self._update_revisions(stop_revision, overwrite=overwrite,
3472
3399
                    graph=graph)
3473
3400
        if self.source._push_should_merge_tags():
3474
 
            result.tag_updates, result.tag_conflicts = (
3475
 
                self.source.tags.merge_to(self.target.tags, overwrite))
 
3401
            result.tag_conflicts = self.source.tags.merge_to(self.target.tags,
 
3402
                overwrite)
3476
3403
        result.new_revno, result.new_revid = self.target.last_revision_info()
3477
3404
        return result
3478
3405
 
3561
3488
            # TODO: The old revid should be specified when merging tags, 
3562
3489
            # so a tags implementation that versions tags can only 
3563
3490
            # pull in the most recent changes. -- JRV20090506
3564
 
            result.tag_updates, result.tag_conflicts = (
3565
 
                self.source.tags.merge_to(self.target.tags, overwrite,
3566
 
                    ignore_master=not merge_tags_to_master))
 
3491
            result.tag_conflicts = self.source.tags.merge_to(self.target.tags,
 
3492
                overwrite, ignore_master=not merge_tags_to_master)
3567
3493
            result.new_revno, result.new_revid = self.target.last_revision_info()
3568
3494
            if _hook_master:
3569
3495
                result.master_branch = _hook_master