/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: 2011-11-24 15:48:29 UTC
  • mfrom: (6289 +trunk)
  • mto: This revision was merged to the branch mainline in revision 6337.
  • Revision ID: v.ladeuil+lp@free.fr-20111124154829-avowjpsxdl8yp2vz
merge trunk resolving conflicts

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.
850
863
        """
851
864
        pb = ui.ui_factory.nested_progress_bar()
852
865
        try:
853
 
            pb.update("Unstacking")
 
866
            pb.update(gettext("Unstacking"))
854
867
            # The basic approach here is to fetch the tip of the branch,
855
868
            # including all available ghosts, from the existing stacked
856
869
            # repository into a new repository object without the fallbacks. 
870
883
            # stream from one of them to the other.  This does mean doing
871
884
            # separate SSH connection setup, but unstacking is not a
872
885
            # common operation so it's tolerable.
873
 
            new_bzrdir = bzrdir.BzrDir.open(self.bzrdir.root_transport.base)
 
886
            new_bzrdir = controldir.ControlDir.open(
 
887
                self.bzrdir.root_transport.base)
874
888
            new_repository = new_bzrdir.find_repository()
875
889
            if new_repository._fallback_repositories:
876
890
                raise AssertionError("didn't expect %r to have "
993
1007
        """
994
1008
        raise NotImplementedError(self._gen_revision_history)
995
1009
 
 
1010
    @deprecated_method(deprecated_in((2, 5, 0)))
996
1011
    @needs_read_lock
997
1012
    def revision_history(self):
998
1013
        """Return sequence of revision ids on this branch.
1000
1015
        This method will cache the revision history for as long as it is safe to
1001
1016
        do so.
1002
1017
        """
 
1018
        return self._revision_history()
 
1019
 
 
1020
    def _revision_history(self):
1003
1021
        if 'evil' in debug.debug_flags:
1004
1022
            mutter_callsite(3, "revision_history scales with history.")
1005
1023
        if self._revision_history_cache is not None:
1075
1093
        """Given a revision id, return its revno"""
1076
1094
        if _mod_revision.is_null(revision_id):
1077
1095
            return 0
1078
 
        history = self.revision_history()
 
1096
        history = self._revision_history()
1079
1097
        try:
1080
1098
            return history.index(revision_id) + 1
1081
1099
        except ValueError:
1378
1396
        # TODO: We should probably also check that self.revision_history
1379
1397
        # matches the repository for older branch formats.
1380
1398
        # If looking for the code that cross-checks repository parents against
1381
 
        # the iter_reverse_revision_history output, that is now a repository
 
1399
        # the Graph.iter_lefthand_ancestry output, that is now a repository
1382
1400
        # specific check.
1383
1401
        return result
1384
1402
 
1385
 
    def _get_checkout_format(self):
 
1403
    def _get_checkout_format(self, lightweight=False):
1386
1404
        """Return the most suitable metadir for a checkout of this branch.
1387
1405
        Weaves are used if this branch's repository uses weaves.
1388
1406
        """
1434
1452
        """
1435
1453
        t = transport.get_transport(to_location)
1436
1454
        t.ensure_base()
 
1455
        format = self._get_checkout_format(lightweight=lightweight)
1437
1456
        if lightweight:
1438
 
            format = self._get_checkout_format()
1439
1457
            checkout = format.initialize_on_transport(t)
1440
1458
            from_branch = BranchReferenceFormat().initialize(checkout, 
1441
1459
                target_branch=self)
1442
1460
        else:
1443
 
            format = self._get_checkout_format()
1444
 
            checkout_branch = bzrdir.BzrDir.create_branch_convenience(
 
1461
            checkout_branch = controldir.ControlDir.create_branch_convenience(
1445
1462
                to_location, force_new_tree=False, format=format)
1446
1463
            checkout = checkout_branch.bzrdir
1447
1464
            checkout_branch.bind(self)
1578
1595
    object will be created every time regardless.
1579
1596
    """
1580
1597
 
1581
 
    can_set_append_revisions_only = True
1582
 
 
1583
1598
    def __eq__(self, other):
1584
1599
        return self.__class__ is other.__class__
1585
1600
 
1587
1602
        return not (self == other)
1588
1603
 
1589
1604
    @classmethod
