~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/branch.py

  • Committer: Jelmer Vernooij
  • Date: 2010-12-20 02:23:31 UTC
  • mto: This revision was merged to the branch mainline in revision 5577.
  • Revision ID: jelmer@samba.org-20101220022331-hbm91o1ps9gjrlns
Add testr magic for bzr selftest --list

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,
28
29
        debug,
29
30
        errors,
30
31
        lockdir,
64
65
BZR_BRANCH_FORMAT_6 = "Bazaar Branch Format 6 (bzr 0.15)\n"
65
66
 
66
67
 
67
 
class Branch(bzrdir.ControlComponent):
 
68
class Branch(controldir.ControlComponent):
68
69
    """Branch holding a history of revisions.
69
70
 
70
71
    :ivar base:
91
92
        self._revision_id_to_revno_cache = None
92
93
        self._partial_revision_id_to_revno_cache = {}
93
94
        self._partial_revision_history_cache = []
 
95
        self._tags_bytes = None
94
96
        self._last_revision_info_cache = None
95
97
        self._merge_sorted_revisions_cache = None
96
98
        self._open_hook()
103
105
 
104
106
    def _activate_fallback_location(self, url):
105
107
        """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
106
115
        repo = self._get_fallback_repository(url)
107
116
        if repo.has_same_location(self.repository):
108
117
            raise errors.UnstackableLocationError(self.user_url, url)
226
235
            possible_transports=[self.bzrdir.root_transport])
227
236
        return a_branch.repository
228
237
 
 
238
    @needs_read_lock
229
239
    def _get_tags_bytes(self):
230
240
        """Get the bytes of a serialised tags dict.
231
241
 
238
248
        :return: The bytes of the tags file.
239
249
        :seealso: Branch._set_tags_bytes.
240
250
        """
241
 
        return self._transport.get_bytes('tags')
 
251
        if self._tags_bytes is None:
 
252
            self._tags_bytes = self._transport.get_bytes('tags')
 
253
        return self._tags_bytes
242
254
 
243
255
    def _get_nick(self, local=False, possible_transports=None):
244
256
        config = self.get_config()
804
816
            old_repository = self.repository
805
817
            if len(old_repository._fallback_repositories) != 1:
806
818
                raise AssertionError("can't cope with fallback repositories "
807
 
                    "of %r" % (self.repository,))
 
819
                    "of %r (fallbacks: %r)" % (old_repository,
 
820
                        old_repository._fallback_repositories))
808
821
            # Open the new repository object.
809
822
            # Repositories don't offer an interface to remove fallback
810
823
            # repositories today; take the conceptually simpler option and just
875
888
 
876
889
        :seealso: Branch._get_tags_bytes.
877
890
        """
878
 
        return _run_with_write_locked_target(self, self._transport.put_bytes,
879
 
            'tags', bytes)
 
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)
880
897
 
881
898
    def _cache_revision_history(self, rev_history):
882
899
        """Set the cached revision history to rev_history.
912
929
        self._merge_sorted_revisions_cache = None
913
930
        self._partial_revision_history_cache = []
914
931
        self._partial_revision_id_to_revno_cache = {}
 
932
        self._tags_bytes = None
915
933
 
916
934
    def _gen_revision_history(self):
917
935
        """Return sequence of revision hashes on to this branch.
1256
1274
        return result
1257
1275
 
1258
1276
    @needs_read_lock
1259
 
    def sprout(self, to_bzrdir, revision_id=None, repository_policy=None):
 
1277
    def sprout(self, to_bzrdir, revision_id=None, repository_policy=None,
 
1278
            repository=None):
1260
1279
        """Create a new line of development from the branch, into to_bzrdir.
1261
1280
 
1262
1281
        to_bzrdir controls the branch format.
1267
1286
        if (repository_policy is not None and
1268
1287
            repository_policy.requires_stacking()):
1269
1288
            to_bzrdir._format.require_stacking(_skip_repo=True)
1270
 
        result = to_bzrdir.create_branch()
 
1289
        result = to_bzrdir.create_branch(repository=repository)
1271
1290
        result.lock_write()
1272
1291
        try:
1273
1292
            if repository_policy is not None:
1371
1390
        return format
1372
1391
 
1373
1392
    def create_clone_on_transport(self, to_transport, revision_id=None,
1374
 
        stacked_on=None, create_prefix=False, use_existing_dir=False):
 
