56
56
class UnstackableBranchFormat(errors.BzrError):
58
58
_fmt = ("The branch '%(url)s'(%(format)s) is not a stackable format. "
59
"You will need to upgrade the branch to permit branch stacking.")
59
"You will need to upgrade the branch to permit branch stacking.")
61
61
def __init__(self, format, url):
62
62
errors.BzrError.__init__(self)
154
154
repository._iter_for_revno(
155
155
self.repository, self._partial_revision_history_cache,
156
156
stop_index=stop_index, stop_revision=stop_revision)
157
if self._partial_revision_history_cache[-1] == _mod_revision.NULL_REVISION:
157
if self._partial_revision_history_cache[-1] == \
158
_mod_revision.NULL_REVISION:
158
159
self._partial_revision_history_cache.pop()
160
161
def _get_check_refs(self):
172
173
For instance, if the branch is at URL/.bzr/branch,
173
174
Branch.open(URL) -> a Branch instance.
175
control = controldir.ControlDir.open(base,
176
possible_transports=possible_transports, _unsupported=_unsupported)
177
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,
178
181
possible_transports=possible_transports)
181
184
def open_from_transport(transport, name=None, _unsupported=False,
182
possible_transports=None):
185
possible_transports=None):
183
186
"""Open the branch rooted at transport"""
184
control = controldir.ControlDir.open_from_transport(transport, _unsupported)
185
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,
186
191
possible_transports=possible_transports)
194
199
Basically we keep looking up until we find the control directory or
195
200
run into the root. If there isn't one, raises NotBranchError.
196
If there is one and it is either an unrecognised format or an unsupported
197
format, UnknownFormatError or UnsupportedFormatError are raised.
198
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
200
control, relpath = controldir.ControlDir.open_containing(url,
206
control, relpath = controldir.ControlDir.open_containing(
207
url, possible_transports)
202
208
branch = control.open_branch(possible_transports=possible_transports)
203
209
return (branch, relpath)
270
276
# Silently fall back to local implicit nick if the master is
272
278
mutter("Could not connect to bound branch, "
273
"falling back to local nick.\n " + str(e))
279
"falling back to local nick.\n " + str(e))
274
280
return config.get_nickname()
276
282
def _set_nick(self, nick):
300
306
check_not_reserved_id = _mod_revision.check_not_reserved_id
301
307
# Do not include ghosts or graph origin in revision_history
302
while (current_rev_id in parents_map and
303
len(parents_map[current_rev_id]) > 0):
308
while (current_rev_id in parents_map
309
and len(parents_map[current_rev_id]) > 0):
304
310
check_not_reserved_id(current_rev_id)
305
311
new_history.append(current_rev_id)
306
312
current_rev_id = parents_map[current_rev_id][0]
407
413
This dictionary should not be modified by the caller.
409
415
if 'evil' in debug.debug_flags:
410
mutter_callsite(3, "get_revision_id_to_revno_map scales with ancestry.")
417
3, "get_revision_id_to_revno_map scales with ancestry.")
411
418
with self.lock_read():
412
419
if self._revision_id_to_revno_cache is not None:
413
420
mapping = self._revision_id_to_revno_cache
415
422
mapping = self._gen_revno_map()
416
423
self._cache_revision_id_to_revno(mapping)
417
# TODO: jam 20070417 Since this is being cached, should we be returning
419
# I would rather not, and instead just declare that users should not
420
# 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.
423
430
def _gen_revno_map(self):
431
438
:return: A dictionary mapping revision_id => dotted revno.
433
revision_id_to_revno = dict((rev_id, revno)
434
for rev_id, depth, revno, end_of_merge
435
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()}
436
443
return revision_id_to_revno
438
445
def iter_merge_sorted_revisions(self, start_revision_id=None,
439
stop_revision_id=None, stop_rule='exclude', direction='reverse'):
446
stop_revision_id=None,
447
stop_rule='exclude', direction='reverse'):
440
448
"""Walk the revisions for a branch in merge sorted order.
442
450
Merge sorted order is the output from a merge-aware,
454
462
* 'include' - the stop revision is the last item in the result
455
463
* 'with-merges' - include the stop revision and all of its
456
464
merged revisions in the result
457
* 'with-merges-without-common-ancestry' - filter out revisions
465
* 'with-merges-without-common-ancestry' - filter out revisions
458
466
that are in both ancestries
459
467
:param direction: either 'reverse' or 'forward':
503
511
raise ValueError('invalid direction %r' % direction)
505
513
def _filter_merge_sorted_revisions(self, merge_sorted_revisions,
506
start_revision_id, stop_revision_id, stop_rule):
514
start_revision_id, stop_revision_id,
507
516
"""Iterate over an inclusive range of sorted revisions."""
508
517
rev_iter = iter(merge_sorted_revisions)
509
518
if start_revision_id is not None:
564
573
if rev_id == left_parent:
565
574
# reached the left parent after the stop_revision
567
if (not reached_stop_revision_id or
568
rev_id in revision_id_whitelist):
576
if (not reached_stop_revision_id
577
or rev_id in revision_id_whitelist):
569
578
yield (rev_id, node.merge_depth, node.revno,
571
580
if reached_stop_revision_id or rev_id == stop_revision_id:
572
581
# only do the merged revs of rev_id from now on
573
582
rev = self.repository.get_revision(rev_id)
637
647
"""Tell this branch object to release the physical lock when this
638
648
object is unlocked, even if it didn't originally acquire it.
640
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
642
653
self.control_files.dont_leave_in_place()
681
692
with self.lock_write():
682
693
return InterBranch.get(from_branch, self).fetch(
683
last_revision, limit=limit)
694
last_revision, limit=limit)
685
696
def get_bound_location(self):
686
697
"""Return the URL of the branch we are bound to.
708
719
:param revprops: Optional dictionary of revision properties.
709
720
:param revision_id: Optional revision id.
710
721
:param lossy: Whether to discard data that can not be natively
711
represented, when pushing to a foreign VCS
722
represented, when pushing to a foreign VCS
714
725
if config_stack is None:
715
726
config_stack = self.get_config_stack()
717
return self.repository.get_commit_builder(self, parents, config_stack,
718
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)
721
732
def get_master_branch(self, possible_transports=None):
722
733
"""Return the branch we are bound to.
761
772
if not graph.is_ancestor(last_rev, revision_id):
762
773
# our previous tip is not merged into stop_revision
763
774
raise errors.DivergedBranches(self, other_branch)
764
revno = graph.find_distance_to_null(revision_id, known_revision_ids)
775
revno = graph.find_distance_to_null(
776
revision_id, known_revision_ids)
765
777
self.set_last_revision_info(revno, revision_id)
767
779
def set_parent(self, url):
776
788
url.encode('ascii')
777
789
except UnicodeEncodeError:
778
raise urlutils.InvalidURL(url,
779
"Urls must be 7-bit ascii, "
790
raise urlutils.InvalidURL(
791
url, "Urls must be 7-bit ascii, "
780
792
"use breezy.urlutils.escape")
781
793
url = urlutils.relative_url(self.base, url)
782
794
with self.lock_write():
793
805
if not self._format.supports_stacking():
794
806
raise UnstackableBranchFormat(self._format, self.user_url)
795
807
with self.lock_write():
796
# XXX: Changing from one fallback repository to another does not check
797
# 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.
798
810
# Possibly it should.
799
811
self._check_stackable_repo()
802
old_url = self.get_stacked_on_url()
814
self.get_stacked_on_url()
803
815
except (errors.NotStacked, UnstackableBranchFormat,
804
errors.UnstackableRepositoryFormat):
816
errors.UnstackableRepositoryFormat):
808
self._activate_fallback_location(url,
809
possible_transports=[self.controldir.root_transport])
820
self._activate_fallback_location(
821
url, possible_transports=[self.controldir.root_transport])
810
822
# write this out after the repository is stacked to avoid setting a
811
823
# stacked config that doesn't work.
812
824
self._set_config_location('stacked_on_location', url)
820
832
pb.update(gettext("Unstacking"))
821
833
# The basic approach here is to fetch the tip of the branch,
822
834
# including all available ghosts, from the existing stacked
823
# repository into a new repository object without the fallbacks.
835
# repository into a new repository object without the fallbacks.
825
837
# XXX: See <https://launchpad.net/bugs/397286> - this may not be
826
838
# correct for CHKMap repostiories
827
839
old_repository = self.repository
828
840
if len(old_repository._fallback_repositories) != 1:
829
raise AssertionError("can't cope with fallback repositories "
830
"of %r (fallbacks: %r)" % (old_repository,
831
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))
832
845
# Open the new repository object.
833
846
# Repositories don't offer an interface to remove fallback
834
847
# repositories today; take the conceptually simpler option and just
841
854
self.controldir.root_transport.base)
842
855
new_repository = new_bzrdir.find_repository()
843
856
if new_repository._fallback_repositories:
844
raise AssertionError("didn't expect %r to have "
845
"fallback_repositories"
857
raise AssertionError(
858
"didn't expect %r to have fallback_repositories"
846
859
% (self.repository,))
847
860
# Replace self.repository with the new repository.
848
861
# Do our best to transfer the lock state (i.e. lock-tokens and
875
888
if old_lock_count == 0:
876
889
raise AssertionError(
877
890
'old_repository should have been locked at least once.')
878
for i in range(old_lock_count-1):
891
for i in range(old_lock_count - 1):
879
892
self.repository.lock_write()
880
893
# Fetch from the old repository into the new.
881
894
with old_repository.lock_read():
886
899
tags_to_fetch = set(self.tags.get_reverse_tag_dict())
887
900
except errors.TagsNotSupported:
888
901
tags_to_fetch = set()
889
fetch_spec = vf_search.NotInOtherForRevs(self.repository,
890
old_repository, required_ids=[self.last_revision()],
902
fetch_spec = vf_search.NotInOtherForRevs(
903
self.repository, old_repository,
904
required_ids=[self.last_revision()],
891
905
if_present_ids=tags_to_fetch, find_ghosts=True).execute()
892
906
self.repository.fetch(old_repository, fetch_spec=fetch_spec)
976
990
with self.lock_read():
977
991
if self._last_revision_info_cache is None:
978
self._last_revision_info_cache = self._read_last_revision_info()
992
self._last_revision_info_cache = (
993
self._read_last_revision_info())
979
994
return self._last_revision_info_cache
981
996
def _read_last_revision_info(self):
1036
1051
:returns: PullResult instance
1038
return InterBranch.get(source, self).pull(overwrite=overwrite,
1039
stop_revision=stop_revision,
1053
return InterBranch.get(source, self).pull(
1054
overwrite=overwrite, stop_revision=stop_revision,
1040
1055
possible_transports=possible_transports, *args, **kwargs)
1042
1057
def push(self, target, overwrite=False, stop_revision=None, lossy=False,
1044
1059
"""Mirror this branch into target.
1046
1061
This branch is considered to be 'local', having low latency.
1048
return InterBranch.get(self, target).push(overwrite, stop_revision,
1049
lossy, *args, **kwargs)
1063
return InterBranch.get(self, target).push(
1064
overwrite, stop_revision, lossy, *args, **kwargs)
1051
1066
def basis_tree(self):
1052
1067
"""Return `Tree` object for last revision."""
1068
1083
parent = urlutils.local_path_to_url(parent)
1070
1085
return urlutils.join(self.base[:-1], parent)
1071
except urlutils.InvalidURLJoin as e:
1086
except urlutils.InvalidURLJoin:
1072
1087
raise errors.InaccessibleParent(parent, self.user_url)
1074
1089
def _get_parent_location(self):
1202
1217
def sprout(self, to_controldir, revision_id=None, repository_policy=None,
1203
repository=None, lossy=False):
1218
repository=None, lossy=False):
1204
1219
"""Create a new line of development from the branch, into to_controldir.
1206
1221
to_controldir controls the branch format.
1208
1223
revision_id: if not None, the revision history in the new branch will
1209
1224
be truncated to end with revision_id.
1211
if (repository_policy is not None and
1212
repository_policy.requires_stacking()):
1226
if (repository_policy is not None
1227
and repository_policy.requires_stacking()):
1213
1228
to_controldir._format.require_stacking(_skip_repo=True)
1214
1229
result = to_controldir.create_branch(repository=repository)
1244
1259
graph = self.repository.get_graph()
1246
revno = graph.find_distance_to_null(revision_id,
1247
[(source_revision_id, source_revno)])
1261
revno = graph.find_distance_to_null(
1262
revision_id, [(source_revision_id, source_revno)])
1248
1263
except errors.GhostRevisionsHaveNoRevno:
1249
1264
# Default to 1, if we can't find anything else
1295
1310
if actual_revno != last_revno:
1296
1311
result.errors.append(errors.BzrCheckError(
1297
1312
'revno does not match len(mainline) %s != %s' % (
1298
last_revno, actual_revno)))
1313
last_revno, actual_revno)))
1299
1314
# TODO: We should probably also check that self.revision_history
1300
1315
# matches the repository for older branch formats.
1301
# If looking for the code that cross-checks repository parents against
1302
# 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.
1306
1321
def _get_checkout_format(self, lightweight=False):
1314
1329
def create_clone_on_transport(self, to_transport, revision_id=None,
1315
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):
1317
1332
"""Create a clone of this branch and its bzrdir.
1319
1334
:param to_transport: The transport to clone onto.
1327
1342
# XXX: Fix the bzrdir API to allow getting the branch back from the
1328
1343
# clone call. Or something. 20090224 RBC/spiv.
1329
# XXX: Should this perhaps clone colocated branches as well,
1344
# XXX: Should this perhaps clone colocated branches as well,
1330
1345
# rather than just the default branch? 20100319 JRV
1331
1346
if revision_id is None:
1332
1347
revision_id = self.last_revision()
1333
dir_to = self.controldir.clone_on_transport(to_transport,
1334
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,
1335
1350
create_prefix=create_prefix, use_existing_dir=use_existing_dir,
1336
1351
no_tree=no_tree)
1337
1352
return dir_to.open_branch()
1370
1385
raise errors.AlreadyControlDirError(t.base)
1371
if checkout.control_transport.base == self.controldir.control_transport.base:
1386
if (checkout.control_transport.base
1387
== self.controldir.control_transport.base):
1372
1388
# When checking out to the same control directory,
1373
1389
# always create a lightweight checkout
1374
1390
lightweight = True
1377
1393
from_branch = checkout.set_branch_reference(target_branch=self)
1379
1395
policy = checkout.determine_repository_policy()
1380
repo = policy.acquire_repository()[0]
1396
policy.acquire_repository()
1381
1397
checkout_branch = checkout.create_branch()
1382
1398
checkout_branch.bind(self)
1383
1399
# pull up to the specified revision_id to set the initial
1601
1617
raise NotImplementedError(self.network_name)
1603
1619
def open(self, controldir, name=None, _found=False, ignore_fallbacks=False,
1604
found_repository=None, possible_transports=None):
1620
found_repository=None, possible_transports=None):
1605
1621
"""Return the branch object for controldir.
1607
1623
:param controldir: A ControlDir that contains a branch.
1661
1677
Hooks.__init__(self, "breezy.branch", "Branch.hooks")
1662
self.add_hook('open',
1663
1680
"Called with the Branch object that has been opened after a "
1664
1681
"branch is opened.", (1, 8))
1665
self.add_hook('post_push',
1666
1684
"Called after a push operation completes. post_push is called "
1667
"with a breezy.branch.BranchPushResult object and only runs in the "
1668
"bzr client.", (0, 15))
1669
self.add_hook('post_pull',
1685
"with a breezy.branch.BranchPushResult object and only runs in "
1686
"the bzr client.", (0, 15))
1670
1689
"Called after a pull operation completes. post_pull is called "
1671
1690
"with a breezy.branch.PullResult object and only runs in the "
1672
1691
"bzr client.", (0, 15))
1673
self.add_hook('pre_commit',
1674
1694
"Called after a commit is calculated but before it is "
1675
1695
"completed. pre_commit is called with (local, master, old_revno, "
1676
1696
"old_revid, future_revno, future_revid, tree_delta, future_tree"
1680
1700
" future_tree is an in-memory tree obtained from "
1681
1701
"CommitBuilder.revision_tree() and hooks MUST NOT modify this "
1682
1702
"tree.", (0, 91))
1683
self.add_hook('post_commit',
1684
1705
"Called in the bzr client after a commit has completed. "
1685
1706
"post_commit is called with (local, master, old_revno, old_revid, "
1686
1707
"new_revno, new_revid). old_revid is NULL_REVISION for the first "
1687
1708
"commit to a branch.", (0, 15))
1688
self.add_hook('post_uncommit',
1689
1711
"Called in the bzr client after an uncommit completes. "
1690
1712
"post_uncommit is called with (local, master, old_revno, "
1691
1713
"old_revid, new_revno, new_revid) where local is the local branch "
1692
1714
"or None, master is the target branch, and an empty branch "
1693
1715
"receives new_revno of 0, new_revid of None.", (0, 15))
1694
self.add_hook('pre_change_branch_tip',
1717
'pre_change_branch_tip',
1695
1718
"Called in bzr client and server before a change to the tip of a "
1696
1719
"branch is made. pre_change_branch_tip is called with a "
1697
1720
"breezy.branch.ChangeBranchTipParams. Note that push, pull, "
1698
1721
"commit, uncommit will all trigger this hook.", (1, 6))
1699
self.add_hook('post_change_branch_tip',
1723
'post_change_branch_tip',
1700
1724
"Called in bzr client and server after a change to the tip of a "
1701
1725
"branch is made. post_change_branch_tip is called with a "
1702
1726
"breezy.branch.ChangeBranchTipParams. Note that push, pull, "
1703
1727
"commit, uncommit will all trigger this hook.", (1, 4))
1704
self.add_hook('transform_fallback_location',
1729
'transform_fallback_location',
1705
1730
"Called when a stacked branch is activating its fallback "
1706
1731
"locations. transform_fallback_location is called with (branch, "
1707
1732
"url), and should return a new url. Returning the same url "
1713
1738
"multiple hooks installed for transform_fallback_location, "
1714
1739
"all are called with the url returned from the previous hook."
1715
1740
"The order is however undefined.", (1, 9))
1716
self.add_hook('automatic_tag_name',
1742
'automatic_tag_name',
1717
1743
"Called to determine an automatic tag name for a revision. "
1718
1744
"automatic_tag_name is called with (branch, revision_id) and "
1719
1745
"should return a tag name or None if no tag name could be "
1720
1746
"determined. The first non-None tag name returned will be used.",
1722
self.add_hook('post_branch_init',
1723
1750
"Called after new branch initialization completes. "
1724
1751
"post_branch_init is called with a "
1725
1752
"breezy.branch.BranchInitHookParams. "
1726
1753
"Note that init, branch and checkout (both heavyweight and "
1727
1754
"lightweight) will all trigger this hook.", (2, 2))
1728
self.add_hook('post_switch',
1729
1757
"Called after a checkout switches branch. "
1730
1758
"post_switch is called with a "
1731
1759
"breezy.branch.SwitchHookParams.", (2, 2))
1735
1762
# install the default hooks into the Branch class.
1736
1763
Branch.hooks = BranchHooks()
1842
1869
return self.__dict__ == other.__dict__
1844
1871
def __repr__(self):
1845
return "<%s for %s to (%s, %s)>" % (self.__class__.__name__,
1846
self.control_dir, self.to_branch,
1872
return "<%s for %s to (%s, %s)>" % (
1873
self.__class__.__name__, self.control_dir, self.to_branch,
1847
1874
self.revision_id)
1858
1885
def get_default(self):
1859
1886
"""Return the current default format."""
1860
if (self._default_format_key is not None and
1861
self._default_format is None):
1887
if (self._default_format_key is not None
1888
and self._default_format is None):
1862
1889
self._default_format = self.get(self._default_format_key)
1863
1890
return self._default_format
1993
2020
if self.old_revid != self.new_revid:
1994
2021
note(gettext('Pushed up to revision %d.') % self.new_revno)
1995
2022
if tag_updates:
1996
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))
1997
2025
if self.old_revid == self.new_revid and not tag_updates:
1998
2026
if not tag_conflicts:
1999
2027
note(gettext('No new revisions or tags to push.'))
2021
2049
note(gettext('checked branch {0} format {1}').format(
2022
self.branch.user_url, self.branch._format))
2050
self.branch.user_url, self.branch._format))
2023
2051
for error in self.errors:
2024
2052
note(gettext('found error:%s'), error)
2136
2164
fetch_spec_factory.source_branch_stop_revision_id = stop_revision
2137
2165
fetch_spec_factory.source_repo = self.source.repository
2138
2166
fetch_spec_factory.target_repo = self.target.repository
2139
fetch_spec_factory.target_repo_kind = fetch.TargetRepoKinds.PREEXISTING
2167
fetch_spec_factory.target_repo_kind = (
2168
fetch.TargetRepoKinds.PREEXISTING)
2140
2169
fetch_spec_factory.limit = limit
2141
2170
fetch_spec = fetch_spec_factory.make_fetch_spec()
2142
2171
return self.target.repository.fetch(
2143
self.source.repository,
2144
fetch_spec=fetch_spec)
2172
self.source.repository,
2173
fetch_spec=fetch_spec)
2146
2175
def _update_revisions(self, stop_revision=None, overwrite=False,
2148
2177
with self.source.lock_read(), self.target.lock_write():
2149
2178
other_revno, other_last_revision = self.source.last_revision_info()
2150
stop_revno = None # unknown
2179
stop_revno = None # unknown
2151
2180
if stop_revision is None:
2152
2181
stop_revision = other_last_revision
2153
2182
if _mod_revision.is_null(stop_revision):
2176
2205
if graph is None:
2177
2206
graph = self.target.repository.get_graph()
2178
2207
this_revno, this_last_revision = \
2179
self.target.last_revision_info()
2180
stop_revno = graph.find_distance_to_null(stop_revision,
2181
[(other_last_revision, other_revno),
2182
(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)])
2183
2212
self.target.set_last_revision_info(stop_revno, stop_revision)
2185
2214
def pull(self, overwrite=False, stop_revision=None,
2208
2237
source_is_master = False
2209
2238
if not local and bound_location and not source_is_master:
2210
2239
# not pulling from master, so we need to update master.
2211
master_branch = self.target.get_master_branch(possible_transports)
2240
master_branch = self.target.get_master_branch(
2241
possible_transports)
2212
2242
master_branch.lock_write()
2214
2244
if master_branch:
2215
2245
# pull from source into master.
2216
master_branch.pull(self.source, overwrite, stop_revision,
2218
return self._pull(overwrite,
2219
stop_revision, _hook_master=master_branch,
2247
self.source, overwrite, stop_revision, run_hooks=False)
2249
overwrite, stop_revision, _hook_master=master_branch,
2220
2250
run_hooks=run_hooks,
2221
2251
_override_hook_target=_override_hook_target,
2222
2252
merge_tags_to_master=not source_is_master)
2250
2281
if bound_location and self.target.base != bound_location:
2251
2282
# there is a master branch.
2253
# XXX: Why the second check? Is it even supported for a branch to
2254
# 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
2255
2286
master_branch = self.target.get_master_branch()
2256
2287
with master_branch.lock_write():
2257
2288
# push into the master from the source branch.
2258
2289
master_inter = InterBranch.get(self.source, master_branch)
2259
2290
master_inter._basic_push(overwrite, stop_revision)
2260
# and push into the target branch from the source. Note that
2261
# we push from the source branch again, because it's considered
2262
# 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.
2263
2294
result = self._basic_push(overwrite, stop_revision)
2264
2295
result.master_branch = master_branch
2265
2296
result.local_branch = self.target
2291
2322
# We assume that during 'push' this repository is closer than
2293
2324
graph = self.source.repository.get_graph(self.target.repository)
2294
self._update_revisions(stop_revision,
2295
overwrite=("history" in overwrite),
2325
self._update_revisions(
2326
stop_revision, overwrite=("history" in overwrite), graph=graph)
2297
2327
if self.source._push_should_merge_tags():
2298
2328
result.tag_updates, result.tag_conflicts = (
2299
2329
self.source.tags.merge_to(
2300
self.target.tags, "tags" in overwrite))
2330
self.target.tags, "tags" in overwrite))
2301
2331
result.new_revno, result.new_revid = self.target.last_revision_info()
2304
2334
def _pull(self, overwrite=False, stop_revision=None,
2305
possible_transports=None, _hook_master=None, run_hooks=True,
2306
_override_hook_target=None, local=False,
2307
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):
2308
2338
"""See Branch.pull.
2310
2340
This function is the core worker, used by GenericInterBranch.pull to
2335
2365
# the source one.
2336
2366
self.source.update_references(self.target)
2337
2367
graph = self.target.repository.get_graph(self.source.repository)
2338
# TODO: Branch formats should have a flag that indicates
2368
# TODO: Branch formats should have a flag that indicates
2339
2369
# that revno's are expensive, and pull() should honor that flag.
2340
2370
# -- JRV20090506
2341
2371
result.old_revno, result.old_revid = \
2342
2372
self.target.last_revision_info()
2343
2373
overwrite = _fix_overwrite_type(overwrite)
2344
self._update_revisions(stop_revision,
2345
overwrite=("history" in overwrite),
2347
# TODO: The old revid should be specified when merging tags,
2348
# 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
2349
2378
# pull in the most recent changes. -- JRV20090506
2350
2379
result.tag_updates, result.tag_conflicts = (
2351
self.source.tags.merge_to(self.target.tags,
2352
"tags" in overwrite,
2380
self.source.tags.merge_to(
2381
self.target.tags, "tags" in overwrite,
2353
2382
ignore_master=not merge_tags_to_master))
2354
result.new_revno, result.new_revid = self.target.last_revision_info()
2383
result.new_revno, result.new_revid = (
2384
self.target.last_revision_info())
2355
2385
if _hook_master:
2356
2386
result.master_branch = _hook_master
2357
2387
result.local_branch = result.target_branch