1590
 
    def find_format(klass, a_bzrdir, name=None):
1591
 
        """Return the format for the branch object in a_bzrdir."""
1592
 
        try:
1593
 
            transport = a_bzrdir.get_branch_transport(None, name=name)
 
1605
    def find_format(klass, controldir, name=None):
 
1606
        """Return the format for the branch object in controldir."""
 
1607
        try:
 
1608
            transport = controldir.get_branch_transport(None, name=name)
 
1609
        except errors.NoSuchFile:
 
1610
            raise errors.NotBranchError(path=name, bzrdir=controldir)
 
1611
        try:
1594
1612
            format_string = transport.get_bytes("format")
1595
1613
            return format_registry.get(format_string)
1596
1614
        except errors.NoSuchFile:
1597
 
            raise errors.NotBranchError(path=transport.base, bzrdir=a_bzrdir)
 
1615
            raise errors.NotBranchError(path=transport.base, bzrdir=controldir)
1598
1616
        except KeyError:
1599
1617
            raise errors.UnknownFormatError(format=format_string, kind='branch')
1600
1618
 
1614
1632
        """
1615
1633
        return format_registry._get_all()
1616
1634
 
1617
 
    def get_reference(self, a_bzrdir, name=None):
1618
 
        """Get the target reference of the branch in a_bzrdir.
 
1635
    def get_reference(self, controldir, name=None):
 
1636
        """Get the target reference of the branch in controldir.
1619
1637
 
1620
1638
        format probing must have been completed before calling
1621
1639
        this method - it is assumed that the format of the branch
1622
 
        in a_bzrdir is correct.
 
1640
        in controldir is correct.
1623
1641
 
1624
 
        :param a_bzrdir: The bzrdir to get the branch data from.
 
1642
        :param controldir: The controldir to get the branch data from.
1625
1643
        :param name: Name of the colocated branch to fetch
1626
1644
        :return: None if the branch is not a reference branch.
1627
1645
        """
1628
1646
        return None
1629
1647
 
1630
1648
    @classmethod
1631
 
    def set_reference(self, a_bzrdir, name, to_branch):
1632
 
        """Set the target reference of the branch in a_bzrdir.
 
1649
    def set_reference(self, controldir, name, to_branch):
 
1650
        """Set the target reference of the branch in controldir.
1633
1651
 
1634
1652
        format probing must have been completed before calling
1635
1653
        this method - it is assumed that the format of the branch
1636
 
        in a_bzrdir is correct.
 
1654
        in controldir is correct.
1637
1655
 
1638
 
        :param a_bzrdir: The bzrdir to set the branch reference for.
 
1656
        :param controldir: The controldir to set the branch reference for.
1639
1657
        :param name: Name of colocated branch to set, None for default
1640
1658
        :param to_branch: branch that the checkout is to reference
1641
1659
        """
1649
1667
        """Return the short format description for this format."""
1650
1668
        raise NotImplementedError(self.get_format_description)
1651
1669
 
1652
 
    def _run_post_branch_init_hooks(self, a_bzrdir, name, branch):
 
1670
    def _run_post_branch_init_hooks(self, controldir, name, branch):
1653
1671
        hooks = Branch.hooks['post_branch_init']
1654
1672
        if not hooks:
1655
1673
            return
1656
 
        params = BranchInitHookParams(self, a_bzrdir, name, branch)
 
1674
        params = BranchInitHookParams(self, controldir, name, branch)
1657
1675
        for hook in hooks:
1658
1676
            hook(params)
1659
1677
 
1660
 
    def initialize(self, a_bzrdir, name=None, repository=None):
1661
 
        """Create a branch of this format in a_bzrdir.
1662
 
        
 
1678
    def initialize(self, controldir, name=None, repository=None,
 
1679
                   append_revisions_only=None):
 
1680
        """Create a branch of this format in controldir.
 
1681
 
1663
1682
        :param name: Name of the colocated branch to create.
1664
1683
        """
1665
1684
        raise NotImplementedError(self.initialize)
1685
1704
        Note that it is normal for branch to be a RemoteBranch when using tags
1686
1705
        on a RemoteBranch.
1687
1706
        """
1688
 
        return DisabledTags(branch)
 
1707
        return _mod_tag.DisabledTags(branch)
1689
1708
 
1690
1709
    def network_name(self):
1691
1710
        """A simple byte string uniquely identifying this format for RPC calls.