1393
        stacked_on=None, create_prefix=False, use_existing_dir=False,
 
1394
        no_tree=None):
1375
1395
        """Create a clone of this branch and its bzrdir.
1376
1396
 
1377
1397
        :param to_transport: The transport to clone onto.
1390
1410
            revision_id = self.last_revision()
1391
1411
        dir_to = self.bzrdir.clone_on_transport(to_transport,
1392
1412
            revision_id=revision_id, stacked_on=stacked_on,
1393
 
            create_prefix=create_prefix, use_existing_dir=use_existing_dir)
 
1413
            create_prefix=create_prefix, use_existing_dir=use_existing_dir,
 
1414
            no_tree=no_tree)
1394
1415
        return dir_to.open_branch()
1395
1416
 
1396
1417
    def create_checkout(self, to_location, revision_id=None,
1521
1542
     * an open routine.
1522
1543
 
1523
1544
    Formats are placed in an dict by their format string for reference
1524
 
    during branch opening. Its not required that these be instances, they
 
1545
    during branch opening. It's not required that these be instances, they
1525
1546
    can be classes themselves with class methods - it simply depends on
1526
1547
    whether state is needed for a given format or not.
1527
1548
 
1622
1643
            hook(params)
1623
1644
 
1624
1645
    def _initialize_helper(self, a_bzrdir, utf8_files, name=None,
1625
 
                           lock_type='metadir', set_format=True):
 
1646
                           repository=None, lock_type='metadir',
 
1647
                           set_format=True):
1626
1648
        """Initialize a branch in a bzrdir, with specified files
1627
1649
 
1628
1650
        :param a_bzrdir: The bzrdir to initialize the branch in
1662
1684
        finally:
1663
1685
            if lock_taken:
1664
1686
                control_files.unlock()
1665
 
        branch = self.open(a_bzrdir, name, _found=True)
 
1687
        branch = self.open(a_bzrdir, name, _found=True,
 
1688
                found_repository=repository)
1666
1689
        self._run_post_branch_init_hooks(a_bzrdir, name, branch)
1667
1690
        return branch
1668
1691
 
1669
 
    def initialize(self, a_bzrdir, name=None):
 
1692
    def initialize(self, a_bzrdir, name=None, repository=None):
1670
1693
        """Create a branch of this format in a_bzrdir.
1671
1694
        
1672
1695
        :param name: Name of the colocated branch to create.
1706
1729
        """
1707
1730
        raise NotImplementedError(self.network_name)
1708
1731
 
1709
 
    def open(self, a_bzrdir, name=None, _found=False, ignore_fallbacks=False):
 
1732
    def open(self, a_bzrdir, name=None, _found=False, ignore_fallbacks=False,
 
1733
            found_repository=None):
1710
1734
        """Return the branch object for a_bzrdir
1711
1735
 
1712
1736
        :param a_bzrdir: A BzrDir that contains a branch.
1818
1842
            "with a bzrlib.branch.PullResult object and only runs in the "
1819
1843
            "bzr client.", (0, 15), None))
1820
1844
        self.create_hook(HookPoint('pre_commit',
1821
 
            "Called after a commit is calculated but before it is is "
 
1845
            "Called after a commit is calculated but before it is "
1822
1846
            "completed. pre_commit is called with (local, master, old_revno, "
1823
1847
            "old_revid, future_revno, future_revid, tree_delta, future_tree"
1824
1848
            "). old_revid is NULL_REVISION for the first commit to a branch, "
2006
2030
        """See BranchFormat.get_format_description()."""
2007
2031
        return "Branch format 4"
2008
2032
 
2009
 
    def initialize(self, a_bzrdir, name=None):
 
2033
    def initialize(self, a_bzrdir, name=None, repository=None):
2010
2034
        """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,))
2011
2038
        utf8_files = [('revision-history', ''),
2012
2039
                      ('branch-name', ''),
2013
2040
                      ]
2022
2049
        """The network name for this format is the control dirs disk label."""
2023
2050
        return self._matchingbzrdir.get_format_string()
2024
2051
 
2025
 
    def open(self, a_bzrdir, name=None, _found=False, ignore_fallbacks=False):
 
2052
    def open(self, a_bzrdir, name=None, _found=False, ignore_fallbacks=False,
 
2053
            found_repository=None):
2026
2054
        """See BranchFormat.open()."""
2027
2055
        if not _found:
