~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/branch.py

  • Committer: Vincent Ladeuil
  • Date: 2011-10-27 15:38:14 UTC
  • mfrom: (6015.44.4 2.4)
  • mto: This revision was merged to the branch mainline in revision 6236.
  • Revision ID: v.ladeuil+lp@free.fr-20111027153814-0r4nd2io1jv6t47f
Merge 2.4 into trunk including fix for bug #880701

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