~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/branch.py

  • Committer: John Arbash Meinel
  • Date: 2010-08-02 19:20:30 UTC
  • mto: This revision was merged to the branch mainline in revision 5369.
  • Revision ID: john@arbash-meinel.com-20100802192030-p5ofsyvopbog4xj3
Simplify the test to better cope with platform and version variation.

Show diffs side-by-side

added added

removed removed

Lines of Context:
25
25
        bzrdir,
26
26
        cache_utf8,
27
27
        config as _mod_config,
28
 
        controldir,
29
28
        debug,
30
29
        errors,
31
30
        lockdir,
65
64
BZR_BRANCH_FORMAT_6 = "Bazaar Branch Format 6 (bzr 0.15)\n"
66
65
 
67
66
 
68
 
class Branch(controldir.ControlComponent):
 
67
class Branch(bzrdir.ControlComponent):
69
68
    """Branch holding a history of revisions.
70
69
 
71
70
    :ivar base:
92
91
        self._revision_id_to_revno_cache = None
93
92
        self._partial_revision_id_to_revno_cache = {}
94
93
        self._partial_revision_history_cache = []
95
 
        self._tags_bytes = None
96
94
        self._last_revision_info_cache = None
97
95
        self._merge_sorted_revisions_cache = None
98
96
        self._open_hook()
105
103
 
106
104
    def _activate_fallback_location(self, url):
107
105
        """Activate the branch/repository from url as a fallback repository."""
108
 
        for existing_fallback_repo in self.repository._fallback_repositories:
109
 
            if existing_fallback_repo.user_url == url:
110
 
                # This fallback is already configured.  This probably only
111
 
                # happens because BzrDir.sprout is a horrible mess.  To avoid
112
 
                # confusing _unstack we don't add this a second time.
113
 
                mutter('duplicate activation of fallback %r on %r', url, self)
114
 
                return
115
106
        repo = self._get_fallback_repository(url)
116
107
        if repo.has_same_location(self.repository):
117
108
            raise errors.UnstackableLocationError(self.user_url, url)
235
226
            possible_transports=[self.bzrdir.root_transport])
236
227
        return a_branch.repository
237
228
 
238
 
    @needs_read_lock
239
229
    def _get_tags_bytes(self):
240
230
        """Get the bytes of a serialised tags dict.
241
231
 
248
238
        :return: The bytes of the tags file.
249
239
        :seealso: Branch._set_tags_bytes.
250
240
        """
251
 
        if self._tags_bytes is None:
252
 
            self._tags_bytes = self._transport.get_bytes('tags')
253
 
        return self._tags_bytes
 
241
        return self._transport.get_bytes('tags')
254
242
 
255
243
    def _get_nick(self, local=False, possible_transports=None):
256
244
        config = self.get_config()
258
246
        if not local and not config.has_explicit_nickname():
259
247
            try:
260
248
                master = self.get_master_branch(possible_transports)
261
 
                if master and self.user_url == master.user_url:
262
 
                    raise errors.RecursiveBind(self.user_url)
263
249
                if master is not None:
264
250
                    # return the master branch value
265
251
                    return master.nick
266
 
            except errors.RecursiveBind, e:
267
 
                raise e
268
252
            except errors.BzrError, e:
269
253
                # Silently fall back to local implicit nick if the master is
270
254
                # unavailable
816
800
            old_repository = self.repository
817
801
            if len(old_repository._fallback_repositories) != 1:
818
802
                raise AssertionError("can't cope with fallback repositories "
819
 
                    "of %r (fallbacks: %r)" % (old_repository,
820
 
                        old_repository._fallback_repositories))
 
803
                    "of %r" % (self.repository,))
821
804
            # Open the new repository object.
822
805
            # Repositories don't offer an interface to remove fallback
823
806
            # repositories today; take the conceptually simpler option and just
888
871
 
889
872
        :seealso: Branch._get_tags_bytes.
890
873
        """
