~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/branch.py

  • Committer: jelmer at samba
  • Date: 2011-10-11 10:21:35 UTC
  • mto: This revision was merged to the branch mainline in revision 6214.
  • Revision ID: jelmer@samba.org-20111011102135-0wuzm1stjwxehkft
Move convenience methods to ControlDir.

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
20
19
 
22
21
lazy_import(globals(), """
23
22
import itertools
24
23
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,
44
 
    )
 
24
        bzrdir,
 
25
        cache_utf8,
 
26
        cleanup,
 
27
        config as _mod_config,
 
28
        debug,
 
29
        errors,
 
30
        fetch,
 
31
        graph as _mod_graph,
 
32
        lockdir,
 
33
        lockable_files,
 
34
        remote,
 
35
        repository,
 
36
        revision as _mod_revision,
 
37
        rio,
 
38
        tag as _mod_tag,
 
39
        transport,
 
40
        ui,
 
41
        urlutils,
 
42
        )
45
43
from bzrlib.i18n import gettext, ngettext
46
44
""")
47
45
 
109
107
        for existing_fallback_repo in self.repository._fallback_repositories:
110
108
            if existing_fallback_repo.user_url == url:
111
109
                # This fallback is already configured.  This probably only
112
 
                # happens because ControlDir.sprout is a horrible mess.  To avoid
 
110
                # happens because BzrDir.sprout is a horrible mess.  To avoid
113
111
                # confusing _unstack we don't add this a second time.
114
112
                mutter('duplicate activation of fallback %r on %r', url, self)
115
113
                return
173
171
        For instance, if the branch is at URL/.bzr/branch,
174
172
        Branch.open(URL) -> a Branch instance.
175
173
        """
176
 
        control = controldir.ControlDir.open(base, _unsupported,
 
174
        control = bzrdir.BzrDir.open(base, _unsupported,
177
175
                                     possible_transports=possible_transports)
178
176
        return control.open_branch(unsupported=_unsupported)
179
177
 
180
178
    @staticmethod
181
179
    def open_from_transport(transport, name=None, _unsupported=False):
182
180
        """Open the branch rooted at transport"""
183
 
        control = controldir.ControlDir.open_from_transport(transport, _unsupported)
 
181
        control = bzrdir.BzrDir.open_from_transport(transport, _unsupported)
184
182
        return control.open_branch(name=name, unsupported=_unsupported)
185
183
 
186
184
    @staticmethod
195
193
        format, UnknownFormatError or UnsupportedFormatError are raised.
196
194
        If there is one, it is returned, along with the unused portion of url.
197
195
        """