1697
1716
        """
1698
1717
        raise NotImplementedError(self.network_name)
1699
1718
 
1700
 
    def open(self, a_bzrdir, name=None, _found=False, ignore_fallbacks=False,
 
1719
    def open(self, controldir, name=None, _found=False, ignore_fallbacks=False,
1701
1720
            found_repository=None):
1702
 
        """Return the branch object for a_bzrdir
 
1721
        """Return the branch object for controldir.
1703
1722
 
1704
 
        :param a_bzrdir: A BzrDir that contains a branch.
 
1723
        :param controldir: A ControlDir that contains a branch.
1705
1724
        :param name: Name of colocated branch to open
1706
1725
        :param _found: a private parameter, do not use it. It is used to
1707
1726
            indicate if format probing has already be done.
1749
1768
        """True if this format supports tags stored in the branch"""
1750
1769
        return False  # by default
1751
1770
 
 
1771
    def tags_are_versioned(self):
 
1772
        """Whether the tag container for this branch versions tags."""
 
1773
        return False
 
1774
 
 
1775
    def supports_tags_referencing_ghosts(self):
 
1776
        """True if tags can reference ghost revisions."""
 
1777
        return True
 
1778
 
1752
1779
 
1753
1780
class MetaDirBranchFormatFactory(registry._LazyObjectGetter):
1754
1781
    """A factory for a BranchFormat object, permitting simple lazy registration.
1919
1946
    There are 4 fields that hooks may wish to access:
1920
1947
 
1921
1948
    :ivar format: the branch format
1922
 
    :ivar bzrdir: the BzrDir where the branch will be/has been initialized
 
1949
    :ivar bzrdir: the ControlDir where the branch will be/has been initialized
1923
1950
    :ivar name: name of colocated branch, if any (or None)
1924
1951
    :ivar branch: the branch created
1925
1952
 
1928
1955
    branch, which refer to the original branch.
1929
1956
    """
1930
1957
 
1931
 
    def __init__(self, format, a_bzrdir, name, branch):
 
1958
    def __init__(self, format, controldir, name, branch):
1932
1959
        """Create a group of BranchInitHook parameters.
1933
1960
 
1934
1961
        :param format: the branch format
1935
 
        :param a_bzrdir: the BzrDir where the branch will be/has been
 
1962
        :param controldir: the ControlDir where the branch will be/has been
1936
1963
            initialized
1937
1964
        :param name: name of colocated branch, if any (or None)
1938
1965
        :param branch: the branch created
1942
1969
        in branch, which refer to the original branch.
1943
1970
        """
1944
1971
        self.format = format
1945
 
        self.bzrdir = a_bzrdir
 
1972
        self.bzrdir = controldir
1946
1973
        self.name = name
1947
1974
        self.branch = branch
1948
1975
 
1958
1985
 
1959
1986
    There are 4 fields that hooks may wish to access:
1960
1987
 
1961
 
    :ivar control_dir: BzrDir of the checkout to change
 
1988
    :ivar control_dir: ControlDir of the checkout to change
1962
1989
    :ivar to_branch: branch that the checkout is to reference
1963
1990
    :ivar force: skip the check for local commits in a heavy checkout
1964
1991
    :ivar revision_id: revision ID to switch to (or None)
1967
1994
    def __init__(self, control_dir, to_branch, force, revision_id):
1968
1995
        """Create a group of SwitchHook parameters.
1969
1996
 
1970
 
        :param control_dir: BzrDir of the checkout to change
 
1997
        :param control_dir: ControlDir of the checkout to change
1971
1998
        :param to_branch: branch that the checkout is to reference
1972
1999
        :param force: skip the check for local commits in a heavy checkout
1973
2000
        :param revision_id: revision ID to switch to (or None)
1993
2020
        """What class to instantiate on open calls."""
1994
2021
        raise NotImplementedError(self._branch_class)
1995
2022
 
 
2023
    def _get_initial_config(self, append_revisions_only=None):
 
2024
        if append_revisions_only:
 
2025
            return "append_revisions_only = True\n"
 
2026
        else:
 
2027
            # Avoid writing anything if append_revisions_only is disabled,
 
2028
            # as that is the default.
 