891
 
        return _run_with_write_locked_target(self, self._set_tags_bytes_locked,
892
 
                bytes)
893
 
 
894
 
    def _set_tags_bytes_locked(self, bytes):
895
 
        self._tags_bytes = bytes
896
 
        return self._transport.put_bytes('tags', bytes)
 
874
        return _run_with_write_locked_target(self, self._transport.put_bytes,
 
875
            'tags', bytes)
897
876
 
898
877
    def _cache_revision_history(self, rev_history):
899
878
        """Set the cached revision history to rev_history.
929
908
        self._merge_sorted_revisions_cache = None
930
909
        self._partial_revision_history_cache = []
931
910
        self._partial_revision_id_to_revno_cache = {}
932
 
        self._tags_bytes = None
933
911
 
934
912
    def _gen_revision_history(self):
935
913
        """Return sequence of revision hashes on to this branch.
1274
1252
        return result
1275
1253
 
1276
1254
    @needs_read_lock
1277
 
    def sprout(self, to_bzrdir, revision_id=None, repository_policy=None,
1278
 
            repository=None):
 
1255
    def sprout(self, to_bzrdir, revision_id=None, repository_policy=None):
1279
1256
        """Create a new line of development from the branch, into to_bzrdir.
1280
1257
 
1281
1258
        to_bzrdir controls the branch format.
1286
1263
        if (repository_policy is not None and
1287
1264
            repository_policy.requires_stacking()):
1288
1265
            to_bzrdir._format.require_stacking(_skip_repo=True)
1289
 
        result = to_bzrdir.create_branch(repository=repository)
 
1266
        result = to_bzrdir.create_branch()
1290
1267
        result.lock_write()
1291
1268
        try:
1292
1269
            if repository_policy is not None:
1390
1367
        return format
1391
1368
 
1392
1369
    def create_clone_on_transport(self, to_transport, revision_id=None,
1393
 
        stacked_on=None, create_prefix=False, use_existing_dir=False,
1394
 
        no_tree=None):
 
1370
        stacked_on=None, create_prefix=False, use_existing_dir=False):
1395
1371
        """Create a clone of this branch and its bzrdir.
1396
1372
 
1397
1373
        :param to_transport: The transport to clone onto.
1410
1386
            revision_id = self.last_revision()
1411
1387
        dir_to = self.bzrdir.clone_on_transport(to_transport,
1412
1388
            revision_id=revision_id, stacked_on=stacked_on,
1413
 
            create_prefix=create_prefix, use_existing_dir=use_existing_dir,
1414
 
            no_tree=no_tree)
 
1389
            create_prefix=create_prefix, use_existing_dir=use_existing_dir)
1415
1390
        return dir_to.open_branch()
1416
1391
 
1417
1392
    def create_checkout(self, to_location, revision_id=None,
1542
1517
     * an open routine.
1543
1518
 
1544
1519
    Formats are placed in an dict by their format string for reference
1545
 
    during branch opening. It's not required that these be instances, they
 
1520
    during branch opening. Its not required that these be instances, they
1546
1521
    can be classes themselves with class methods - it simply depends on
1547
1522
    whether state is needed for a given format or not.
1548
1523
 
1643
1618
            hook(params)
1644
1619
 
1645
1620
    def _initialize_helper(self, a_bzrdir, utf8_files, name=None,
1646
 
                           repository=None, lock_type='metadir',
1647
 
                           set_format=True):
 
1621
                           lock_type='metadir', set_format=True):
1648
1622
        """Initialize a branch in a bzrdir, with specified files
1649
1623
 
1650
1624
        :param a_bzrdir: The bzrdir to initialize the branch in
1684
1658
        finally:
1685
1659
            if lock_taken:
1686
1660
                control_files.unlock()
1687
 
        branch = self.open(a_bzrdir, name, _found=True,
1688
 
                found_repository=repository)
 
1661
        branch = self.open(a_bzrdir, name, _found=True)
1689
1662
        self._run_post_branch_init_hooks(a_bzrdir, name, branch)
1690
1663
        return branch
1691
1664
 
1692
 
    def initialize(self, a_bzrdir, name=None, repository=None):
 
1665
    def initialize(self, a_bzrdir, name=None):
1693
1666
        """Create a branch of this format in a_bzrdir.