198
 
        control, relpath = controldir.ControlDir.open_containing(url,
 
196
        control, relpath = bzrdir.BzrDir.open_containing(url,
199
197
                                                         possible_transports)
200
198
        return control.open_branch(), relpath
201
199
 
883
881
            # stream from one of them to the other.  This does mean doing
884
882
            # separate SSH connection setup, but unstacking is not a
885
883
            # common operation so it's tolerable.
886
 
            new_bzrdir = controldir.ControlDir.open(
887
 
                self.bzrdir.root_transport.base)
 
884
            new_bzrdir = bzrdir.BzrDir.open(self.bzrdir.root_transport.base)
888
885
            new_repository = new_bzrdir.find_repository()
889
886
            if new_repository._fallback_repositories:
890
887
                raise AssertionError("didn't expect %r to have "
1007
1004
        """
1008
1005
        raise NotImplementedError(self._gen_revision_history)
1009
1006
 
1010
 
    @deprecated_method(deprecated_in((2, 5, 0)))
1011
1007
    @needs_read_lock
1012
1008
    def revision_history(self):
1013
1009
        """Return sequence of revision ids on this branch.
1015
1011
        This method will cache the revision history for as long as it is safe to
1016
1012
        do so.
1017
1013
        """
1018
 
        return self._revision_history()
1019
 
 
1020
 
    def _revision_history(self):
1021
1014
        if 'evil' in debug.debug_flags:
1022
1015
            mutter_callsite(3, "revision_history scales with history.")
1023
1016
        if self._revision_history_cache is not None:
1093
1086
        """Given a revision id, return its revno"""
1094
1087
        if _mod_revision.is_null(revision_id):
1095
1088
            return 0
1096
 
        history = self._revision_history()
 
1089
        history = self.revision_history()
1097
1090
        try:
1098
1091
            return history.index(revision_id) + 1
1099
1092
        except ValueError:
1396
1389
        # TODO: We should probably also check that self.revision_history
1397
1390
        # matches the repository for older branch formats.
1398
1391
        # If looking for the code that cross-checks repository parents against
1399
 
        # the Graph.iter_lefthand_ancestry output, that is now a repository
 
1392
        # the iter_reverse_revision_history output, that is now a repository
1400
1393
        # specific check.
1401
1394
        return result
1402
1395
 
1458
1451
            from_branch = BranchReferenceFormat().initialize(checkout, 
1459
1452
                target_branch=self)
1460
1453
        else:
1461
 
            checkout_branch = controldir.ControlDir.create_branch_convenience(
 
1454
            checkout_branch = bzrdir.BzrDir.create_branch_convenience(
1462
1455
                to_location, force_new_tree=False, format=format)
1463
1456
            checkout = checkout_branch.bzrdir
1464
1457
            checkout_branch.bind(self)
1602
1595
        return not (self == other)
1603
1596
 
1604
1597
    @classmethod
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:
 
1598
    def find_format(klass, a_bzrdir, name=None):
 
1599
        """Return the format for the branch object in a_bzrdir."""
 
1600
        try:
 
1601
            transport = a_bzrdir.get_branch_transport(None, name=name)
1612
1602
            format_string = transport.get_bytes("format")
1613
1603
            return format_registry.get(format_string)
1614
1604
        except errors.NoSuchFile:
1615
 
            raise errors.NotBranchError(path=transport.base, bzrdir=controldir)
 
1605
            raise errors.NotBranchError(path=transport.base, bzrdir=a_bzrdir)
1616
1606
        except KeyError:
1617
1607
            raise errors.UnknownFormatError(format=format_string, kind='branch')
1618
1608
 
1632
1622
        """
1633
1623
        return format_registry._get_all()
1634
1624
 
1635
 
    def get_reference(self, controldir, name=None):
1636
 
        """Get the target reference of the branch in controldir.
 
1625
    def get_reference(self, a_bzrdir, name=None):
 
1626
        """Get the target reference of the branch in a_bzrdir.
1637
1627
 
1638
1628
        format probing must have been completed before calling
1639
1629
        this method - it is assumed that the format of the branch
1640
 
        in controldir is correct.
 
1630
        in a_bzrdir is correct.
1641
1631
 
1642
 
        :param controldir: The controldir to get the branch data from.
 
1632
        :param a_bzrdir: The bzrdir to get the branch data from.
1643
1633
        :param name: Name of the colocated branch to fetch
1644
1634
        :return: None if the branch is not a reference branch.
1645
1635
        """
1646
1636
        return None
1647
1637
 
1648
1638
    @classmethod
1649
 
    def set_reference(self, controldir, name, to_branch):
1650
 
        """Set the target reference of the branch in controldir.
 
1639
    def set_reference(self, a_bzrdir, name, to_branch):
 
1640
        """Set the target reference of the branch in a_bzrdir.
1651
1641
 
1652
1642
        format probing must have been completed before calling
1653
1643
        this method - it is assumed that the format of the branch
1654
 
        in controldir is correct.
 
1644
        in a_bzrdir is correct.
1655
1645
 
1656
 
        :param controldir: The controldir to set the branch reference for.
 
1646
        :param a_bzrdir: The bzrdir to set the branch reference for.
1657
1647
        :param name: Name of colocated branch to set, None for default
1658
1648
        :param to_branch: branch that the checkout is to reference
1659
1649
        """
1667
1657
        """Return the short format description for this format."""
1668
1658
        raise NotImplementedError(self.get_format_description)
1669
1659
 
1670
 
    def _run_post_branch_init_hooks(self, controldir, name, branch):
 
1660
    def _run_post_branch_init_hooks(self, a_bzrdir, name, branch):
1671
1661
        hooks = Branch.hooks['post_branch_init']
1672
1662
        if not hooks:
1673
1663
            return
1674
 
        params = BranchInitHookParams(self, controldir, name, branch)
 
1664
        params = BranchInitHookParams(self, a_bzrdir, name, branch)
1675
1665
        for hook in hooks:
1676
1666
            hook(params)
1677
1667
 
1678
 
    def initialize(self, controldir, name=None, repository=None,
 
1668
    def initialize(self, a_bzrdir, name=None, repository=None,
1679
1669
                   append_revisions_only=None):
1680
 
        """Create a branch of this format in controldir.
1681
 
 
 
1670
        """Create a branch of this format in a_bzrdir.
 
1671
        
1682
1672
        :param name: Name of the colocated branch to create.
1683
1673
        """
1684
1674
        raise NotImplementedError(self.initialize)
1716
1706
        """
1717
1707
        raise NotImplementedError(self.network_name)
1718
1708
 
1719
 
    def open(self, controldir, name=None, _found=False, ignore_fallbacks=False,
 
1709
    def open(self, a_bzrdir, name=None, _found=False, ignore_fallbacks=False,
1720
1710
            found_repository=None):
1721
 
        """Return the branch object for controldir.
 
1711
        """Return the branch object for a_bzrdir
1722
1712
 
1723
 
        :param controldir: A ControlDir that contains a branch.
 
1713
        :param a_bzrdir: A BzrDir that contains a branch.
1724
1714
        :param name: Name of colocated branch to open
1725
1715
        :param _found: a private parameter, do not use it. It is used to
1726
1716
            indicate if format probing has already be done.
1946
1936
    There are 4 fields that hooks may wish to access:
1947
1937
 
1948
1938
    :ivar format: the branch format
1949
 
    :ivar bzrdir: the ControlDir where the branch will be/has been initialized
 
1939
    :ivar bzrdir: the BzrDir where the branch will be/has been initialized
1950
1940
    :ivar name: name of colocated branch, if any (or None)
1951
1941
    :ivar branch: the branch created
1952
1942
 
1955
1945
    branch, which refer to the original branch.
1956
1946
    """
1957
1947
 
1958
 
    def __init__(self, format, controldir, name, branch):
 
1948
    def __init__(self, format, a_bzrdir, name, branch):
1959
1949
        """Create a group of BranchInitHook parameters.
1960
1950
 
1961
1951
        :param format: the branch format
1962
 
        :param controldir: the ControlDir where the branch will be/has been
 
1952
        :param a_bzrdir: the BzrDir where the branch will be/has been
1963
1953
            initialized
1964
1954
        :param name: name of colocated branch, if any (or None)
1965
1955
        :param branch: the branch created
1969
1959
        in branch, which refer to the original branch.
1970
1960
        """
1971
1961
        self.format = format
1972
 
        self.bzrdir = controldir
 
1962
        self.bzrdir = a_bzrdir
1973
1963
        self.name = name
1974
1964
        self.branch = branch
1975
1965
 
1985
1975
 
1986
1976
    There are 4 fields that hooks may wish to access:
1987
1977
 
1988
 
    :ivar control_dir: ControlDir of the checkout to change
 
1978
    :ivar control_dir: BzrDir of the checkout to change
1989
1979
    :ivar to_branch: branch that the checkout is to reference
1990
1980
    :ivar force: skip the check for local commits in a heavy checkout
1991
1981
    :ivar revision_id: revision ID to switch to (or None)
1994
1984
    def __init__(self, control_dir, to_branch, force, revision_id):
1995
1985
        """Create a group of SwitchHook parameters.
1996
1986
 
1997
 
        :param control_dir: ControlDir of the checkout to change
 
1987
        :param control_dir: BzrDir of the checkout to change
1998
1988
        :param to_branch: branch that the checkout is to reference
1999
1989
        :param force: skip the check for local commits in a heavy checkout
2000
1990
        :param revision_id: revision ID to switch to (or None)
2087
2077
        except errors.NoSuchFile:
2088
2078
            raise errors.NotBranchError(path=transport.base, bzrdir=a_bzrdir)
2089
2079
 
2090
 
    @property
2091
 
    def _matchingbzrdir(self):
2092
 
        ret = bzrdir.BzrDirMetaFormat1()
2093
 
        ret.set_branch_format(self)
2094
 
        return ret
 
2080
    def __init__(self):
 
2081
        super(BranchFormatMetadir, self).__init__()
 
2082
        self._matchingbzrdir = bzrdir.BzrDirMetaFormat1()
 
2083
        self._matchingbzrdir.set_branch_format(self)
2095
2084
 
2096
2085
    def supports_tags(self):
2097
2086
        return True
2259
2248
    supports_reference_locations = False
2260
2249
 
2261
2250
 
2262
 
class BranchReferenceFormat(BranchFormatMetadir):
 
2251
class BranchReferenceFormat(BranchFormat):
2263
2252
    """Bzr branch reference format.
2264
2253
 
2265
2254
    Branch references are used in implementing checkouts, they
2300
2289
            raise errors.IncompatibleFormat(self, a_bzrdir._format)
2301
2290
        branch_transport = a_bzrdir.get_branch_transport(self, name=name)
2302
2291
        branch_transport.put_bytes('location',
2303
 
            target_branch.user_url)
 
2292
            target_branch.bzrdir.user_url)
2304
2293
        branch_transport.put_bytes('format', self.get_format_string())
2305
2294
        branch = self.open(
2306
2295
            a_bzrdir, name, _found=True,
2308
2297
        self._run_post_branch_init_hooks(a_bzrdir, name, branch)
2309
2298
        return branch
2310
2299
 
 
2300
    def __init__(self):
 
2301
        super(BranchReferenceFormat, self).__init__()
 
2302
        self._matchingbzrdir = bzrdir.BzrDirMetaFormat1()
 
2303
        self._matchingbzrdir.set_branch_format(self)
 
2304
 
2311
2305
    def _make_reference_clone_function(format, a_branch):
2312
2306
        """Create a clone() routine for a branch dynamically."""
2313
2307
        def clone(to_bzrdir, revision_id=None,
2342
2336
                    (format, self))
2343
2337
        if location is None:
2344
2338
            location = self.get_reference(a_bzrdir, name)
2345
 
        real_bzrdir = controldir.ControlDir.open(
 
2339
        real_bzrdir = bzrdir.BzrDir.open(
2346
2340
            location, possible_transports=possible_transports)
2347
2341
        result = real_bzrdir.open_branch(name=name, 
2348
2342
            ignore_fallbacks=ignore_fallbacks)
2438
2432
            raise ValueError('a_bzrdir must be supplied')
2439
2433
        else:
2440
2434
            self.bzrdir = a_bzrdir
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
 
2435
        self._base = self.bzrdir.transport.clone('..').base
2446
2436
        self.name = name
 
2437
        # XXX: We should be able to just do
 
2438
        #   self.base = self.bzrdir.root_transport.base
 
2439
        # but this does not quite work yet -- mbp 20080522
2447
2440
        self._format = _format
2448
2441
        if _control_files is None:
2449
2442
            raise ValueError('BzrBranch _control_files is None')
2453
2446
        Branch.__init__(self)
2454
2447
 
2455
2448
    def __str__(self):
2456
 
        return '%s(%s)' % (self.__class__.__name__, self.user_url)
 
2449
        if self.name is None:
 
2450
            return '%s(%s)' % (self.__class__.__name__, self.user_url)
 
2451
        else:
 
2452
            return '%s(%s,%s)' % (self.__class__.__name__, self.user_url,
 
2453
                self.name)
2457
2454
 
2458
2455
    __repr__ = __str__
2459
2456
 
2463
2460
 
2464
2461
    base = property(_get_base, doc="The URL for the root of this branch.")
2465
2462
 
2466
 
    @property
2467
 
    def user_transport(self):
2468
 
        return self._user_transport
2469
 
 
2470
2463
    def _get_config(self):
2471
2464
        return _mod_config.TransportConfig(self._transport, 'branch.conf')
2472
2465
 
2473
 
    def _get_config_store(self):
2474
 
        return _mod_config.BranchStore(self)
2475
 
 
2476
2466
    def is_locked(self):
2477
2467
        return self.control_files.is_locked()
2478
2468
 
2725
2715
        self._set_revision_history(history)
2726
2716
 
2727
2717
    def _read_last_revision_info(self):
2728
 
        rh = self._revision_history()
 
2718
        rh = self.revision_history()
2729
2719
        revno = len(rh)
2730
2720
        if revno:
2731
2721
            return (revno, rh[-1])
2785
2775
        if revision_id == _mod_revision.NULL_REVISION:
2786
2776
            new_history = []
2787
2777
        else:
2788
 
            new_history = self._revision_history()
 
2778
            new_history = self.revision_history()
2789
2779
        if revision_id is not None and new_history != []:
2790
2780
            try:
2791
2781
                new_history = new_history[:new_history.index(revision_id) + 1]
3037
3027
            except errors.RevisionNotPresent, e:
3038
3028
                raise errors.GhostRevisionsHaveNoRevno(revision_id, e.revision_id)
3039
3029
            index = len(self._partial_revision_history_cache) - 1
3040
 
            if index < 0:
3041
 
                raise errors.NoSuchRevision(self, revision_id)
3042
3030
            if self._partial_revision_history_cache[index] != revision_id:
3043
3031
                raise errors.NoSuchRevision(self, revision_id)
3044
3032
        return self.revno() - index