2028
2056
            # we are being called directly and must probe.
2029
2057
            raise NotImplementedError
 
2058
        if found_repository is None:
 
2059
            found_repository = a_bzrdir.open_repository()
2030
2060
        return BzrBranch(_format=self,
2031
2061
                         _control_files=a_bzrdir._control_files,
2032
2062
                         a_bzrdir=a_bzrdir,
2033
2063
                         name=name,
2034
 
                         _repository=a_bzrdir.open_repository())
 
2064
                         _repository=found_repository)
2035
2065
 
2036
2066
    def __str__(self):
2037
2067
        return "Bazaar-NG branch format 4"
2051
2081
        """
2052
2082
        return self.get_format_string()
2053
2083
 
2054
 
    def open(self, a_bzrdir, name=None, _found=False, ignore_fallbacks=False):
 
2084
    def open(self, a_bzrdir, name=None, _found=False, ignore_fallbacks=False,
 
2085
            found_repository=None):
2055
2086
        """See BranchFormat.open()."""
2056
2087
        if not _found:
2057
2088
            format = BranchFormat.find_format(a_bzrdir, name=name)
2062
2093
        try:
2063
2094
            control_files = lockable_files.LockableFiles(transport, 'lock',
2064
2095
                                                         lockdir.LockDir)
 
2096
            if found_repository is None:
 
2097
                found_repository = a_bzrdir.find_repository()
2065
2098
            return self._branch_class()(_format=self,
2066
2099
                              _control_files=control_files,
2067
2100
                              name=name,
2068
2101
                              a_bzrdir=a_bzrdir,
2069
 
                              _repository=a_bzrdir.find_repository(),
 
2102
                              _repository=found_repository,
2070
2103
                              ignore_fallbacks=ignore_fallbacks)
2071
2104
        except errors.NoSuchFile:
2072
2105
            raise errors.NotBranchError(path=transport.base, bzrdir=a_bzrdir)
2104
2137
        """See BranchFormat.get_format_description()."""
2105
2138
        return "Branch format 5"
2106
2139
 
2107
 
    def initialize(self, a_bzrdir, name=None):
 
2140
    def initialize(self, a_bzrdir, name=None, repository=None):
2108
2141
        """Create a branch of this format in a_bzrdir."""
2109
2142
        utf8_files = [('revision-history', ''),
2110
2143
                      ('branch-name', ''),
2111
2144
                      ]
2112
 
        return self._initialize_helper(a_bzrdir, utf8_files, name)
 
2145
        return self._initialize_helper(a_bzrdir, utf8_files, name, repository)
2113
2146
 
2114
2147
    def supports_tags(self):
2115
2148
        return False
2137
2170
        """See BranchFormat.get_format_description()."""
2138
2171
        return "Branch format 6"
2139
2172
 
2140
 
    def initialize(self, a_bzrdir, name=None):
 
2173
    def initialize(self, a_bzrdir, name=None, repository=None):
2141
2174
        """Create a branch of this format in a_bzrdir."""
2142
2175
        utf8_files = [('last-revision', '0 null:\n'),
2143
2176
                      ('branch.conf', ''),
2144
2177
                      ('tags', ''),
2145
2178
                      ]
2146
 
        return self._initialize_helper(a_bzrdir, utf8_files, name)
 
2179
        return self._initialize_helper(a_bzrdir, utf8_files, name, repository)
2147
2180
 
2148
2181
    def make_tags(self, branch):
2149
2182
        """See bzrlib.branch.BranchFormat.make_tags()."""
2167
2200
        """See BranchFormat.get_format_description()."""
2168
2201
        return "Branch format 8"
2169
2202
 
2170
 
    def initialize(self, a_bzrdir, name=None):
 
2203
    def initialize(self, a_bzrdir, name=None, repository=None):
2171
2204
        """Create a branch of this format in a_bzrdir."""
2172
2205
        utf8_files = [('last-revision', '0 null:\n'),
2173
2206
                      ('branch.conf', ''),
2174
2207
                      ('tags', ''),
2175
2208
                      ('references', '')
2176
2209
                      ]
2177
 
        return self._initialize_helper(a_bzrdir, utf8_files, name)
 
2210
        return self._initialize_helper(a_bzrdir, utf8_files, name, repository)
2178
2211
 
2179
2212
    def __init__(self):
2180
2213
        super(BzrBranchFormat8, self).__init__()
2203
2236
    This format was introduced in bzr 1.6.
2204
2237
    """