1694
1667
        
1695
1668
        :param name: Name of the colocated branch to create.
1729
1702
        """
1730
1703
        raise NotImplementedError(self.network_name)
1731
1704
 
1732
 
    def open(self, a_bzrdir, name=None, _found=False, ignore_fallbacks=False,
1733
 
            found_repository=None):
 
1705
    def open(self, a_bzrdir, name=None, _found=False, ignore_fallbacks=False):
1734
1706
        """Return the branch object for a_bzrdir
1735
1707
 
1736
1708
        :param a_bzrdir: A BzrDir that contains a branch.
1842
1814
            "with a bzrlib.branch.PullResult object and only runs in the "
1843
1815
            "bzr client.", (0, 15), None))
1844
1816
        self.create_hook(HookPoint('pre_commit',
1845
 
            "Called after a commit is calculated but before it is "
 
1817
            "Called after a commit is calculated but before it is is "
1846
1818
            "completed. pre_commit is called with (local, master, old_revno, "
1847
1819
            "old_revid, future_revno, future_revid, tree_delta, future_tree"
1848
1820
            "). old_revid is NULL_REVISION for the first commit to a branch, "
1885
1857
            "all are called with the url returned from the previous hook."
1886
1858
            "The order is however undefined.", (1, 9), None))
1887
1859
        self.create_hook(HookPoint('automatic_tag_name',
1888
 
            "Called to determine an automatic tag name for a revision. "
 
1860
            "Called to determine an automatic tag name for a revision."
1889
1861
            "automatic_tag_name is called with (branch, revision_id) and "
1890
1862
            "should return a tag name or None if no tag name could be "
1891
1863
            "determined. The first non-None tag name returned will be used.",
1982
1954
        return self.__dict__ == other.__dict__
1983
1955
 
1984
1956
    def __repr__(self):
1985
 
        return "<%s of %s>" % (self.__class__.__name__, self.branch)
 
1957
        if self.branch:
 
1958
            return "<%s of %s>" % (self.__class__.__name__, self.branch)
 
1959
        else:
 
1960
            return "<%s of format:%s bzrdir:%s>" % (
 
1961
                self.__class__.__name__, self.branch,
 
1962
                self.format, self.bzrdir)
1986
1963
 
1987
1964
 
1988
1965
class SwitchHookParams(object):
2030
2007
        """See BranchFormat.get_format_description()."""
2031
2008
        return "Branch format 4"
2032
2009
 
2033
 
    def initialize(self, a_bzrdir, name=None, repository=None):
 
2010
    def initialize(self, a_bzrdir, name=None):
2034
2011
        """Create a branch of this format in a_bzrdir."""
2035
 
        if repository is not None:
2036
 
            raise NotImplementedError(
2037
 
                "initialize(repository=<not None>) on %r" % (self,))
2038
2012
        utf8_files = [('revision-history', ''),
2039
2013
                      ('branch-name', ''),
2040
2014
                      ]
2049
2023
        """The network name for this format is the control dirs disk label."""
2050
2024
        return self._matchingbzrdir.get_format_string()
2051
2025
 
2052
 
    def open(self, a_bzrdir, name=None, _found=False, ignore_fallbacks=False,
2053
 
            found_repository=None):
 
2026
    def open(self, a_bzrdir, name=None, _found=False, ignore_fallbacks=False):
2054
2027
        """See BranchFormat.open()."""
2055
2028
        if not _found:
2056
2029
            # we are being called directly and must probe.
2057
2030
            raise NotImplementedError
2058
 
        if found_repository is None:
2059
 
            found_repository = a_bzrdir.open_repository()
2060
2031
        return BzrBranch(_format=self,
2061
2032
                         _control_files=a_bzrdir._control_files,
2062
2033
                         a_bzrdir=a_bzrdir,
2063
2034
                         name=name,
2064
 
                         _repository=found_repository)
 
2035
                         _repository=a_bzrdir.open_repository())
2065
2036
 
2066
2037
    def __str__(self):
2067
2038
        return "Bazaar-NG branch format 4"
2081
2052
        """
2082
2053
        return self.get_format_string()
2083
2054
 
2084
 
    def open(self, a_bzrdir, name=None, _found=False, ignore_fallbacks=False,
2085
 
            found_repository=None):
 
2055
    def open(self, a_bzrdir, name=None, _found=False, ignore_fallbacks=False):
2086
2056
        """See BranchFormat.open()."""
2087
2057
        if not _found:
2088
2058
            format = BranchFormat.find_format(a_bzrdir, name=name)
2093
2063
        try:
2094
2064
            control_files = lockable_files.LockableFiles(transport, 'lock',
2095
2065
                                                         lockdir.LockDir)
2096
 
            if found_repository is None:
2097
 
                found_repository = a_bzrdir.find_repository()
2098
2066
            return self._branch_class()(_format=self,
2099
2067
                              _control_files=control_files,
2100
2068
                              name=name,
2101
2069
                              a_bzrdir=a_bzrdir,
2102
 
                              _repository=found_repository,
 
2070
                              _repository=a_bzrdir.find_repository(),
2103
2071
                              ignore_fallbacks=ignore_fallbacks)
2104
2072
        except errors.NoSuchFile:
2105
2073
            raise errors.NotBranchError(path=transport.base, bzrdir=a_bzrdir)
2137
2105
        """See BranchFormat.get_format_description()."""
2138
2106
        return "Branch format 5"
2139
2107
 
2140
 
    def initialize(self, a_bzrdir, name=None, repository=None):
 
2108
    def initialize(self, a_bzrdir, name=None):
2141
2109
        """Create a branch of this format in a_bzrdir."""
2142
2110
        utf8_files = [('revision-history', ''),
2143
2111
                      ('branch-name', ''),
2144
2112
                      ]
2145
 
        return self._initialize_helper(a_bzrdir, utf8_files, name, repository)
 
2113
        return self._initialize_helper(a_bzrdir, utf8_files, name)
2146
2114
 
2147
2115
    def supports_tags(self):
2148
2116
        return False
2170
2138
        """See BranchFormat.get_format_description()."""
2171
2139
        return "Branch format 6"
2172
2140
 
2173
 
    def initialize(self, a_bzrdir, name=None, repository=None):
 
2141
    def initialize(self, a_bzrdir, name=None):
2174
2142
        """Create a branch of this format in a_bzrdir."""
2175
2143
        utf8_files = [('last-revision', '0 null:\n'),
2176
2144
                      ('branch.conf', ''),
2177
2145
                      ('tags', ''),
2178
2146
                      ]
2179
 
        return self._initialize_helper(a_bzrdir, utf8_files, name, repository)
 
2147
        return self._initialize_helper(a_bzrdir, utf8_files, name)
2180
2148
 
2181
2149
    def make_tags(self, branch):
2182
2150
        """See bzrlib.branch.BranchFormat.make_tags()."""
2200
2168
        """See BranchFormat.get_format_description()."""
2201
2169
        return "Branch format 8"
2202
2170
 
2203
 
    def initialize(self, a_bzrdir, name=None, repository=None):
 
2171
    def initialize(self, a_bzrdir, name=None):
2204
2172
        """Create a branch of this format in a_bzrdir."""
2205
2173
        utf8_files = [('last-revision', '0 null:\n'),
2206
2174
                      ('branch.conf', ''),
2207
2175
                      ('tags', ''),
2208
2176
                      ('references', '')
2209
2177
                      ]
2210
 
        return self._initialize_helper(a_bzrdir, utf8_files, name, repository)
 
2178
        return self._initialize_helper(a_bzrdir, utf8_files, name)
2211
2179
 
2212
2180
    def __init__(self):
2213
2181
        super(BzrBranchFormat8, self).__init__()
2236
2204
    This format was introduced in bzr 1.6.
2237
2205
    """
2238
2206
 
2239
 
    def initialize(self, a_bzrdir, name=None, repository=None):
 
2207
    def initialize(self, a_bzrdir, name=None):
2240
2208
        """Create a branch of this format in a_bzrdir."""
2241
2209
        utf8_files = [('last-revision', '0 null:\n'),
2242
2210
                      ('branch.conf', ''),
2243
2211
                      ('tags', ''),
2244
2212
                      ]
2245
 
        return self._initialize_helper(a_bzrdir, utf8_files, name, repository)
 
2213
        return self._initialize_helper(a_bzrdir, utf8_files, name)
2246
2214
 
2247
2215
    def _branch_class(self):
2248
2216
        return BzrBranch7
2290
2258
        transport = a_bzrdir.get_branch_transport(None, name=name)
2291
2259
        location = transport.put_bytes('location', to_branch.base)
2292
2260
 
2293
 
    def initialize(self, a_bzrdir, name=None, target_branch=None,
2294
 
            repository=None):
 
2261
    def initialize(self, a_bzrdir, name=None, target_branch=None):
2295
2262
        """Create a branch of this format in a_bzrdir."""
2296
2263
        if target_branch is None:
2297
2264
            # this format does not implement branch itself, thus the implicit
2325
2292
        return clone
2326
2293
 
2327
2294
    def open(self, a_bzrdir, name=None, _found=False, location=None,
2328
 
             possible_transports=None, ignore_fallbacks=False,
2329
 
             found_repository=None):
 
2295
             possible_transports=None, ignore_fallbacks=False):