2029
            return ""
 
2030
 
1996
2031
    def _initialize_helper(self, a_bzrdir, utf8_files, name=None,
1997
2032
                           repository=None):
1998
2033
        """Initialize a branch in a bzrdir, with specified files
2052
2087
        except errors.NoSuchFile:
2053
2088
            raise errors.NotBranchError(path=transport.base, bzrdir=a_bzrdir)
2054
2089
 
2055
 
    def __init__(self):
2056
 
        super(BranchFormatMetadir, self).__init__()
2057
 
        self._matchingbzrdir = bzrdir.BzrDirMetaFormat1()
2058
 
        self._matchingbzrdir.set_branch_format(self)
 
2090
    @property
 
2091
    def _matchingbzrdir(self):
 
2092
        ret = bzrdir.BzrDirMetaFormat1()
 
2093
        ret.set_branch_format(self)
 
2094
        return ret
2059
2095
 
2060
2096
    def supports_tags(self):
2061
2097
        return True
2088
2124
        """See BranchFormat.get_format_description()."""
2089
2125
        return "Branch format 5"
2090
2126
 
2091
 
    def initialize(self, a_bzrdir, name=None, repository=None):
 
2127
    def initialize(self, a_bzrdir, name=None, repository=None,
 
2128
                   append_revisions_only=None):
2092
2129
        """Create a branch of this format in a_bzrdir."""
 
2130
        if append_revisions_only:
 
2131
            raise errors.UpgradeRequired(a_bzrdir.user_url)
2093
2132
        utf8_files = [('revision-history', ''),
2094
2133
                      ('branch-name', ''),
2095
2134
                      ]
2121
2160
        """See BranchFormat.get_format_description()."""
2122
2161
        return "Branch format 6"
2123
2162
 
2124
 
    def initialize(self, a_bzrdir, name=None, repository=None):
 
2163
    def initialize(self, a_bzrdir, name=None, repository=None,
 
2164
                   append_revisions_only=None):
2125
2165
        """Create a branch of this format in a_bzrdir."""
2126
2166
        utf8_files = [('last-revision', '0 null:\n'),
2127
 
                      ('branch.conf', ''),
 
2167
                      ('branch.conf',
 
2168
                          self._get_initial_config(append_revisions_only)),
2128
2169
                      ('tags', ''),
2129
2170
                      ]
2130
2171
        return self._initialize_helper(a_bzrdir, utf8_files, name, repository)
2131
2172
 
2132
2173
    def make_tags(self, branch):
2133
2174
        """See bzrlib.branch.BranchFormat.make_tags()."""
2134
 
        return BasicTags(branch)
 
2175
        return _mod_tag.BasicTags(branch)
2135
2176
 
2136
2177
    def supports_set_append_revisions_only(self):
2137
2178
        return True
2151
2192
        """See BranchFormat.get_format_description()."""
2152
2193
        return "Branch format 8"
2153
2194
 
2154
 
    def initialize(self, a_bzrdir, name=None, repository=None):
 
2195
    def initialize(self, a_bzrdir, name=None, repository=None,
 
2196
                   append_revisions_only=None):
2155
2197
        """Create a branch of this format in a_bzrdir."""
2156
2198
        utf8_files = [('last-revision', '0 null:\n'),
2157
 
                      ('branch.conf', ''),
 
2199
                      ('branch.conf',
 
2200
                          self._get_initial_config(append_revisions_only)),
2158
2201
                      ('tags', ''),
2159
2202
                      ('references', '')
2160
2203
                      ]
2162
2205
 
2163
2206
    def make_tags(self, branch):
2164
2207
        """See bzrlib.branch.BranchFormat.make_tags()."""
2165
 
        return BasicTags(branch)
 
2208
        return _mod_tag.BasicTags(branch)
2166
2209
 
2167
2210
    def supports_set_append_revisions_only(self):
2168
2211
        return True
2182
2225
    This format was introduced in bzr 1.6.
2183
2226
    """
2184
2227
 
2185
 
    def initialize(self, a_bzrdir, name=None, repository=None):
 
2228
    def initialize(self, a_bzrdir, name=None, repository=None,
 
2229
                   append_revisions_only=None):
2186
2230
        """Create a branch of this format in a_bzrdir."""
