155
188
The default implementation returns False if this branch has no tags,
156
189
and True the rest of the time. Subclasses may override this.
158
return self.tags.supports_tags() and self.tags.get_tag_dict()
191
return self.supports_tags() and self.tags.get_tag_dict()
160
193
def get_config(self):
161
194
return BranchConfig(self)
196
def _get_config(self):
197
"""Get the concrete config for just the config in this branch.
199
This is not intended for client use; see Branch.get_config for the
204
:return: An object supporting get_option and set_option.
206
raise NotImplementedError(self._get_config)
208
def _get_fallback_repository(self, url):
209
"""Get the repository we fallback to at url."""
210
url = urlutils.join(self.base, url)
211
a_bzrdir = bzrdir.BzrDir.open(url,
212
possible_transports=[self.bzrdir.root_transport])
213
return a_bzrdir.open_branch().repository
215
def _get_tags_bytes(self):
216
"""Get the bytes of a serialised tags dict.
218
Note that not all branches support tags, nor do all use the same tags
219
logic: this method is specific to BasicTags. Other tag implementations
220
may use the same method name and behave differently, safely, because
221
of the double-dispatch via
222
format.make_tags->tags_instance->get_tags_dict.
224
:return: The bytes of the tags file.
225
:seealso: Branch._set_tags_bytes.
227
return self._transport.get_bytes('tags')
163
229
def _get_nick(self, local=False, possible_transports=None):
164
230
config = self.get_config()
165
231
# explicit overrides master, but don't look for master if local is True
563
661
:raises UnstackableRepositoryFormat: If the repository does not support
566
raise NotImplementedError(self.set_stacked_on_url)
664
if not self._format.supports_stacking():
665
raise errors.UnstackableBranchFormat(self._format, self.base)
666
# XXX: Changing from one fallback repository to another does not check
667
# that all the data you need is present in the new fallback.
668
# Possibly it should.
669
self._check_stackable_repo()
672
old_url = self.get_stacked_on_url()
673
except (errors.NotStacked, errors.UnstackableBranchFormat,
674
errors.UnstackableRepositoryFormat):
678
self._activate_fallback_location(url)
679
# write this out after the repository is stacked to avoid setting a
680
# stacked config that doesn't work.
681
self._set_config_location('stacked_on_location', url)
684
"""Change a branch to be unstacked, copying data as needed.
686
Don't call this directly, use set_stacked_on_url(None).
688
pb = ui.ui_factory.nested_progress_bar()
690
pb.update("Unstacking")
691
# The basic approach here is to fetch the tip of the branch,
692
# including all available ghosts, from the existing stacked
693
# repository into a new repository object without the fallbacks.
695
# XXX: See <https://launchpad.net/bugs/397286> - this may not be
696
# correct for CHKMap repostiories
697
old_repository = self.repository
698
if len(old_repository._fallback_repositories) != 1:
699
raise AssertionError("can't cope with fallback repositories "
700
"of %r" % (self.repository,))
701
# unlock it, including unlocking the fallback
702
old_repository.unlock()
703
old_repository.lock_read()
705
# Repositories don't offer an interface to remove fallback
706
# repositories today; take the conceptually simpler option and just
707
# reopen it. We reopen it starting from the URL so that we
708
# get a separate connection for RemoteRepositories and can
709
# stream from one of them to the other. This does mean doing
710
# separate SSH connection setup, but unstacking is not a
711
# common operation so it's tolerable.
712
new_bzrdir = bzrdir.BzrDir.open(self.bzrdir.root_transport.base)
713
new_repository = new_bzrdir.find_repository()
714
self.repository = new_repository
715
if self.repository._fallback_repositories:
716
raise AssertionError("didn't expect %r to have "
717
"fallback_repositories"
718
% (self.repository,))
719
# this is not paired with an unlock because it's just restoring
720
# the previous state; the lock's released when set_stacked_on_url
722
self.repository.lock_write()
723
# XXX: If you unstack a branch while it has a working tree
724
# with a pending merge, the pending-merged revisions will no
725
# longer be present. You can (probably) revert and remerge.
727
# XXX: This only fetches up to the tip of the repository; it
728
# doesn't bring across any tags. That's fairly consistent
729
# with how branch works, but perhaps not ideal.
730
self.repository.fetch(old_repository,
731
revision_id=self.last_revision(),
734
old_repository.unlock()
738
def _set_tags_bytes(self, bytes):
739
"""Mirror method for _get_tags_bytes.
741
:seealso: Branch._get_tags_bytes.
743
return _run_with_write_locked_target(self, self._transport.put_bytes,
568
746
def _cache_revision_history(self, rev_history):
569
747
"""Set the cached revision history to rev_history.
730
906
except ValueError:
731
907
raise errors.NoSuchRevision(self, revision_id)
733
910
def get_rev_id(self, revno, history=None):
734
911
"""Find the revision id of the specified revno."""
736
913
return _mod_revision.NULL_REVISION
738
history = self.revision_history()
739
if revno <= 0 or revno > len(history):
914
last_revno, last_revid = self.last_revision_info()
915
if revno == last_revno:
917
if revno <= 0 or revno > last_revno:
740
918
raise errors.NoSuchRevision(self, revno)
741
return history[revno - 1]
919
distance_from_last = last_revno - revno
920
if len(self._partial_revision_history_cache) <= distance_from_last:
921
self._extend_partial_history(distance_from_last)
922
return self._partial_revision_history_cache[distance_from_last]
743
925
def pull(self, source, overwrite=False, stop_revision=None,
744
possible_transports=None, _override_hook_target=None):
926
possible_transports=None, *args, **kwargs):
745
927
"""Mirror source into this branch.
747
929
This branch is considered to be 'local', having low latency.
749
931
:returns: PullResult instance
751
raise NotImplementedError(self.pull)
933
return InterBranch.get(source, self).pull(overwrite=overwrite,
934
stop_revision=stop_revision,
935
possible_transports=possible_transports, *args, **kwargs)
753
def push(self, target, overwrite=False, stop_revision=None):
937
def push(self, target, overwrite=False, stop_revision=None, *args,
754
939
"""Mirror this branch into target.
756
941
This branch is considered to be 'local', having low latency.
758
raise NotImplementedError(self.push)
943
return InterBranch.get(self, target).push(overwrite, stop_revision,
946
def lossy_push(self, target, stop_revision=None):
947
"""Push deltas into another branch.
949
:note: This does not, like push, retain the revision ids from
950
the source branch and will, rather than adding bzr-specific
951
metadata, push only those semantics of the revision that can be
952
natively represented by this branch' VCS.
954
:param target: Target branch
955
:param stop_revision: Revision to push, defaults to last revision.
956
:return: BranchPushResult with an extra member revidmap:
957
A dictionary mapping revision ids from the target branch
958
to new revision ids in the target branch, for each
959
revision that was pushed.
961
inter = InterBranch.get(self, target)
962
lossy_push = getattr(inter, "lossy_push", None)
963
if lossy_push is None:
964
raise errors.LossyPushToSameVCS(self, target)
965
return lossy_push(stop_revision)
760
967
def basis_tree(self):
761
968
"""Return `Tree` object for last revision."""
1328
1625
Hooks.__init__(self)
1329
# Introduced in 0.15:
1330
# invoked whenever the revision history has been set
1331
# with set_revision_history. The api signature is
1332
# (branch, revision_history), and the branch will
1335
# Invoked after a branch is opened. The api signature is (branch).
1337
# invoked after a push operation completes.
1338
# the api signature is
1340
# containing the members
1341
# (source, local, master, old_revno, old_revid, new_revno, new_revid)
1342
# where local is the local target branch or None, master is the target
1343
# master branch, and the rest should be self explanatory. The source
1344
# is read locked and the target branches write locked. Source will
1345
# be the local low-latency branch.
1346
self['post_push'] = []
1347
# invoked after a pull operation completes.
1348
# the api signature is
1350
# containing the members
1351
# (source, local, master, old_revno, old_revid, new_revno, new_revid)
1352
# where local is the local branch or None, master is the target
1353
# master branch, and the rest should be self explanatory. The source
1354
# is read locked and the target branches write locked. The local
1355
# branch is the low-latency branch.
1356
self['post_pull'] = []
1357
# invoked before a commit operation takes place.
1358
# the api signature is
1359
# (local, master, old_revno, old_revid, future_revno, future_revid,
1360
# tree_delta, future_tree).
1361
# old_revid is NULL_REVISION for the first commit to a branch
1362
# tree_delta is a TreeDelta object describing changes from the basis
1363
# revision, hooks MUST NOT modify this delta
1364
# future_tree is an in-memory tree obtained from
1365
# CommitBuilder.revision_tree() and hooks MUST NOT modify this tree
1366
self['pre_commit'] = []
1367
# invoked after a commit operation completes.
1368
# the api signature is
1369
# (local, master, old_revno, old_revid, new_revno, new_revid)
1370
# old_revid is NULL_REVISION for the first commit to a branch.
1371
self['post_commit'] = []
1372
# invoked after a uncommit operation completes.
1373
# the api signature is
1374
# (local, master, old_revno, old_revid, new_revno, new_revid) where
1375
# local is the local branch or None, master is the target branch,
1376
# and an empty branch recieves new_revno of 0, new_revid of None.
1377
self['post_uncommit'] = []
1379
# Invoked before the tip of a branch changes.
1380
# the api signature is
1381
# (params) where params is a ChangeBranchTipParams with the members
1382
# (branch, old_revno, new_revno, old_revid, new_revid)
1383
self['pre_change_branch_tip'] = []
1385
# Invoked after the tip of a branch changes.
1386
# the api signature is
1387
# (params) where params is a ChangeBranchTipParams with the members
1388
# (branch, old_revno, new_revno, old_revid, new_revid)
1389
self['post_change_branch_tip'] = []
1391
# Invoked when a stacked branch activates its fallback locations and
1392
# allows the transformation of the url of said location.
1393
# the api signature is
1394
# (branch, url) where branch is the branch having its fallback
1395
# location activated and url is the url for the fallback location.
1396
# The hook should return a url.
1397
self['transform_fallback_location'] = []
1626
self.create_hook(HookPoint('set_rh',
1627
"Invoked whenever the revision history has been set via "
1628
"set_revision_history. The api signature is (branch, "
1629
"revision_history), and the branch will be write-locked. "
1630
"The set_rh hook can be expensive for bzr to trigger, a better "
1631
"hook to use is Branch.post_change_branch_tip.", (0, 15), None))
1632
self.create_hook(HookPoint('open',
1633
"Called with the Branch object that has been opened after a "
1634
"branch is opened.", (1, 8), None))
1635
self.create_hook(HookPoint('post_push',
1636
"Called after a push operation completes. post_push is called "
1637
"with a bzrlib.branch.BranchPushResult object and only runs in the "
1638
"bzr client.", (0, 15), None))
1639
self.create_hook(HookPoint('post_pull',
1640
"Called after a pull operation completes. post_pull is called "
1641
"with a bzrlib.branch.PullResult object and only runs in the "
1642
"bzr client.", (0, 15), None))
1643
self.create_hook(HookPoint('pre_commit',
1644
"Called after a commit is calculated but before it is is "
1645
"completed. pre_commit is called with (local, master, old_revno, "
1646
"old_revid, future_revno, future_revid, tree_delta, future_tree"
1647
"). old_revid is NULL_REVISION for the first commit to a branch, "
1648
"tree_delta is a TreeDelta object describing changes from the "
1649
"basis revision. hooks MUST NOT modify this delta. "
1650
" future_tree is an in-memory tree obtained from "
1651
"CommitBuilder.revision_tree() and hooks MUST NOT modify this "
1652
"tree.", (0,91), None))
1653
self.create_hook(HookPoint('post_commit',
1654
"Called in the bzr client after a commit has completed. "
1655
"post_commit is called with (local, master, old_revno, old_revid, "
1656
"new_revno, new_revid). old_revid is NULL_REVISION for the first "
1657
"commit to a branch.", (0, 15), None))
1658
self.create_hook(HookPoint('post_uncommit',
1659
"Called in the bzr client after an uncommit completes. "
1660
"post_uncommit is called with (local, master, old_revno, "
1661
"old_revid, new_revno, new_revid) where local is the local branch "
1662
"or None, master is the target branch, and an empty branch "
1663
"receives new_revno of 0, new_revid of None.", (0, 15), None))
1664
self.create_hook(HookPoint('pre_change_branch_tip',
1665
"Called in bzr client and server before a change to the tip of a "
1666
"branch is made. pre_change_branch_tip is called with a "
1667
"bzrlib.branch.ChangeBranchTipParams. Note that push, pull, "
1668
"commit, uncommit will all trigger this hook.", (1, 6), None))
1669
self.create_hook(HookPoint('post_change_branch_tip',
1670
"Called in bzr client and server after a change to the tip of a "
1671
"branch is made. post_change_branch_tip is called with a "
1672
"bzrlib.branch.ChangeBranchTipParams. Note that push, pull, "
1673
"commit, uncommit will all trigger this hook.", (1, 4), None))
1674
self.create_hook(HookPoint('transform_fallback_location',
1675
"Called when a stacked branch is activating its fallback "
1676
"locations. transform_fallback_location is called with (branch, "
1677
"url), and should return a new url. Returning the same url "
1678
"allows it to be used as-is, returning a different one can be "
1679
"used to cause the branch to stack on a closer copy of that "
1680
"fallback_location. Note that the branch cannot have history "
1681
"accessing methods called on it during this hook because the "
1682
"fallback locations have not been activated. When there are "
1683
"multiple hooks installed for transform_fallback_location, "
1684
"all are called with the url returned from the previous hook."
1685
"The order is however undefined.", (1, 9), None))
1400
1688
# install the default hooks into the Branch class.
1596
1877
return self._initialize_helper(a_bzrdir, utf8_files)
1599
class BzrBranchFormat7(BranchFormatMetadir):
1879
def make_tags(self, branch):
1880
"""See bzrlib.branch.BranchFormat.make_tags()."""
1881
return BasicTags(branch)
1883
def supports_set_append_revisions_only(self):
1887
class BzrBranchFormat8(BranchFormatMetadir):
1888
"""Metadir format supporting storing locations of subtree branches."""
1890
def _branch_class(self):
1893
def get_format_string(self):
1894
"""See BranchFormat.get_format_string()."""
1895
return "Bazaar Branch Format 8 (needs bzr 1.15)\n"
1897
def get_format_description(self):
1898
"""See BranchFormat.get_format_description()."""
1899
return "Branch format 8"
1901
def initialize(self, a_bzrdir):
1902
"""Create a branch of this format in a_bzrdir."""
1903
utf8_files = [('last-revision', '0 null:\n'),
1904
('branch.conf', ''),
1908
return self._initialize_helper(a_bzrdir, utf8_files)
1911
super(BzrBranchFormat8, self).__init__()
1912
self._matchingbzrdir.repository_format = \
1913
RepositoryFormatKnitPack5RichRoot()
1915
def make_tags(self, branch):
1916
"""See bzrlib.branch.BranchFormat.make_tags()."""
1917
return BasicTags(branch)
1919
def supports_set_append_revisions_only(self):
1922
def supports_stacking(self):
1925
supports_reference_locations = True
1928
class BzrBranchFormat7(BzrBranchFormat8):
1600
1929
"""Branch format with last-revision, tags, and a stacked location pointer.
1602
1931
The stacked location pointer is passed down to the repository and requires
1792
2128
base = property(_get_base, doc="The URL for the root of this branch.")
2130
def _get_config(self):
2131
return TransportConfig(self._transport, 'branch.conf')
1794
2133
def is_locked(self):
1795
2134
return self.control_files.is_locked()
1797
2136
def lock_write(self, token=None):
1798
repo_token = self.repository.lock_write()
2137
# All-in-one needs to always unlock/lock.
2138
repo_control = getattr(self.repository, 'control_files', None)
2139
if self.control_files == repo_control or not self.is_locked():
2140
self.repository.lock_write()
1800
token = self.control_files.lock_write(token=token)
2145
return self.control_files.lock_write(token=token)
1802
self.repository.unlock()
2148
self.repository.unlock()
1806
2151
def lock_read(self):
1807
self.repository.lock_read()
2152
# All-in-one needs to always unlock/lock.
2153
repo_control = getattr(self.repository, 'control_files', None)
2154
if self.control_files == repo_control or not self.is_locked():
2155
self.repository.lock_read()
1809
2160
self.control_files.lock_read()
1811
self.repository.unlock()
2163
self.repository.unlock()
1814
2166
def unlock(self):
1815
# TODO: test for failed two phase locks. This is known broken.
1817
2168
self.control_files.unlock()
1819
self.repository.unlock()
1820
if not self.control_files.is_locked():
1821
# we just released the lock
1822
self._clear_cached_state()
2170
# All-in-one needs to always unlock/lock.
2171
repo_control = getattr(self.repository, 'control_files', None)
2172
if (self.control_files == repo_control or
2173
not self.control_files.is_locked()):
2174
self.repository.unlock()
2175
if not self.control_files.is_locked():
2176
# we just released the lock
2177
self._clear_cached_state()
1824
2179
def peek_lock_mode(self):
1825
2180
if self.control_files._lock_count == 0:
1944
2299
"""See Branch.basis_tree."""
1945
2300
return self.repository.revision_tree(self.last_revision())
1948
def pull(self, source, overwrite=False, stop_revision=None,
1949
_hook_master=None, run_hooks=True, possible_transports=None,
1950
_override_hook_target=None):
1953
:param _hook_master: Private parameter - set the branch to
1954
be supplied as the master to pull hooks.
1955
:param run_hooks: Private parameter - if false, this branch
1956
is being called because it's the master of the primary branch,
1957
so it should not run its hooks.
1958
:param _override_hook_target: Private parameter - set the branch to be
1959
supplied as the target_branch to pull hooks.
1961
result = PullResult()
1962
result.source_branch = source
1963
if _override_hook_target is None:
1964
result.target_branch = self
1966
result.target_branch = _override_hook_target
1969
# We assume that during 'pull' the local repository is closer than
1971
graph = self.repository.get_graph(source.repository)
1972
result.old_revno, result.old_revid = self.last_revision_info()
1973
self.update_revisions(source, stop_revision, overwrite=overwrite,
1975
result.tag_conflicts = source.tags.merge_to(self.tags, overwrite)
1976
result.new_revno, result.new_revid = self.last_revision_info()
1978
result.master_branch = _hook_master
1979
result.local_branch = result.target_branch
1981
result.master_branch = result.target_branch
1982
result.local_branch = None
1984
for hook in Branch.hooks['post_pull']:
1990
2302
def _get_parent_location(self):
1991
2303
_locs = ['parent', 'pull', 'x-pull']
1992
2304
for l in _locs:
2000
def push(self, target, overwrite=False, stop_revision=None,
2001
_override_hook_source_branch=None):
2004
This is the basic concrete implementation of push()
2006
:param _override_hook_source_branch: If specified, run
2007
the hooks passing this Branch as the source, rather than self.
2008
This is for use of RemoteBranch, where push is delegated to the
2009
underlying vfs-based Branch.
2011
# TODO: Public option to disable running hooks - should be trivial but
2013
return _run_with_write_locked_target(
2014
target, self._push_with_bound_branches, target, overwrite,
2016
_override_hook_source_branch=_override_hook_source_branch)
2018
def _push_with_bound_branches(self, target, overwrite,
2020
_override_hook_source_branch=None):
2021
"""Push from self into target, and into target's master if any.
2023
This is on the base BzrBranch class even though it doesn't support
2024
bound branches because the *target* might be bound.
2027
if _override_hook_source_branch:
2028
result.source_branch = _override_hook_source_branch
2029
for hook in Branch.hooks['post_push']:
2032
bound_location = target.get_bound_location()
2033
if bound_location and target.base != bound_location:
2034
# there is a master branch.
2036
# XXX: Why the second check? Is it even supported for a branch to
2037
# be bound to itself? -- mbp 20070507
2038
master_branch = target.get_master_branch()
2039
master_branch.lock_write()
2041
# push into the master from this branch.
2042
self._basic_push(master_branch, overwrite, stop_revision)
2043
# and push into the target branch from this. Note that we push from
2044
# this branch again, because its considered the highest bandwidth
2046
result = self._basic_push(target, overwrite, stop_revision)
2047
result.master_branch = master_branch
2048
result.local_branch = target
2052
master_branch.unlock()
2055
result = self._basic_push(target, overwrite, stop_revision)
2056
# TODO: Why set master_branch and local_branch if there's no
2057
# binding? Maybe cleaner to just leave them unset? -- mbp
2059
result.master_branch = target
2060
result.local_branch = None
2064
2311
def _basic_push(self, target, overwrite, stop_revision):
2065
2312
"""Basic implementation of push without bound branches or hooks.
2067
Must be called with self read locked and target write locked.
2314
Must be called with source read locked and target write locked.
2069
result = PushResult()
2316
result = BranchPushResult()
2070
2317
result.source_branch = self
2071
2318
result.target_branch = target
2072
2319
result.old_revno, result.old_revid = target.last_revision_info()
2320
self.update_references(target)
2073
2321
if result.old_revid != self.last_revision():
2074
2322
# We assume that during 'push' this repository is closer than
2076
2324
graph = self.repository.get_graph(target.repository)
2077
target.update_revisions(self, stop_revision, overwrite=overwrite,
2325
target.update_revisions(self, stop_revision,
2326
overwrite=overwrite, graph=graph)
2079
2327
if self._push_should_merge_tags():
2080
result.tag_conflicts = self.tags.merge_to(target.tags, overwrite)
2328
result.tag_conflicts = self.tags.merge_to(target.tags,
2081
2330
result.new_revno, result.new_revid = target.last_revision_info()
2084
def get_parent(self):
2085
"""See Branch.get_parent."""
2086
parent = self._get_parent_location()
2089
# This is an old-format absolute path to a local branch
2090
# turn it into a url
2091
if parent.startswith('/'):
2092
parent = urlutils.local_path_to_url(parent.decode('utf8'))
2094
return urlutils.join(self.base[:-1], parent)
2095
except errors.InvalidURLJoin, e:
2096
raise errors.InaccessibleParent(parent, self.base)
2098
2333
def get_stacked_on_url(self):
2099
2334
raise errors.UnstackableBranchFormat(self._format, self.base)
2420
2562
"""Set the parent branch"""
2421
2563
return self._get_config_location('parent_location')
2566
def _set_all_reference_info(self, info_dict):
2567
"""Replace all reference info stored in a branch.
2569
:param info_dict: A dict of {file_id: (tree_path, branch_location)}
2572
writer = rio.RioWriter(s)
2573
for key, (tree_path, branch_location) in info_dict.iteritems():
2574
stanza = rio.Stanza(file_id=key, tree_path=tree_path,
2575
branch_location=branch_location)
2576
writer.write_stanza(stanza)
2577
self._transport.put_bytes('references', s.getvalue())
2578
self._reference_info = info_dict
2581
def _get_all_reference_info(self):
2582
"""Return all the reference info stored in a branch.
2584
:return: A dict of {file_id: (tree_path, branch_location)}
2586
if self._reference_info is not None:
2587
return self._reference_info
2588
rio_file = self._transport.get('references')
2590
stanzas = rio.read_stanzas(rio_file)
2591
info_dict = dict((s['file_id'], (s['tree_path'],
2592
s['branch_location'])) for s in stanzas)
2595
self._reference_info = info_dict
2598
def set_reference_info(self, file_id, tree_path, branch_location):
2599
"""Set the branch location to use for a tree reference.
2601
:param file_id: The file-id of the tree reference.
2602
:param tree_path: The path of the tree reference in the tree.
2603
:param branch_location: The location of the branch to retrieve tree
2606
info_dict = self._get_all_reference_info()
2607
info_dict[file_id] = (tree_path, branch_location)
2608
if None in (tree_path, branch_location):
2609
if tree_path is not None:
2610
raise ValueError('tree_path must be None when branch_location'
2612
if branch_location is not None:
2613
raise ValueError('branch_location must be None when tree_path'
2615
del info_dict[file_id]
2616
self._set_all_reference_info(info_dict)
2618
def get_reference_info(self, file_id):
2619
"""Get the tree_path and branch_location for a tree reference.
2621
:return: a tuple of (tree_path, branch_location)
2623
return self._get_all_reference_info().get(file_id, (None, None))
2625
def reference_parent(self, file_id, path, possible_transports=None):
2626
"""Return the parent branch for a tree-reference file_id.
2628
:param file_id: The file_id of the tree reference
2629
:param path: The path of the file_id in the tree
2630
:return: A branch associated with the file_id
2632
branch_location = self.get_reference_info(file_id)[1]
2633
if branch_location is None:
2634
return Branch.reference_parent(self, file_id, path,
2635
possible_transports)
2636
branch_location = urlutils.join(self.base, branch_location)
2637
return Branch.open(branch_location,
2638
possible_transports=possible_transports)
2423
2640
def set_push_location(self, location):
2424
2641
"""See Branch.set_push_location."""
2425
2642
self._set_config_location('push_location', location)
2467
2684
raise errors.NotStacked(self)
2468
2685
return stacked_url
2470
def set_append_revisions_only(self, enabled):
2475
self.get_config().set_user_option('append_revisions_only', value,
2478
def set_stacked_on_url(self, url):
2479
self._check_stackable_repo()
2482
old_url = self.get_stacked_on_url()
2483
except (errors.NotStacked, errors.UnstackableBranchFormat,
2484
errors.UnstackableRepositoryFormat):
2487
# repositories don't offer an interface to remove fallback
2488
# repositories today; take the conceptually simpler option and just
2490
self.repository = self.bzrdir.find_repository()
2491
# for every revision reference the branch has, ensure it is pulled
2493
source_repository = self._get_fallback_repository(old_url)
2494
for revision_id in chain([self.last_revision()],
2495
self.tags.get_reverse_tag_dict()):
2496
self.repository.fetch(source_repository, revision_id,
2499
self._activate_fallback_location(url)
2500
# write this out after the repository is stacked to avoid setting a
2501
# stacked config that doesn't work.
2502
self._set_config_location('stacked_on_location', url)
2504
2687
def _get_append_revisions_only(self):
2505
2688
value = self.get_config().get_user_option('append_revisions_only')
2506
2689
return value == 'True'
2508
def _make_tags(self):
2509
return BasicTags(self)
2511
2691
@needs_write_lock
2512
2692
def generate_revision_history(self, revision_id, last_rev=None,
2513
2693
other_branch=None):
2810
3038
self.source.unlock()
3040
def pull(self, overwrite=False, stop_revision=None,
3041
possible_transports=None, _hook_master=None, run_hooks=True,
3042
_override_hook_target=None, local=False):
3045
:param _hook_master: Private parameter - set the branch to
3046
be supplied as the master to pull hooks.
3047
:param run_hooks: Private parameter - if false, this branch
3048
is being called because it's the master of the primary branch,
3049
so it should not run its hooks.
3050
:param _override_hook_target: Private parameter - set the branch to be
3051
supplied as the target_branch to pull hooks.
3052
:param local: Only update the local branch, and not the bound branch.
3054
# This type of branch can't be bound.
3056
raise errors.LocalRequiresBoundBranch()
3057
result = PullResult()
3058
result.source_branch = self.source
3059
if _override_hook_target is None:
3060
result.target_branch = self.target
3062
result.target_branch = _override_hook_target
3063
self.source.lock_read()
3065
# We assume that during 'pull' the target repository is closer than
3067
self.source.update_references(self.target)
3068
graph = self.target.repository.get_graph(self.source.repository)
3069
# TODO: Branch formats should have a flag that indicates
3070
# that revno's are expensive, and pull() should honor that flag.
3072
result.old_revno, result.old_revid = \
3073
self.target.last_revision_info()
3074
self.target.update_revisions(self.source, stop_revision,
3075
overwrite=overwrite, graph=graph)
3076
# TODO: The old revid should be specified when merging tags,
3077
# so a tags implementation that versions tags can only
3078
# pull in the most recent changes. -- JRV20090506
3079
result.tag_conflicts = self.source.tags.merge_to(self.target.tags,
3081
result.new_revno, result.new_revid = self.target.last_revision_info()
3083
result.master_branch = _hook_master
3084
result.local_branch = result.target_branch
3086
result.master_branch = result.target_branch
3087
result.local_branch = None
3089
for hook in Branch.hooks['post_pull']:
3092
self.source.unlock()
3095
def push(self, overwrite=False, stop_revision=None,
3096
_override_hook_source_branch=None):
3097
"""See InterBranch.push.
3099
This is the basic concrete implementation of push()
3101
:param _override_hook_source_branch: If specified, run
3102
the hooks passing this Branch as the source, rather than self.
3103
This is for use of RemoteBranch, where push is delegated to the
3104
underlying vfs-based Branch.
3106
# TODO: Public option to disable running hooks - should be trivial but
3108
self.source.lock_read()
3110
return _run_with_write_locked_target(
3111
self.target, self._push_with_bound_branches, overwrite,
3113
_override_hook_source_branch=_override_hook_source_branch)
3115
self.source.unlock()
3117
def _push_with_bound_branches(self, overwrite, stop_revision,
3118
_override_hook_source_branch=None):
3119
"""Push from source into target, and into target's master if any.
3122
if _override_hook_source_branch:
3123
result.source_branch = _override_hook_source_branch
3124
for hook in Branch.hooks['post_push']:
3127
bound_location = self.target.get_bound_location()
3128
if bound_location and self.target.base != bound_location:
3129
# there is a master branch.
3131
# XXX: Why the second check? Is it even supported for a branch to
3132
# be bound to itself? -- mbp 20070507
3133
master_branch = self.target.get_master_branch()
3134
master_branch.lock_write()
3136
# push into the master from the source branch.
3137
self.source._basic_push(master_branch, overwrite, stop_revision)
3138
# and push into the target branch from the source. Note that we
3139
# push from the source branch again, because its considered the
3140
# highest bandwidth repository.
3141
result = self.source._basic_push(self.target, overwrite,
3143
result.master_branch = master_branch
3144
result.local_branch = self.target
3148
master_branch.unlock()
3151
result = self.source._basic_push(self.target, overwrite,
3153
# TODO: Why set master_branch and local_branch if there's no
3154
# binding? Maybe cleaner to just leave them unset? -- mbp
3156
result.master_branch = self.target
3157
result.local_branch = None
2813
3162
def is_compatible(self, source, target):
2814
3163
# GenericBranch uses the public API, so always compatible
3167
class InterToBranch5(GenericInterBranch):
3170
def _get_branch_formats_to_test():
3171
return BranchFormat._default_format, BzrBranchFormat5()
3173
def pull(self, overwrite=False, stop_revision=None,
3174
possible_transports=None, run_hooks=True,
3175
_override_hook_target=None, local=False):
3176
"""Pull from source into self, updating my master if any.
3178
:param run_hooks: Private parameter - if false, this branch
3179
is being called because it's the master of the primary branch,
3180
so it should not run its hooks.
3182
bound_location = self.target.get_bound_location()
3183
if local and not bound_location:
3184
raise errors.LocalRequiresBoundBranch()
3185
master_branch = None
3186
if not local and bound_location and self.source.base != bound_location:
3187
# not pulling from master, so we need to update master.
3188
master_branch = self.target.get_master_branch(possible_transports)
3189
master_branch.lock_write()
3192
# pull from source into master.
3193
master_branch.pull(self.source, overwrite, stop_revision,
3195
return super(InterToBranch5, self).pull(overwrite,
3196
stop_revision, _hook_master=master_branch,
3197
run_hooks=run_hooks,
3198
_override_hook_target=_override_hook_target)
3201
master_branch.unlock()
2818
3204
InterBranch.register_optimiser(GenericInterBranch)
3205
InterBranch.register_optimiser(InterToBranch5)