2330
2296
        """Return the branch that the branch reference in a_bzrdir points at.
2331
2297
 
2332
2298
        :param a_bzrdir: A BzrDir that contains a branch.
3137
3103
    :ivar tag_conflicts: A list of tag conflicts, see BasicTags.merge_to
3138
3104
    """
3139
3105
 
3140
 
    @deprecated_method(deprecated_in((2, 3, 0)))
3141
3106
    def __int__(self):
3142
 
        """Return the relative change in revno.
3143
 
 
3144
 
        :deprecated: Use `new_revno` and `old_revno` instead.
3145
 
        """
 
3107
        # DEPRECATED: pull used to return the change in revno
3146
3108
        return self.new_revno - self.old_revno
3147
3109
 
3148
3110
    def report(self, to_file):
3173
3135
        target, otherwise it will be None.
3174
3136
    """
3175
3137
 
3176
 
    @deprecated_method(deprecated_in((2, 3, 0)))
3177
3138
    def __int__(self):
3178
 
        """Return the relative change in revno.
3179
 
 
3180
 
        :deprecated: Use `new_revno` and `old_revno` instead.
3181
 
        """
 
3139
        # DEPRECATED: push used to return the change in revno
3182
3140
        return self.new_revno - self.old_revno
3183
3141
 
3184
3142
    def report(self, to_file):
3378
3336
        if isinstance(format, remote.RemoteBranchFormat):
3379
3337
            format._ensure_real()
3380
3338
            return format._custom_format
3381
 
        return format
 
3339
        return format                                                                                                  
3382
3340
 
3383
3341
    @needs_write_lock
3384
3342
    def copy_content_into(self, revision_id=None):
3514
3472
                # push into the master from the source branch.
3515
3473
                self.source._basic_push(master_branch, overwrite, stop_revision)
3516
3474
                # and push into the target branch from the source. Note that we
3517
 
                # push from the source branch again, because it's considered the
 
3475
                # push from the source branch again, because its considered the
3518
3476
                # highest bandwidth repository.
3519
3477
                result = self.source._basic_push(self.target, overwrite,
3520
3478
                    stop_revision)