147
156
possible_transports)
148
157
return control.open_branch(), relpath
159
def _push_should_merge_tags(self):
160
"""Should _basic_push merge this branch's tags into the target?
162
The default implementation returns False if this branch has no tags,
163
and True the rest of the time. Subclasses may override this.
165
return self.supports_tags() and self.tags.get_tag_dict()
150
167
def get_config(self):
151
168
return BranchConfig(self)
170
def _get_config(self):
171
"""Get the concrete config for just the config in this branch.
173
This is not intended for client use; see Branch.get_config for the
178
:return: An object supporting get_option and set_option.
180
raise NotImplementedError(self._get_config)
182
def _get_fallback_repository(self, url):
183
"""Get the repository we fallback to at url."""
184
url = urlutils.join(self.base, url)
185
a_bzrdir = bzrdir.BzrDir.open(url,
186
possible_transports=[self.bzrdir.root_transport])
187
return a_bzrdir.open_branch().repository
189
def _get_tags_bytes(self):
190
"""Get the bytes of a serialised tags dict.
192
Note that not all branches support tags, nor do all use the same tags
193
logic: this method is specific to BasicTags. Other tag implementations
194
may use the same method name and behave differently, safely, because
195
of the double-dispatch via
196
format.make_tags->tags_instance->get_tags_dict.
198
:return: The bytes of the tags file.
199
:seealso: Branch._set_tags_bytes.
201
return self._transport.get_bytes('tags')
153
203
def _get_nick(self, local=False, possible_transports=None):
154
204
config = self.get_config()
155
205
# explicit overrides master, but don't look for master if local is True
555
598
:raises UnstackableRepositoryFormat: If the repository does not support
558
raise NotImplementedError(self.set_stacked_on_url)
601
if not self._format.supports_stacking():
602
raise errors.UnstackableBranchFormat(self._format, self.base)
603
self._check_stackable_repo()
606
old_url = self.get_stacked_on_url()
607
except (errors.NotStacked, errors.UnstackableBranchFormat,
608
errors.UnstackableRepositoryFormat):
611
# repositories don't offer an interface to remove fallback
612
# repositories today; take the conceptually simpler option and just
614
self.repository = self.bzrdir.find_repository()
615
# for every revision reference the branch has, ensure it is pulled
617
source_repository = self._get_fallback_repository(old_url)
618
for revision_id in chain([self.last_revision()],
619
self.tags.get_reverse_tag_dict()):
620
self.repository.fetch(source_repository, revision_id,
623
self._activate_fallback_location(url)
624
# write this out after the repository is stacked to avoid setting a
625
# stacked config that doesn't work.
626
self._set_config_location('stacked_on_location', url)
629
def _set_tags_bytes(self, bytes):
630
"""Mirror method for _get_tags_bytes.
632
:seealso: Branch._get_tags_bytes.
634
return _run_with_write_locked_target(self, self._transport.put_bytes,
560
637
def _cache_revision_history(self, rev_history):
561
638
"""Set the cached revision history to rev_history.
695
772
information. This can be None.
700
other_revno, other_last_revision = other.last_revision_info()
701
stop_revno = None # unknown
702
if stop_revision is None:
703
stop_revision = other_last_revision
704
if _mod_revision.is_null(stop_revision):
705
# if there are no commits, we're done.
707
stop_revno = other_revno
709
# what's the current last revision, before we fetch [and change it
711
last_rev = _mod_revision.ensure_null(self.last_revision())
712
# we fetch here so that we don't process data twice in the common
713
# case of having something to pull, and so that the check for
714
# already merged can operate on the just fetched graph, which will
715
# be cached in memory.
716
self.fetch(other, stop_revision)
717
# Check to see if one is an ancestor of the other
720
graph = self.repository.get_graph()
721
if self._check_if_descendant_or_diverged(
722
stop_revision, last_rev, graph, other):
723
# stop_revision is a descendant of last_rev, but we aren't
724
# overwriting, so we're done.
726
if stop_revno is None:
728
graph = self.repository.get_graph()
729
this_revno, this_last_revision = self.last_revision_info()
730
stop_revno = graph.find_distance_to_null(stop_revision,
731
[(other_last_revision, other_revno),
732
(this_last_revision, this_revno)])
733
self.set_last_revision_info(stop_revno, stop_revision)
775
return InterBranch.get(other, self).update_revisions(stop_revision,
778
def import_last_revision_info(self, source_repo, revno, revid):
779
"""Set the last revision info, importing from another repo if necessary.
781
This is used by the bound branch code to upload a revision to
782
the master branch first before updating the tip of the local branch.
784
:param source_repo: Source repository to optionally fetch from
785
:param revno: Revision number of the new tip
786
:param revid: Revision id of the new tip
788
if not self.repository.has_same_location(source_repo):
789
self.repository.fetch(source_repo, revision_id=revid)
790
self.set_last_revision_info(revno, revid)
737
792
def revision_id_to_revno(self, revision_id):
738
793
"""Given a revision id, return its revno"""
1253
1344
"""Is this format supported?
1255
1346
Supported formats can be initialized and opened.
1256
Unsupported formats may not support initialization or committing or
1347
Unsupported formats may not support initialization or committing or
1257
1348
some other features depending on the reason for not being supported.
1261
def open(self, a_bzrdir, _found=False):
1352
def make_tags(self, branch):
1353
"""Create a tags object for branch.
1355
This method is on BranchFormat, because BranchFormats are reflected
1356
over the wire via network_name(), whereas full Branch instances require
1357
multiple VFS method calls to operate at all.
1359
The default implementation returns a disabled-tags instance.
1361
Note that it is normal for branch to be a RemoteBranch when using tags
1364
return DisabledTags(branch)
1366
def network_name(self):
1367
"""A simple byte string uniquely identifying this format for RPC calls.
1369
MetaDir branch formats use their disk format string to identify the
1370
repository over the wire. All in one formats such as bzr < 0.8, and
1371
foreign formats like svn/git and hg should use some marker which is
1372
unique and immutable.
1374
raise NotImplementedError(self.network_name)
1376
def open(self, a_bzrdir, _found=False, ignore_fallbacks=False):
1262
1377
"""Return the branch object for a_bzrdir
1264
_found is a private parameter, do not use it. It is used to indicate
1265
if format probing has already be done.
1379
:param a_bzrdir: A BzrDir that contains a branch.
1380
:param _found: a private parameter, do not use it. It is used to
1381
indicate if format probing has already be done.
1382
:param ignore_fallbacks: when set, no fallback branches will be opened
1383
(if there are any). Default is to open fallbacks.
1267
1385
raise NotImplementedError(self.open)
1270
1388
def register_format(klass, format):
1389
"""Register a metadir format."""
1271
1390
klass._formats[format.get_format_string()] = format
1391
# Metadir formats have a network name of their format string, and get
1392
# registered as class factories.
1393
network_format_registry.register(format.get_format_string(), format.__class__)
1274
1396
def set_default_format(klass, format):
1306
1428
Hooks.__init__(self)
1307
# Introduced in 0.15:
1308
# invoked whenever the revision history has been set
1309
# with set_revision_history. The api signature is
1310
# (branch, revision_history), and the branch will
1313
# Invoked after a branch is opened. The api signature is (branch).
1315
# invoked after a push operation completes.
1316
# the api signature is
1318
# containing the members
1319
# (source, local, master, old_revno, old_revid, new_revno, new_revid)
1320
# where local is the local target branch or None, master is the target
1321
# master branch, and the rest should be self explanatory. The source
1322
# is read locked and the target branches write locked. Source will
1323
# be the local low-latency branch.
1324
self['post_push'] = []
1325
# invoked after a pull operation completes.
1326
# the api signature is
1328
# containing the members
1329
# (source, local, master, old_revno, old_revid, new_revno, new_revid)
1330
# where local is the local branch or None, master is the target
1331
# master branch, and the rest should be self explanatory. The source
1332
# is read locked and the target branches write locked. The local
1333
# branch is the low-latency branch.
1334
self['post_pull'] = []
1335
# invoked before a commit operation takes place.
1336
# the api signature is
1337
# (local, master, old_revno, old_revid, future_revno, future_revid,
1338
# tree_delta, future_tree).
1339
# old_revid is NULL_REVISION for the first commit to a branch
1340
# tree_delta is a TreeDelta object describing changes from the basis
1341
# revision, hooks MUST NOT modify this delta
1342
# future_tree is an in-memory tree obtained from
1343
# CommitBuilder.revision_tree() and hooks MUST NOT modify this tree
1344
self['pre_commit'] = []
1345
# invoked after a commit operation completes.
1346
# the api signature is
1347
# (local, master, old_revno, old_revid, new_revno, new_revid)
1348
# old_revid is NULL_REVISION for the first commit to a branch.
1349
self['post_commit'] = []
1350
# invoked after a uncommit operation completes.
1351
# the api signature is
1352
# (local, master, old_revno, old_revid, new_revno, new_revid) where
1353
# local is the local branch or None, master is the target branch,
1354
# and an empty branch receives new_revno of 0, new_revid of None.
1355
self['post_uncommit'] = []
1357
# Invoked before the tip of a branch changes.
1358
# the api signature is
1359
# (params) where params is a ChangeBranchTipParams with the members
1360
# (branch, old_revno, new_revno, old_revid, new_revid)
1361
self['pre_change_branch_tip'] = []
1363
# Invoked after the tip of a branch changes.
1364
# the api signature is
1365
# (params) where params is a ChangeBranchTipParams with the members
1366
# (branch, old_revno, new_revno, old_revid, new_revid)
1367
self['post_change_branch_tip'] = []
1369
# Invoked when a stacked branch activates its fallback locations and
1370
# allows the transformation of the url of said location.
1371
# the api signature is
1372
# (branch, url) where branch is the branch having its fallback
1373
# location activated and url is the url for the fallback location.
1374
# The hook should return a url.
1375
self['transform_fallback_location'] = []
1429
self.create_hook(HookPoint('set_rh',
1430
"Invoked whenever the revision history has been set via "
1431
"set_revision_history. The api signature is (branch, "
1432
"revision_history), and the branch will be write-locked. "
1433
"The set_rh hook can be expensive for bzr to trigger, a better "
1434
"hook to use is Branch.post_change_branch_tip.", (0, 15), None))
1435
self.create_hook(HookPoint('open',
1436
"Called with the Branch object that has been opened after a "
1437
"branch is opened.", (1, 8), None))
1438
self.create_hook(HookPoint('post_push',
1439
"Called after a push operation completes. post_push is called "
1440
"with a bzrlib.branch.BranchPushResult object and only runs in the "
1441
"bzr client.", (0, 15), None))
1442
self.create_hook(HookPoint('post_pull',
1443
"Called after a pull operation completes. post_pull is called "
1444
"with a bzrlib.branch.PullResult object and only runs in the "
1445
"bzr client.", (0, 15), None))
1446
self.create_hook(HookPoint('pre_commit',
1447
"Called after a commit is calculated but before it is is "
1448
"completed. pre_commit is called with (local, master, old_revno, "
1449
"old_revid, future_revno, future_revid, tree_delta, future_tree"
1450
"). old_revid is NULL_REVISION for the first commit to a branch, "
1451
"tree_delta is a TreeDelta object describing changes from the "
1452
"basis revision. hooks MUST NOT modify this delta. "
1453
" future_tree is an in-memory tree obtained from "
1454
"CommitBuilder.revision_tree() and hooks MUST NOT modify this "
1455
"tree.", (0,91), None))
1456
self.create_hook(HookPoint('post_commit',
1457
"Called in the bzr client after a commit has completed. "
1458
"post_commit is called with (local, master, old_revno, old_revid, "
1459
"new_revno, new_revid). old_revid is NULL_REVISION for the first "
1460
"commit to a branch.", (0, 15), None))
1461
self.create_hook(HookPoint('post_uncommit',
1462
"Called in the bzr client after an uncommit completes. "
1463
"post_uncommit is called with (local, master, old_revno, "
1464
"old_revid, new_revno, new_revid) where local is the local branch "
1465
"or None, master is the target branch, and an empty branch "
1466
"receives new_revno of 0, new_revid of None.", (0, 15), None))
1467
self.create_hook(HookPoint('pre_change_branch_tip',
1468
"Called in bzr client and server before a change to the tip of a "
1469
"branch is made. pre_change_branch_tip is called with a "
1470
"bzrlib.branch.ChangeBranchTipParams. Note that push, pull, "
1471
"commit, uncommit will all trigger this hook.", (1, 6), None))
1472
self.create_hook(HookPoint('post_change_branch_tip',
1473
"Called in bzr client and server after a change to the tip of a "
1474
"branch is made. post_change_branch_tip is called with a "
1475
"bzrlib.branch.ChangeBranchTipParams. Note that push, pull, "
1476
"commit, uncommit will all trigger this hook.", (1, 4), None))
1477
self.create_hook(HookPoint('transform_fallback_location',
1478
"Called when a stacked branch is activating its fallback "
1479
"locations. transform_fallback_location is called with (branch, "
1480
"url), and should return a new url. Returning the same url "
1481
"allows it to be used as-is, returning a different one can be "
1482
"used to cause the branch to stack on a closer copy of that "
1483
"fallback_location. Note that the branch cannot have history "
1484
"accessing methods called on it during this hook because the "
1485
"fallback locations have not been activated. When there are "
1486
"multiple hooks installed for transform_fallback_location, "
1487
"all are called with the url returned from the previous hook."
1488
"The order is however undefined.", (1, 9), None))
1378
1491
# install the default hooks into the Branch class.
2689
2775
target.unlock()
2779
class InterBranch(InterObject):
2780
"""This class represents operations taking place between two branches.
2782
Its instances have methods like pull() and push() and contain
2783
references to the source and target repositories these operations
2784
can be carried out on.
2788
"""The available optimised InterBranch types."""
2791
def _get_branch_formats_to_test():
2792
"""Return a tuple with the Branch formats to use when testing."""
2793
raise NotImplementedError(self._get_branch_formats_to_test)
2795
def update_revisions(self, stop_revision=None, overwrite=False,
2797
"""Pull in new perfect-fit revisions.
2799
:param stop_revision: Updated until the given revision
2800
:param overwrite: Always set the branch pointer, rather than checking
2801
to see if it is a proper descendant.
2802
:param graph: A Graph object that can be used to query history
2803
information. This can be None.
2806
raise NotImplementedError(self.update_revisions)
2809
class GenericInterBranch(InterBranch):
2810
"""InterBranch implementation that uses public Branch functions.
2814
def _get_branch_formats_to_test():
2815
return BranchFormat._default_format, BranchFormat._default_format
2817
def update_revisions(self, stop_revision=None, overwrite=False,
2819
"""See InterBranch.update_revisions()."""
2820
self.source.lock_read()
2822
other_revno, other_last_revision = self.source.last_revision_info()
2823
stop_revno = None # unknown
2824
if stop_revision is None:
2825
stop_revision = other_last_revision
2826
if _mod_revision.is_null(stop_revision):
2827
# if there are no commits, we're done.
2829
stop_revno = other_revno
2831
# what's the current last revision, before we fetch [and change it
2833
last_rev = _mod_revision.ensure_null(self.target.last_revision())
2834
# we fetch here so that we don't process data twice in the common
2835
# case of having something to pull, and so that the check for
2836
# already merged can operate on the just fetched graph, which will
2837
# be cached in memory.
2838
self.target.fetch(self.source, stop_revision)
2839
# Check to see if one is an ancestor of the other
2842
graph = self.target.repository.get_graph()
2843
if self.target._check_if_descendant_or_diverged(
2844
stop_revision, last_rev, graph, self.source):
2845
# stop_revision is a descendant of last_rev, but we aren't
2846
# overwriting, so we're done.
2848
if stop_revno is None:
2850
graph = self.target.repository.get_graph()
2851
this_revno, this_last_revision = \
2852
self.target.last_revision_info()
2853
stop_revno = graph.find_distance_to_null(stop_revision,
2854
[(other_last_revision, other_revno),
2855
(this_last_revision, this_revno)])
2856
self.target.set_last_revision_info(stop_revno, stop_revision)
2858
self.source.unlock()
2861
def is_compatible(self, source, target):
2862
# GenericBranch uses the public API, so always compatible
2866
InterBranch.register_optimiser(GenericInterBranch)