2205
2238
 
2206
 
    def initialize(self, a_bzrdir, name=None):
 
2239
    def initialize(self, a_bzrdir, name=None, repository=None):
2207
2240
        """Create a branch of this format in a_bzrdir."""
2208
2241
        utf8_files = [('last-revision', '0 null:\n'),
2209
2242
                      ('branch.conf', ''),
2210
2243
                      ('tags', ''),
2211
2244
                      ]
2212
 
        return self._initialize_helper(a_bzrdir, utf8_files, name)
 
2245
        return self._initialize_helper(a_bzrdir, utf8_files, name, repository)
2213
2246
 
2214
2247
    def _branch_class(self):
2215
2248
        return BzrBranch7
2257
2290
        transport = a_bzrdir.get_branch_transport(None, name=name)
2258
2291
        location = transport.put_bytes('location', to_branch.base)
2259
2292
 
2260
 
    def initialize(self, a_bzrdir, name=None, target_branch=None):
 
2293
    def initialize(self, a_bzrdir, name=None, target_branch=None,
 
2294
            repository=None):
2261
2295
        """Create a branch of this format in a_bzrdir."""
2262
2296
        if target_branch is None:
2263
2297
            # this format does not implement branch itself, thus the implicit
2291
2325
        return clone
2292
2326
 
2293
2327
    def open(self, a_bzrdir, name=None, _found=False, location=None,
2294
 
             possible_transports=None, ignore_fallbacks=False):
 
2328
             possible_transports=None, ignore_fallbacks=False,
 
2329
             found_repository=None):
2295
2330
        """Return the branch that the branch reference in a_bzrdir points at.
2296
2331
 
2297
2332
        :param a_bzrdir: A BzrDir that contains a branch.
3102
3137
    :ivar tag_conflicts: A list of tag conflicts, see BasicTags.merge_to
3103
3138
    """
3104
3139
 
 
3140
    @deprecated_method(deprecated_in((2, 3, 0)))
3105
3141
    def __int__(self):
3106
 
        # DEPRECATED: pull used to return the change in revno
 
3142
        """Return the relative change in revno.
 
3143
 
 
3144
        :deprecated: Use `new_revno` and `old_revno` instead.
 
3145
        """
3107
3146
        return self.new_revno - self.old_revno
3108
3147
 
3109
3148
    def report(self, to_file):
3134
3173
        target, otherwise it will be None.
3135
3174
    """
3136
3175
 
 
3176
    @deprecated_method(deprecated_in((2, 3, 0)))
3137
3177
    def __int__(self):
3138
 
        # DEPRECATED: push used to return the change in revno
 
3178
        """Return the relative change in revno.
 
3179
 
 
3180
        :deprecated: Use `new_revno` and `old_revno` instead.
 
3181
        """
3139
3182
        return self.new_revno - self.old_revno
3140
3183
 
3141
3184
    def report(self, to_file):
3308
3351
        """
3309
3352
        raise NotImplementedError(self.push)
3310
3353
 
 
3354
    @needs_write_lock
 
3355
    def copy_content_into(self, revision_id=None):
 
3356
        """Copy the content of source into target
 
3357
 
 
3358
        revision_id: if not None, the revision history in the new branch will
 
3359
                     be truncated to end with revision_id.
 
3360
        """
 
3361
        raise NotImplementedError(self.copy_content_into)
 
3362
 
3311
3363
 
3312
3364
class GenericInterBranch(InterBranch):
3313
3365
    """InterBranch implementation that uses public Branch functions."""
3326
3378
        if isinstance(format, remote.RemoteBranchFormat):
3327
3379
            format._ensure_real()
3328
3380
            return format._custom_format
3329
 
        return format                                                                                                  
 
3381
        return format
3330
3382
 
3331
3383
    @needs_write_lock
3332
3384
    def copy_content_into(self, revision_id=None):
3462
3514
                # push into the master from the source branch.
3463
3515
                self.source._basic_push(master_branch, overwrite, stop_revision)
3464
3516
                # and push into the target branch from the source. Note that we
3465
 
                # push from the source branch again, because its considered the
 
3517
                # push from the source branch again, because it's considered the
3466
3518
                # highest bandwidth repository.
3467
3519
                result = self.source._basic_push(self.target, overwrite,
3468
3520
                    stop_revision)