64
56
class UnstackableBranchFormat(errors.BzrError):
66
58
_fmt = ("The branch '%(url)s'(%(format)s) is not a stackable format. "
67
"You will need to upgrade the branch to permit branch stacking.")
59
"You will need to upgrade the branch to permit branch stacking.")
69
61
def __init__(self, format, url):
70
62
errors.BzrError.__init__(self)
162
154
repository._iter_for_revno(
163
155
self.repository, self._partial_revision_history_cache,
164
156
stop_index=stop_index, stop_revision=stop_revision)
165
if self._partial_revision_history_cache[-1] == _mod_revision.NULL_REVISION:
157
if self._partial_revision_history_cache[-1] == \
158
_mod_revision.NULL_REVISION:
166
159
self._partial_revision_history_cache.pop()
168
161
def _get_check_refs(self):
180
173
For instance, if the branch is at URL/.bzr/branch,
181
174
Branch.open(URL) -> a Branch instance.
183
control = controldir.ControlDir.open(base,
184
possible_transports=possible_transports, _unsupported=_unsupported)
185
return control.open_branch(unsupported=_unsupported,
176
control = controldir.ControlDir.open(
177
base, possible_transports=possible_transports,
178
_unsupported=_unsupported)
179
return control.open_branch(
180
unsupported=_unsupported,
186
181
possible_transports=possible_transports)
189
184
def open_from_transport(transport, name=None, _unsupported=False,
190
possible_transports=None):
185
possible_transports=None):
191
186
"""Open the branch rooted at transport"""
192
control = controldir.ControlDir.open_from_transport(transport, _unsupported)
193
return control.open_branch(name=name, unsupported=_unsupported,
187
control = controldir.ControlDir.open_from_transport(
188
transport, _unsupported)
189
return control.open_branch(
190
name=name, unsupported=_unsupported,
194
191
possible_transports=possible_transports)
202
199
Basically we keep looking up until we find the control directory or
203
200
run into the root. If there isn't one, raises NotBranchError.
204
If there is one and it is either an unrecognised format or an unsupported
205
format, UnknownFormatError or UnsupportedFormatError are raised.
206
If there is one, it is returned, along with the unused portion of url.
201
If there is one and it is either an unrecognised format or an
202
unsupported format, UnknownFormatError or UnsupportedFormatError are
203
raised. If there is one, it is returned, along with the unused portion
208
control, relpath = controldir.ControlDir.open_containing(url,
206
control, relpath = controldir.ControlDir.open_containing(
207
url, possible_transports)
210
208
branch = control.open_branch(possible_transports=possible_transports)
211
209
return (branch, relpath)
278
276
# Silently fall back to local implicit nick if the master is
280
278
mutter("Could not connect to bound branch, "
281
"falling back to local nick.\n " + str(e))
279
"falling back to local nick.\n " + str(e))
282
280
return config.get_nickname()
284
282
def _set_nick(self, nick):
308
306
check_not_reserved_id = _mod_revision.check_not_reserved_id
309
307
# Do not include ghosts or graph origin in revision_history
310
while (current_rev_id in parents_map and
311
len(parents_map[current_rev_id]) > 0):
308
while (current_rev_id in parents_map
309
and len(parents_map[current_rev_id]) > 0):
312
310
check_not_reserved_id(current_rev_id)
313
311
new_history.append(current_rev_id)
314
312
current_rev_id = parents_map[current_rev_id][0]
415
413
This dictionary should not be modified by the caller.
417
415
if 'evil' in debug.debug_flags:
418
mutter_callsite(3, "get_revision_id_to_revno_map scales with ancestry.")
417
3, "get_revision_id_to_revno_map scales with ancestry.")
419
418
with self.lock_read():
420
419
if self._revision_id_to_revno_cache is not None:
421
420
mapping = self._revision_id_to_revno_cache
423
422
mapping = self._gen_revno_map()
424
423
self._cache_revision_id_to_revno(mapping)
425
# TODO: jam 20070417 Since this is being cached, should we be returning
427
# I would rather not, and instead just declare that users should not
428
# modify the return value.
424
# TODO: jam 20070417 Since this is being cached, should we be
426
# I would rather not, and instead just declare that users should
427
# not modify the return value.
431
430
def _gen_revno_map(self):
439
438
:return: A dictionary mapping revision_id => dotted revno.
441
revision_id_to_revno = dict((rev_id, revno)
442
for rev_id, depth, revno, end_of_merge
443
in self.iter_merge_sorted_revisions())
440
revision_id_to_revno = {
441
rev_id: revno for rev_id, depth, revno, end_of_merge
442
in self.iter_merge_sorted_revisions()}
444
443
return revision_id_to_revno
446
445
def iter_merge_sorted_revisions(self, start_revision_id=None,
447
stop_revision_id=None, stop_rule='exclude', direction='reverse'):
446
stop_revision_id=None,
447
stop_rule='exclude', direction='reverse'):
448
448
"""Walk the revisions for a branch in merge sorted order.
450
450
Merge sorted order is the output from a merge-aware,
462
462
* 'include' - the stop revision is the last item in the result
463
463
* 'with-merges' - include the stop revision and all of its
464
464
merged revisions in the result
465
* 'with-merges-without-common-ancestry' - filter out revisions
465
* 'with-merges-without-common-ancestry' - filter out revisions
466
466
that are in both ancestries
467
467
:param direction: either 'reverse' or 'forward':
511
511
raise ValueError('invalid direction %r' % direction)
513
513
def _filter_merge_sorted_revisions(self, merge_sorted_revisions,
514
start_revision_id, stop_revision_id, stop_rule):
514
start_revision_id, stop_revision_id,
515
516
"""Iterate over an inclusive range of sorted revisions."""
516
517
rev_iter = iter(merge_sorted_revisions)
517
518
if start_revision_id is not None:
572
573
if rev_id == left_parent:
573
574
# reached the left parent after the stop_revision
575
if (not reached_stop_revision_id or
576
rev_id in revision_id_whitelist):
576
if (not reached_stop_revision_id
577
or rev_id in revision_id_whitelist):
577
578
yield (rev_id, node.merge_depth, node.revno,
579
580
if reached_stop_revision_id or rev_id == stop_revision_id:
580
581
# only do the merged revs of rev_id from now on
581
582
rev = self.repository.get_revision(rev_id)
645
647
"""Tell this branch object to release the physical lock when this
646
648
object is unlocked, even if it didn't originally acquire it.
648
If lock_write doesn't return a token, then this method is not supported.
650
If lock_write doesn't return a token, then this method is not
650
653
self.control_files.dont_leave_in_place()
689
692
with self.lock_write():
690
693
return InterBranch.get(from_branch, self).fetch(
691
last_revision, limit=limit)
694
last_revision, limit=limit)
693
696
def get_bound_location(self):
694
697
"""Return the URL of the branch we are bound to.
716
719
:param revprops: Optional dictionary of revision properties.
717
720
:param revision_id: Optional revision id.
718
721
:param lossy: Whether to discard data that can not be natively
719
represented, when pushing to a foreign VCS
722
represented, when pushing to a foreign VCS
722
725
if config_stack is None:
723
726
config_stack = self.get_config_stack()
725
return self.repository.get_commit_builder(self, parents, config_stack,
726
timestamp, timezone, committer, revprops, revision_id,
728
return self.repository.get_commit_builder(
729
self, parents, config_stack, timestamp, timezone, committer,
730
revprops, revision_id, lossy)
729
732
def get_master_branch(self, possible_transports=None):
730
733
"""Return the branch we are bound to.
769
772
if not graph.is_ancestor(last_rev, revision_id):
770
773
# our previous tip is not merged into stop_revision
771
774
raise errors.DivergedBranches(self, other_branch)
772
revno = graph.find_distance_to_null(revision_id, known_revision_ids)
775
revno = graph.find_distance_to_null(
776
revision_id, known_revision_ids)
773
777
self.set_last_revision_info(revno, revision_id)
775
779
def set_parent(self, url):
784
788
url.encode('ascii')
785
789
except UnicodeEncodeError:
786
raise urlutils.InvalidURL(url,
787
"Urls must be 7-bit ascii, "
790
raise urlutils.InvalidURL(
791
url, "Urls must be 7-bit ascii, "
788
792
"use breezy.urlutils.escape")
789
793
url = urlutils.relative_url(self.base, url)
790
794
with self.lock_write():
801
805
if not self._format.supports_stacking():
802
806
raise UnstackableBranchFormat(self._format, self.user_url)
803
807
with self.lock_write():
804
# XXX: Changing from one fallback repository to another does not check
805
# that all the data you need is present in the new fallback.
808
# XXX: Changing from one fallback repository to another does not
809
# check that all the data you need is present in the new fallback.
806
810
# Possibly it should.
807
811
self._check_stackable_repo()
810
old_url = self.get_stacked_on_url()
814
self.get_stacked_on_url()
811
815
except (errors.NotStacked, UnstackableBranchFormat,
812
errors.UnstackableRepositoryFormat):
816
errors.UnstackableRepositoryFormat):
816
self._activate_fallback_location(url,
817
possible_transports=[self.controldir.root_transport])
820
self._activate_fallback_location(
821
url, possible_transports=[self.controldir.root_transport])
818
822
# write this out after the repository is stacked to avoid setting a
819
823
# stacked config that doesn't work.
820
824
self._set_config_location('stacked_on_location', url)
828
832
pb.update(gettext("Unstacking"))
829
833
# The basic approach here is to fetch the tip of the branch,
830
834
# including all available ghosts, from the existing stacked
831
# repository into a new repository object without the fallbacks.
835
# repository into a new repository object without the fallbacks.
833
837
# XXX: See <https://launchpad.net/bugs/397286> - this may not be
834
838
# correct for CHKMap repostiories
835
839
old_repository = self.repository
836
840
if len(old_repository._fallback_repositories) != 1:
837
raise AssertionError("can't cope with fallback repositories "
838
"of %r (fallbacks: %r)" % (old_repository,
839
old_repository._fallback_repositories))
841
raise AssertionError(
842
"can't cope with fallback repositories "
843
"of %r (fallbacks: %r)" % (
844
old_repository, old_repository._fallback_repositories))
840
845
# Open the new repository object.
841
846
# Repositories don't offer an interface to remove fallback
842
847
# repositories today; take the conceptually simpler option and just
849
854
self.controldir.root_transport.base)
850
855
new_repository = new_bzrdir.find_repository()
851
856
if new_repository._fallback_repositories:
852
raise AssertionError("didn't expect %r to have "
853
"fallback_repositories"
857
raise AssertionError(
858
"didn't expect %r to have fallback_repositories"
854
859
% (self.repository,))
855
860
# Replace self.repository with the new repository.
856
861
# Do our best to transfer the lock state (i.e. lock-tokens and
883
888
if old_lock_count == 0:
884
889
raise AssertionError(
885
890
'old_repository should have been locked at least once.')
886
for i in range(old_lock_count-1):
891
for i in range(old_lock_count - 1):
887
892
self.repository.lock_write()
888
893
# Fetch from the old repository into the new.
889
894
with old_repository.lock_read():
894
899
tags_to_fetch = set(self.tags.get_reverse_tag_dict())
895
900
except errors.TagsNotSupported:
896
901
tags_to_fetch = set()
897
fetch_spec = vf_search.NotInOtherForRevs(self.repository,
898
old_repository, required_ids=[self.last_revision()],
902
fetch_spec = vf_search.NotInOtherForRevs(
903
self.repository, old_repository,
904
required_ids=[self.last_revision()],
899
905
if_present_ids=tags_to_fetch, find_ghosts=True).execute()
900
906
self.repository.fetch(old_repository, fetch_spec=fetch_spec)
984
990
with self.lock_read():
985
991
if self._last_revision_info_cache is None:
986
self._last_revision_info_cache = self._read_last_revision_info()
992
self._last_revision_info_cache = (
993
self._read_last_revision_info())
987
994
return self._last_revision_info_cache
989
996
def _read_last_revision_info(self):
1044
1051
:returns: PullResult instance
1046
return InterBranch.get(source, self).pull(overwrite=overwrite,
1047
stop_revision=stop_revision,
1053
return InterBranch.get(source, self).pull(
1054
overwrite=overwrite, stop_revision=stop_revision,
1048
1055
possible_transports=possible_transports, *args, **kwargs)
1050
1057
def push(self, target, overwrite=False, stop_revision=None, lossy=False,
1052
1059
"""Mirror this branch into target.
1054
1061
This branch is considered to be 'local', having low latency.
1056
return InterBranch.get(self, target).push(overwrite, stop_revision,
1057
lossy, *args, **kwargs)
1063
return InterBranch.get(self, target).push(
1064
overwrite, stop_revision, lossy, *args, **kwargs)
1059
1066
def basis_tree(self):
1060
1067
"""Return `Tree` object for last revision."""
1076
1083
parent = urlutils.local_path_to_url(parent)
1078
1085
return urlutils.join(self.base[:-1], parent)
1079
except urlutils.InvalidURLJoin as e:
1086
except urlutils.InvalidURLJoin:
1080
1087
raise errors.InaccessibleParent(parent, self.user_url)
1082
1089
def _get_parent_location(self):
1210
1217
def sprout(self, to_controldir, revision_id=None, repository_policy=None,
1211
repository=None, lossy=False):
1218
repository=None, lossy=False):
1212
1219
"""Create a new line of development from the branch, into to_controldir.
1214
1221
to_controldir controls the branch format.
1216
1223
revision_id: if not None, the revision history in the new branch will
1217
1224
be truncated to end with revision_id.
1219
if (repository_policy is not None and
1220
repository_policy.requires_stacking()):
1226
if (repository_policy is not None
1227
and repository_policy.requires_stacking()):
1221
1228
to_controldir._format.require_stacking(_skip_repo=True)
1222
1229
result = to_controldir.create_branch(repository=repository)
1252
1259
graph = self.repository.get_graph()
1254
revno = graph.find_distance_to_null(revision_id,
1255
[(source_revision_id, source_revno)])
1261
revno = graph.find_distance_to_null(
1262
revision_id, [(source_revision_id, source_revno)])
1256
1263
except errors.GhostRevisionsHaveNoRevno:
1257
1264
# Default to 1, if we can't find anything else
1303
1310
if actual_revno != last_revno:
1304
1311
result.errors.append(errors.BzrCheckError(
1305
1312
'revno does not match len(mainline) %s != %s' % (
1306
last_revno, actual_revno)))
1313
last_revno, actual_revno)))
1307
1314
# TODO: We should probably also check that self.revision_history
1308
1315
# matches the repository for older branch formats.
1309
# If looking for the code that cross-checks repository parents against
1310
# the Graph.iter_lefthand_ancestry output, that is now a repository
1316
# If looking for the code that cross-checks repository parents
1317
# against the Graph.iter_lefthand_ancestry output, that is now a
1318
# repository specific check.
1314
1321
def _get_checkout_format(self, lightweight=False):
1322
1329
def create_clone_on_transport(self, to_transport, revision_id=None,
1323
stacked_on=None, create_prefix=False, use_existing_dir=False,
1330
stacked_on=None, create_prefix=False,
1331
use_existing_dir=False, no_tree=None):
1325
1332
"""Create a clone of this branch and its bzrdir.
1327
1334
:param to_transport: The transport to clone onto.
1335
1342
# XXX: Fix the bzrdir API to allow getting the branch back from the
1336
1343
# clone call. Or something. 20090224 RBC/spiv.
1337
# XXX: Should this perhaps clone colocated branches as well,
1344
# XXX: Should this perhaps clone colocated branches as well,
1338
1345
# rather than just the default branch? 20100319 JRV
1339
1346
if revision_id is None:
1340
1347
revision_id = self.last_revision()
1341
dir_to = self.controldir.clone_on_transport(to_transport,
1342
revision_id=revision_id, stacked_on=stacked_on,
1348
dir_to = self.controldir.clone_on_transport(
1349
to_transport, revision_id=revision_id, stacked_on=stacked_on,
1343
1350
create_prefix=create_prefix, use_existing_dir=use_existing_dir,
1344
1351
no_tree=no_tree)
1345
1352
return dir_to.open_branch()
1378
1385
raise errors.AlreadyControlDirError(t.base)
1379
if checkout.control_transport.base == self.controldir.control_transport.base:
1386
if (checkout.control_transport.base
1387
== self.controldir.control_transport.base):
1380
1388
# When checking out to the same control directory,
1381
1389
# always create a lightweight checkout
1382
1390
lightweight = True
1385
1393
from_branch = checkout.set_branch_reference(target_branch=self)
1387
1395
policy = checkout.determine_repository_policy()
1388
repo = policy.acquire_repository()[0]
1396
policy.acquire_repository()
1389
1397
checkout_branch = checkout.create_branch()
1390
1398
checkout_branch.bind(self)
1391
1399
# pull up to the specified revision_id to set the initial
1400
1408
with basis_tree.lock_read():
1401
1409
for path, file_id in basis_tree.iter_references():
1402
1410
reference_parent = self.reference_parent(path, file_id)
1403
reference_parent.create_checkout(tree.abspath(path),
1404
basis_tree.get_reference_revision(path, file_id),
1411
reference_parent.create_checkout(
1413
basis_tree.get_reference_revision(path), lightweight)
1408
1416
def reconcile(self, thorough=True):
1609
1617
raise NotImplementedError(self.network_name)
1611
1619
def open(self, controldir, name=None, _found=False, ignore_fallbacks=False,
1612
found_repository=None, possible_transports=None):
1620
found_repository=None, possible_transports=None):
1613
1621
"""Return the branch object for controldir.
1615
1623
:param controldir: A ControlDir that contains a branch.
1669
1677
Hooks.__init__(self, "breezy.branch", "Branch.hooks")
1670
self.add_hook('open',
1671
1680
"Called with the Branch object that has been opened after a "
1672
1681
"branch is opened.", (1, 8))
1673
self.add_hook('post_push',
1674
1684
"Called after a push operation completes. post_push is called "
1675
"with a breezy.branch.BranchPushResult object and only runs in the "
1676
"bzr client.", (0, 15))
1677
self.add_hook('post_pull',
1685
"with a breezy.branch.BranchPushResult object and only runs in "
1686
"the bzr client.", (0, 15))
1678
1689
"Called after a pull operation completes. post_pull is called "
1679
1690
"with a breezy.branch.PullResult object and only runs in the "
1680
1691
"bzr client.", (0, 15))
1681
self.add_hook('pre_commit',
1682
1694
"Called after a commit is calculated but before it is "
1683
1695
"completed. pre_commit is called with (local, master, old_revno, "
1684
1696
"old_revid, future_revno, future_revid, tree_delta, future_tree"
1688
1700
" future_tree is an in-memory tree obtained from "
1689
1701
"CommitBuilder.revision_tree() and hooks MUST NOT modify this "
1690
1702
"tree.", (0, 91))
1691
self.add_hook('post_commit',
1692
1705
"Called in the bzr client after a commit has completed. "
1693
1706
"post_commit is called with (local, master, old_revno, old_revid, "
1694
1707
"new_revno, new_revid). old_revid is NULL_REVISION for the first "
1695
1708
"commit to a branch.", (0, 15))
1696
self.add_hook('post_uncommit',
1697
1711
"Called in the bzr client after an uncommit completes. "
1698
1712
"post_uncommit is called with (local, master, old_revno, "
1699
1713
"old_revid, new_revno, new_revid) where local is the local branch "
1700
1714
"or None, master is the target branch, and an empty branch "
1701
1715
"receives new_revno of 0, new_revid of None.", (0, 15))
1702
self.add_hook('pre_change_branch_tip',
1717
'pre_change_branch_tip',
1703
1718
"Called in bzr client and server before a change to the tip of a "
1704
1719
"branch is made. pre_change_branch_tip is called with a "
1705
1720
"breezy.branch.ChangeBranchTipParams. Note that push, pull, "
1706
1721
"commit, uncommit will all trigger this hook.", (1, 6))
1707
self.add_hook('post_change_branch_tip',
1723
'post_change_branch_tip',
1708
1724
"Called in bzr client and server after a change to the tip of a "
1709
1725
"branch is made. post_change_branch_tip is called with a "
1710
1726
"breezy.branch.ChangeBranchTipParams. Note that push, pull, "
1711
1727
"commit, uncommit will all trigger this hook.", (1, 4))
1712
self.add_hook('transform_fallback_location',
1729
'transform_fallback_location',
1713
1730
"Called when a stacked branch is activating its fallback "
1714
1731
"locations. transform_fallback_location is called with (branch, "
1715
1732
"url), and should return a new url. Returning the same url "
1721
1738
"multiple hooks installed for transform_fallback_location, "
1722
1739
"all are called with the url returned from the previous hook."
1723
1740
"The order is however undefined.", (1, 9))
1724
self.add_hook('automatic_tag_name',
1742
'automatic_tag_name',
1725
1743
"Called to determine an automatic tag name for a revision. "
1726
1744
"automatic_tag_name is called with (branch, revision_id) and "
1727
1745
"should return a tag name or None if no tag name could be "
1728
1746
"determined. The first non-None tag name returned will be used.",
1730
self.add_hook('post_branch_init',
1731
1750
"Called after new branch initialization completes. "
1732
1751
"post_branch_init is called with a "
1733
1752
"breezy.branch.BranchInitHookParams. "
1734
1753
"Note that init, branch and checkout (both heavyweight and "
1735
1754
"lightweight) will all trigger this hook.", (2, 2))
1736
self.add_hook('post_switch',
1737
1757
"Called after a checkout switches branch. "
1738
1758
"post_switch is called with a "
1739
1759
"breezy.branch.SwitchHookParams.", (2, 2))
1743
1762
# install the default hooks into the Branch class.
1744
1763
Branch.hooks = BranchHooks()
1850
1869
return self.__dict__ == other.__dict__
1852
1871
def __repr__(self):
1853
return "<%s for %s to (%s, %s)>" % (self.__class__.__name__,
1854
self.control_dir, self.to_branch,
1872
return "<%s for %s to (%s, %s)>" % (
1873
self.__class__.__name__, self.control_dir, self.to_branch,
1855
1874
self.revision_id)
1866
1885
def get_default(self):
1867
1886
"""Return the current default format."""
1868
if (self._default_format_key is not None and
1869
self._default_format is None):
1887
if (self._default_format_key is not None
1888
and self._default_format is None):
1870
1889
self._default_format = self.get(self._default_format_key)
1871
1890
return self._default_format
2001
2020
if self.old_revid != self.new_revid:
2002
2021
note(gettext('Pushed up to revision %d.') % self.new_revno)
2003
2022
if tag_updates:
2004
note(ngettext('%d tag updated.', '%d tags updated.', len(tag_updates)) % len(tag_updates))
2023
note(ngettext('%d tag updated.', '%d tags updated.',
2024
len(tag_updates)) % len(tag_updates))
2005
2025
if self.old_revid == self.new_revid and not tag_updates:
2006
2026
if not tag_conflicts:
2007
2027
note(gettext('No new revisions or tags to push.'))
2029
2049
note(gettext('checked branch {0} format {1}').format(
2030
self.branch.user_url, self.branch._format))
2050
self.branch.user_url, self.branch._format))
2031
2051
for error in self.errors:
2032
2052
note(gettext('found error:%s'), error)
2144
2164
fetch_spec_factory.source_branch_stop_revision_id = stop_revision
2145
2165
fetch_spec_factory.source_repo = self.source.repository
2146
2166
fetch_spec_factory.target_repo = self.target.repository
2147
fetch_spec_factory.target_repo_kind = fetch.TargetRepoKinds.PREEXISTING
2167
fetch_spec_factory.target_repo_kind = (
2168
fetch.TargetRepoKinds.PREEXISTING)
2148
2169
fetch_spec_factory.limit = limit
2149
2170
fetch_spec = fetch_spec_factory.make_fetch_spec()
2150
2171
return self.target.repository.fetch(
2151
self.source.repository,
2152
fetch_spec=fetch_spec)
2172
self.source.repository,
2173
fetch_spec=fetch_spec)
2154
2175
def _update_revisions(self, stop_revision=None, overwrite=False,
2156
2177
with self.source.lock_read(), self.target.lock_write():
2157
2178
other_revno, other_last_revision = self.source.last_revision_info()
2158
stop_revno = None # unknown
2179
stop_revno = None # unknown
2159
2180
if stop_revision is None:
2160
2181
stop_revision = other_last_revision
2161
2182
if _mod_revision.is_null(stop_revision):
2184
2205
if graph is None:
2185
2206
graph = self.target.repository.get_graph()
2186
2207
this_revno, this_last_revision = \
2187
self.target.last_revision_info()
2188
stop_revno = graph.find_distance_to_null(stop_revision,
2189
[(other_last_revision, other_revno),
2190
(this_last_revision, this_revno)])
2208
self.target.last_revision_info()
2209
stop_revno = graph.find_distance_to_null(
2210
stop_revision, [(other_last_revision, other_revno),
2211
(this_last_revision, this_revno)])
2191
2212
self.target.set_last_revision_info(stop_revno, stop_revision)
2193
2214
def pull(self, overwrite=False, stop_revision=None,
2216
2237
source_is_master = False
2217
2238
if not local and bound_location and not source_is_master:
2218
2239
# not pulling from master, so we need to update master.
2219
master_branch = self.target.get_master_branch(possible_transports)
2240
master_branch = self.target.get_master_branch(
2241
possible_transports)
2220
2242
master_branch.lock_write()
2222
2244
if master_branch:
2223
2245
# pull from source into master.
2224
master_branch.pull(self.source, overwrite, stop_revision,
2226
return self._pull(overwrite,
2227
stop_revision, _hook_master=master_branch,
2247
self.source, overwrite, stop_revision, run_hooks=False)
2249
overwrite, stop_revision, _hook_master=master_branch,
2228
2250
run_hooks=run_hooks,
2229
2251
_override_hook_target=_override_hook_target,
2230
2252
merge_tags_to_master=not source_is_master)
2258
2281
if bound_location and self.target.base != bound_location:
2259
2282
# there is a master branch.
2261
# XXX: Why the second check? Is it even supported for a branch to
2262
# be bound to itself? -- mbp 20070507
2284
# XXX: Why the second check? Is it even supported for a branch
2285
# to be bound to itself? -- mbp 20070507
2263
2286
master_branch = self.target.get_master_branch()
2264
2287
with master_branch.lock_write():
2265
2288
# push into the master from the source branch.
2266
2289
master_inter = InterBranch.get(self.source, master_branch)
2267
2290
master_inter._basic_push(overwrite, stop_revision)
2268
# and push into the target branch from the source. Note that
2269
# we push from the source branch again, because it's considered
2270
# the highest bandwidth repository.
2291
# and push into the target branch from the source. Note
2292
# that we push from the source branch again, because it's
2293
# considered the highest bandwidth repository.
2271
2294
result = self._basic_push(overwrite, stop_revision)
2272
2295
result.master_branch = master_branch
2273
2296
result.local_branch = self.target
2299
2322
# We assume that during 'push' this repository is closer than
2301
2324
graph = self.source.repository.get_graph(self.target.repository)
2302
self._update_revisions(stop_revision,
2303
overwrite=("history" in overwrite),
2325
self._update_revisions(
2326
stop_revision, overwrite=("history" in overwrite), graph=graph)
2305
2327
if self.source._push_should_merge_tags():
2306
2328
result.tag_updates, result.tag_conflicts = (
2307
2329
self.source.tags.merge_to(
2308
self.target.tags, "tags" in overwrite))
2330
self.target.tags, "tags" in overwrite))
2309
2331
result.new_revno, result.new_revid = self.target.last_revision_info()
2312
2334
def _pull(self, overwrite=False, stop_revision=None,
2313
possible_transports=None, _hook_master=None, run_hooks=True,
2314
_override_hook_target=None, local=False,
2315
merge_tags_to_master=True):
2335
possible_transports=None, _hook_master=None, run_hooks=True,
2336
_override_hook_target=None, local=False,
2337
merge_tags_to_master=True):
2316
2338
"""See Branch.pull.
2318
2340
This function is the core worker, used by GenericInterBranch.pull to
2343
2365
# the source one.
2344
2366
self.source.update_references(self.target)
2345
2367
graph = self.target.repository.get_graph(self.source.repository)
2346
# TODO: Branch formats should have a flag that indicates
2368
# TODO: Branch formats should have a flag that indicates
2347
2369
# that revno's are expensive, and pull() should honor that flag.
2348
2370
# -- JRV20090506
2349
2371
result.old_revno, result.old_revid = \
2350
2372
self.target.last_revision_info()
2351
2373
overwrite = _fix_overwrite_type(overwrite)
2352
self._update_revisions(stop_revision,
2353
overwrite=("history" in overwrite),
2355
# TODO: The old revid should be specified when merging tags,
2356
# so a tags implementation that versions tags can only
2374
self._update_revisions(
2375
stop_revision, overwrite=("history" in overwrite), graph=graph)
2376
# TODO: The old revid should be specified when merging tags,
2377
# so a tags implementation that versions tags can only
2357
2378
# pull in the most recent changes. -- JRV20090506
2358
2379
result.tag_updates, result.tag_conflicts = (
2359
self.source.tags.merge_to(self.target.tags,
2360
"tags" in overwrite,
2380
self.source.tags.merge_to(
2381
self.target.tags, "tags" in overwrite,
2361
2382
ignore_master=not merge_tags_to_master))
2362
result.new_revno, result.new_revid = self.target.last_revision_info()
2383
result.new_revno, result.new_revid = (
2384
self.target.last_revision_info())
2363
2385
if _hook_master:
2364
2386
result.master_branch = _hook_master
2365
2387
result.local_branch = result.target_branch