2187
2231
        utf8_files = [('last-revision', '0 null:\n'),
2188
 
                      ('branch.conf', ''),
 
2232
                      ('branch.conf',
 
2233
                          self._get_initial_config(append_revisions_only)),
2189
2234
                      ('tags', ''),
2190
2235
                      ]
2191
2236
        return self._initialize_helper(a_bzrdir, utf8_files, name, repository)
2209
2254
 
2210
2255
    def make_tags(self, branch):
2211
2256
        """See bzrlib.branch.BranchFormat.make_tags()."""
2212
 
        return BasicTags(branch)
 
2257
        return _mod_tag.BasicTags(branch)
2213
2258
 
2214
2259
    supports_reference_locations = False
2215
2260
 
2216
2261
 
2217
 
class BranchReferenceFormat(BranchFormat):
 
2262
class BranchReferenceFormat(BranchFormatMetadir):
2218
2263
    """Bzr branch reference format.
2219
2264
 
2220
2265
    Branch references are used in implementing checkouts, they
2244
2289
        location = transport.put_bytes('location', to_branch.base)
2245
2290
 
2246
2291
    def initialize(self, a_bzrdir, name=None, target_branch=None,
2247
 
            repository=None):
 
2292
            repository=None, append_revisions_only=None):
2248
2293
        """Create a branch of this format in a_bzrdir."""
2249
2294
        if target_branch is None:
2250
2295
            # this format does not implement branch itself, thus the implicit
2251
2296
            # creation contract must see it as uninitializable
2252
2297
            raise errors.UninitializableFormat(self)
2253
2298
        mutter('creating branch reference in %s', a_bzrdir.user_url)
 
2299
        if a_bzrdir._format.fixed_components:
 
2300
            raise errors.IncompatibleFormat(self, a_bzrdir._format)
2254
2301
        branch_transport = a_bzrdir.get_branch_transport(self, name=name)
2255
2302
        branch_transport.put_bytes('location',
2256
 
            target_branch.bzrdir.user_url)
 
2303
            target_branch.user_url)
2257
2304
        branch_transport.put_bytes('format', self.get_format_string())
2258
2305
        branch = self.open(
2259
2306
            a_bzrdir, name, _found=True,
2261
2308
        self._run_post_branch_init_hooks(a_bzrdir, name, branch)
2262
2309
        return branch
2263
2310
 
2264
 
    def __init__(self):
2265
 
        super(BranchReferenceFormat, self).__init__()
2266
 
        self._matchingbzrdir = bzrdir.BzrDirMetaFormat1()
2267
 
        self._matchingbzrdir.set_branch_format(self)
2268
 
 
2269
2311
    def _make_reference_clone_function(format, a_branch):
2270
2312
        """Create a clone() routine for a branch dynamically."""
2271
2313
        def clone(to_bzrdir, revision_id=None,
2300
2342
                    (format, self))
2301
2343
        if location is None:
2302
2344
            location = self.get_reference(a_bzrdir, name)
2303
 
        real_bzrdir = bzrdir.BzrDir.open(
 
2345
        real_bzrdir = controldir.ControlDir.open(
2304
2346
            location, possible_transports=possible_transports)
2305
2347
        result = real_bzrdir.open_branch(name=name, 
2306
2348
            ignore_fallbacks=ignore_fallbacks)
2396
2438
            raise ValueError('a_bzrdir must be supplied')
2397
2439
        else:
2398
2440
            self.bzrdir = a_bzrdir
2399
 
        self._base = self.bzrdir.transport.clone('..').base
 
2441
        self._user_transport = self.bzrdir.transport.clone('..')
 
2442
        if name is not None:
 
2443
            self._user_transport.set_segment_parameter(
 
2444
                "branch", urlutils.escape(name))
 
2445
        self._base = self._user_transport.base
2400
2446
        self.name = name
2401
 
        # XXX: We should be able to just do
2402
 
        #   self.base = self.bzrdir.root_transport.base
2403
 
        # but this does not quite work yet -- mbp 20080522
2404
2447
        self._format = _format
2405
2448
        if _control_files is None:
2406
2449
            raise ValueError('BzrBranch _control_files is None')
2410
2453
        Branch.__init__(self)
2411
2454
 
2412
2455
    def __str__(self):
2413
 
        if self.name is None:
2414
 
            return '%s(%s)' % (self.__class__.__name__, self.user_url)
2415
 
        else:
2416
 
            return '%s(%s,%s)' % (self.__class__.__name__, self.user_url,
2417
 
                self.name)
 
2456
        return '%s(%s)' % (self.__class__.__name__, self.user_url)
2418
2457
 
2419
2458
    __repr__ = __str__
2420
2459
 
2424
2463
 
2425
2464
    base = property(_get_base, doc="The URL for the root of this branch.")
2426
2465
 
 
2466
    @property
 
2467
    def user_transport(self):
 
2468
        return self._user_transport
 
2469
 
2427
2470
    def _get_config(self):
2428
 
        return TransportConfig(self._transport, 'branch.conf')
 
2471
        return _mod_config.TransportConfig(self._transport, 'branch.conf')
 
2472
 
 
2473
    def _get_config_store(self):
 
2474
        return _mod_config.BranchStore(self)
2429
2475
 
2430
2476
    def is_locked(self):
2431
2477
        return self.control_files.is_locked()
2512
2558
            raise errors.InvalidRevisionId(revision_id=revision_id, branch=self)
2513
2559
        revision_id = _mod_revision.ensure_null(revision_id)
2514
2560
        old_revno, old_revid = self.last_revision_info()
2515
 
        if self._get_append_revisions_only():
 
2561
        if self.get_append_revisions_only():
2516
2562
            self._check_history_violation(revision_id)
2517
2563
        self._run_pre_change_branch_tip_hooks(revno, revision_id)
2518
2564
        self._write_last_revision_info(revno, revision_id)
2679
2725
        self._set_revision_history(history)
2680
2726
 
2681
2727
    def _read_last_revision_info(self):
2682
 
        rh = self.revision_history()
 
2728
        rh = self._revision_history()
2683
2729
        revno = len(rh)
2684
2730
        if revno:
2685
2731
            return (revno, rh[-1])
2739
2785
        if revision_id == _mod_revision.NULL_REVISION:
2740
2786
            new_history = []
2741
2787
        else:
2742
 
            new_history = self.revision_history()
 
2788
            new_history = self._revision_history()
2743
2789
        if revision_id is not None and new_history != []:
2744
2790
            try:
2745
2791
                new_history = new_history[:new_history.index(revision_id) + 1]
2957
3003
            raise errors.NotStacked(self)
2958
3004
        return stacked_url
2959
3005
 
2960
 
    def _get_append_revisions_only(self):
2961
 
        return self.get_config(
2962
 
            ).get_user_option_as_bool('append_revisions_only')
2963
 
 
2964
3006
    @needs_read_lock
2965
3007
    def get_rev_id(self, revno, history=None):
2966
3008
        """Find the revision id of the specified revno."""
2995
3037
            except errors.RevisionNotPresent, e:
2996
3038
                raise errors.GhostRevisionsHaveNoRevno(revision_id, e.revision_id)
2997
3039
            index = len(self._partial_revision_history_cache) - 1
 
3040
            if index < 0:
 
3041
                raise errors.NoSuchRevision(self, revision_id)
2998
3042
            if self._partial_revision_history_cache[index] != revision_id:
2999
3043
                raise errors.NoSuchRevision(self, revision_id)
3000
3044
        return self.revno() - index
3052
3096
    :ivar local_branch: target branch if there is a Master, else None
3053
3097
    :ivar target_branch: Target/destination branch object. (write locked)
3054
3098
    :ivar tag_conflicts: A list of tag conflicts, see BasicTags.merge_to
 
3099
    :ivar tag_updates: A dict with new tags, see BasicTags.merge_to
3055
3100
    """
