1121
1126
# (params) where params is a ChangeBranchTipParams with the members
1122
1127
# (branch, old_revno, new_revno, old_revid, new_revid)
1123
1128
self['post_change_branch_tip'] = []
1130
# Invoked when a stacked branch activates its fallback locations and
1131
# allows the transformation of the url of said location.
1132
# the api signature is
1133
# (branch, url) where branch is the branch having its fallback
1134
# location activated and url is the url for the fallback location.
1135
# The hook should return a url.
1136
self['transform_fallback_location'] = []
1126
1139
# install the default hooks into the Branch class.
1341
1354
def __init__(self):
1342
1355
super(BzrBranchFormat7, self).__init__()
1343
1356
self._matchingbzrdir.repository_format = \
1344
RepositoryFormatPackDevelopment1Subtree()
1357
RepositoryFormatKnitPack5RichRoot()
1346
1359
def supports_stacking(self):
1739
1752
# TODO: Public option to disable running hooks - should be trivial but
1743
result = self._push_with_bound_branches(target, overwrite,
1745
_override_hook_source_branch=_override_hook_source_branch)
1754
return _run_with_write_locked_target(
1755
target, self._push_with_bound_branches, target, overwrite,
1757
_override_hook_source_branch=_override_hook_source_branch)
1750
1759
def _push_with_bound_branches(self, target, overwrite,
1802
1811
result.source_branch = self
1803
1812
result.target_branch = target
1804
1813
result.old_revno, result.old_revid = target.last_revision_info()
1806
# We assume that during 'push' this repository is closer than
1808
graph = self.repository.get_graph(target.repository)
1809
target.update_revisions(self, stop_revision, overwrite=overwrite,
1811
result.tag_conflicts = self.tags.merge_to(target.tags, overwrite)
1814
if result.old_revid != self.last_revision():
1815
# We assume that during 'push' this repository is closer than
1817
graph = self.repository.get_graph(target.repository)
1818
target.update_revisions(self, stop_revision, overwrite=overwrite,
1820
if self._push_should_merge_tags():
1821
result.tag_conflicts = self.tags.merge_to(target.tags, overwrite)
1812
1822
result.new_revno, result.new_revid = target.last_revision_info()
1825
def _push_should_merge_tags(self):
1826
"""Should _basic_push merge this branch's tags into the target?
1828
The default implementation returns False if this branch has no tags,
1829
and True the rest of the time. Subclasses may override this.
1831
return self.tags.supports_tags() and self.tags.get_tag_dict()
1815
1833
def get_parent(self):
1816
1834
"""See Branch.get_parent."""
1817
1835
parent = self._get_parent_location()
2011
2029
errors.UnstackableBranchFormat):
2032
for hook in Branch.hooks['transform_fallback_location']:
2033
url = hook(self, url)
2035
hook_name = Branch.hooks.get_hook_name(hook)
2036
raise AssertionError(
2037
"'transform_fallback_location' hook %s returned "
2038
"None, not a URL." % hook_name)
2014
2039
self._activate_fallback_location(url)
2016
2041
def _check_stackable_repo(self):
2431
2456
branch._set_config_location('stacked_on_location', '')
2432
2457
# update target format
2433
2458
branch._transport.put_bytes('format', format.get_format_string())
2462
def _run_with_write_locked_target(target, callable, *args, **kwargs):
2463
"""Run ``callable(*args, **kwargs)``, write-locking target for the
2466
_run_with_write_locked_target will attempt to release the lock it acquires.
2468
If an exception is raised by callable, then that exception *will* be
2469
propagated, even if the unlock attempt raises its own error. Thus
2470
_run_with_write_locked_target should be preferred to simply doing::
2474
return callable(*args, **kwargs)
2479
# This is very similar to bzrlib.decorators.needs_write_lock. Perhaps they
2480
# should share code?
2483
result = callable(*args, **kwargs)
2485
exc_info = sys.exc_info()
2489
raise exc_info[0], exc_info[1], exc_info[2]