3056
3101
 
3057
3102
    @deprecated_method(deprecated_in((2, 3, 0)))
3063
3108
        return self.new_revno - self.old_revno
3064
3109
 
3065
3110
    def report(self, to_file):
 
3111
        tag_conflicts = getattr(self, "tag_conflicts", None)
 
3112
        tag_updates = getattr(self, "tag_updates", None)
3066
3113
        if not is_quiet():
3067
 
            if self.old_revid == self.new_revid:
3068
 
                to_file.write('No revisions to pull.\n')
3069
 
            else:
 
3114
            if self.old_revid != self.new_revid:
3070
3115
                to_file.write('Now on revision %d.\n' % self.new_revno)
 
3116
            if tag_updates:
 
3117
                to_file.write('%d tag(s) updated.\n' % len(tag_updates))
 
3118
            if self.old_revid == self.new_revid and not tag_updates:
 
3119
                if not tag_conflicts:
 
3120
                    to_file.write('No revisions or tags to pull.\n')
 
3121
                else:
 
3122
                    to_file.write('No revisions to pull.\n')
3071
3123
        self._show_tag_conficts(to_file)
3072
3124
 
3073
3125
 
3099
3151
        return self.new_revno - self.old_revno
3100
3152
 
3101
3153
    def report(self, to_file):
3102
 
        """Write a human-readable description of the result."""
3103
 
        if self.old_revid == self.new_revid:
3104
 
            note('No new revisions to push.')
3105
 
        else:
3106
 
            note('Pushed up to revision %d.' % self.new_revno)
 
3154
        # TODO: This function gets passed a to_file, but then
 
3155
        # ignores it and calls note() instead. This is also
 
3156
        # inconsistent with PullResult(), which writes to stdout.
 
3157
        # -- JRV20110901, bug #838853
 
3158
        tag_conflicts = getattr(self, "tag_conflicts", None)
 
3159
        tag_updates = getattr(self, "tag_updates", None)
 
3160
        if not is_quiet():
 
3161
            if self.old_revid != self.new_revid:
 
3162
                note(gettext('Pushed up to revision %d.') % self.new_revno)
 
3163
            if tag_updates:
 
3164
                note(ngettext('%d tag updated.', '%d tags updated.', len(tag_updates)) % len(tag_updates))
 
3165
            if self.old_revid == self.new_revid and not tag_updates:
 
3166
                if not tag_conflicts:
 
3167
                    note(gettext('No new revisions or tags to push.'))
 
3168
                else:
 
3169
                    note(gettext('No new revisions to push.'))
3107
3170
        self._show_tag_conficts(to_file)
3108
3171
 
3109
3172
 
3123
3186
        :param verbose: Requests more detailed display of what was checked,
3124
3187
            if any.
3125
3188
        """
3126
 
        note('checked branch %s format %s', self.branch.user_url,
3127
 
            self.branch._format)
 
3189
        note(gettext('checked branch {0} format {1}').format(
 
3190
                                self.branch.user_url, self.branch._format))
3128
3191
        for error in self.errors:
3129
 
            note('found error:%s', error)
 
3192
            note(gettext('found error:%s'), error)
3130
3193
 
3131
3194
 
3132
3195
class Converter5to6(object):
3171
3234
 
3172
3235
 
3173
3236
class Converter7to8(object):
3174
 
    """Perform an in-place upgrade of format 6 to format 7"""
 
3237
    """Perform an in-place upgrade of format 7 to format 8"""
3175
3238
 
3176
3239
    def convert(self, branch):
3177
3240
        format = BzrBranchFormat8()
3417
3480
            self._update_revisions(stop_revision, overwrite=overwrite,
3418
3481
                    graph=graph)
3419
3482
        if self.source._push_should_merge_tags():
3420
 
            result.tag_conflicts = self.source.tags.merge_to(self.target.tags,
3421
 
                overwrite)
 
3483
            result.tag_updates, result.tag_conflicts = (
 
3484
                self.source.tags.merge_to(self.target.tags, overwrite))
3422
3485
        result.new_revno, result.new_revid = self.target.last_revision_info()
3423
3486
        return result
3424
3487
 
3507
3570
            # TODO: The old revid should be specified when merging tags, 
3508
3571
            # so a tags implementation that versions tags can only 
3509
3572
            # pull in the most recent changes. -- JRV20090506
3510
 
            result.tag_conflicts = self.source.tags.merge_to(self.target.tags,
3511
 
                overwrite, ignore_master=not merge_tags_to_master)
 
3573
            result.tag_updates, result.tag_conflicts = (
 
3574
                self.source.tags.merge_to(self.target.tags, overwrite,
 
3575
                    ignore_master=not merge_tags_to_master))
3512
3576
            result.new_revno, result.new_revid = self.target.last_revision_info()
3513
3577
            if _hook_master:
3514
3578
                result.master_branch = _hook_master