724
812
old_repository = self.repository
725
813
if len(old_repository._fallback_repositories) != 1:
726
814
raise AssertionError("can't cope with fallback repositories "
727
"of %r" % (self.repository,))
728
# unlock it, including unlocking the fallback
815
"of %r (fallbacks: %r)" % (old_repository,
816
old_repository._fallback_repositories))
817
# Open the new repository object.
818
# Repositories don't offer an interface to remove fallback
819
# repositories today; take the conceptually simpler option and just
820
# reopen it. We reopen it starting from the URL so that we
821
# get a separate connection for RemoteRepositories and can
822
# stream from one of them to the other. This does mean doing
823
# separate SSH connection setup, but unstacking is not a
824
# common operation so it's tolerable.
825
new_bzrdir = bzrdir.BzrDir.open(self.bzrdir.root_transport.base)
826
new_repository = new_bzrdir.find_repository()
827
if new_repository._fallback_repositories:
828
raise AssertionError("didn't expect %r to have "
829
"fallback_repositories"
830
% (self.repository,))
831
# Replace self.repository with the new repository.
832
# Do our best to transfer the lock state (i.e. lock-tokens and
833
# lock count) of self.repository to the new repository.
834
lock_token = old_repository.lock_write().repository_token
835
self.repository = new_repository
836
if isinstance(self, remote.RemoteBranch):
837
# Remote branches can have a second reference to the old
838
# repository that need to be replaced.
839
if self._real_branch is not None:
840
self._real_branch.repository = new_repository
841
self.repository.lock_write(token=lock_token)
842
if lock_token is not None:
843
old_repository.leave_lock_in_place()
729
844
old_repository.unlock()
845
if lock_token is not None:
846
# XXX: self.repository.leave_lock_in_place() before this
847
# function will not be preserved. Fortunately that doesn't
848
# affect the current default format (2a), and would be a
849
# corner-case anyway.
850
# - Andrew Bennetts, 2010/06/30
851
self.repository.dont_leave_lock_in_place()
855
old_repository.unlock()
856
except errors.LockNotHeld:
859
if old_lock_count == 0:
860
raise AssertionError(
861
'old_repository should have been locked at least once.')
862
for i in range(old_lock_count-1):
863
self.repository.lock_write()
864
# Fetch from the old repository into the new.
730
865
old_repository.lock_read()
732
# Repositories don't offer an interface to remove fallback
733
# repositories today; take the conceptually simpler option and just
734
# reopen it. We reopen it starting from the URL so that we
735
# get a separate connection for RemoteRepositories and can
736
# stream from one of them to the other. This does mean doing
737
# separate SSH connection setup, but unstacking is not a
738
# common operation so it's tolerable.
739
new_bzrdir = bzrdir.BzrDir.open(self.bzrdir.root_transport.base)
740
new_repository = new_bzrdir.find_repository()
741
self.repository = new_repository
742
if self.repository._fallback_repositories:
743
raise AssertionError("didn't expect %r to have "
744
"fallback_repositories"
745
% (self.repository,))
746
# this is not paired with an unlock because it's just restoring
747
# the previous state; the lock's released when set_stacked_on_url
749
self.repository.lock_write()
750
867
# XXX: If you unstack a branch while it has a working tree
751
868
# with a pending merge, the pending-merged revisions will no
752
869
# longer be present. You can (probably) revert and remerge.
754
# XXX: This only fetches up to the tip of the repository; it
755
# doesn't bring across any tags. That's fairly consistent
756
# with how branch works, but perhaps not ideal.
757
self.repository.fetch(old_repository,
758
revision_id=self.last_revision(),
871
tags_to_fetch = set(self.tags.get_reverse_tag_dict())
872
except errors.TagsNotSupported:
873
tags_to_fetch = set()
874
fetch_spec = _mod_graph.NotInOtherForRevs(self.repository,
875
old_repository, required_ids=[self.last_revision()],
876
if_present_ids=tags_to_fetch, find_ghosts=True).execute()
877
self.repository.fetch(old_repository, fetch_spec=fetch_spec)
761
879
old_repository.unlock()
871
995
return (0, _mod_revision.NULL_REVISION)
873
@deprecated_method(deprecated_in((1, 6, 0)))
874
def missing_revisions(self, other, stop_revision=None):
875
"""Return a list of new revisions that would perfectly fit.
877
If self and other have not diverged, return a list of the revisions
878
present in other, but missing from self.
880
self_history = self.revision_history()
881
self_len = len(self_history)
882
other_history = other.revision_history()
883
other_len = len(other_history)
884
common_index = min(self_len, other_len) -1
885
if common_index >= 0 and \
886
self_history[common_index] != other_history[common_index]:
887
raise errors.DivergedBranches(self, other)
889
if stop_revision is None:
890
stop_revision = other_len
892
if stop_revision > other_len:
893
raise errors.NoSuchRevision(self, stop_revision)
894
return other_history[self_len:stop_revision]
897
def update_revisions(self, other, stop_revision=None, overwrite=False,
899
"""Pull in new perfect-fit revisions.
901
:param other: Another Branch to pull from
902
:param stop_revision: Updated until the given revision
903
:param overwrite: Always set the branch pointer, rather than checking
904
to see if it is a proper descendant.
905
:param graph: A Graph object that can be used to query history
906
information. This can be None.
909
return InterBranch.get(other, self).update_revisions(stop_revision,
997
@deprecated_method(deprecated_in((2, 4, 0)))
912
998
def import_last_revision_info(self, source_repo, revno, revid):
913
999
"""Set the last revision info, importing from another repo if necessary.
915
This is used by the bound branch code to upload a revision to
916
the master branch first before updating the tip of the local branch.
918
1001
:param source_repo: Source repository to optionally fetch from
919
1002
:param revno: Revision number of the new tip
920
1003
:param revid: Revision id of the new tip
1483
1616
"""Return the short format description for this format."""
1484
1617
raise NotImplementedError(self.get_format_description)
1486
def _initialize_helper(self, a_bzrdir, utf8_files, lock_type='metadir',
1488
"""Initialize a branch in a bzrdir, with specified files
1619
def _run_post_branch_init_hooks(self, a_bzrdir, name, branch):
1620
hooks = Branch.hooks['post_branch_init']
1623
params = BranchInitHookParams(self, a_bzrdir, name, branch)
1490
:param a_bzrdir: The bzrdir to initialize the branch in
1491
:param utf8_files: The files to create as a list of
1492
(filename, content) tuples
1493
:param set_format: If True, set the format with
1494
self.get_format_string. (BzrBranch4 has its format set
1496
:return: a branch in this format
1627
def initialize(self, a_bzrdir, name=None, repository=None):
1628
"""Create a branch of this format in a_bzrdir.
1630
:param name: Name of the colocated branch to create.
1498
mutter('creating branch %r in %s', self, a_bzrdir.transport.base)
1499
branch_transport = a_bzrdir.get_branch_transport(self)
1501
'metadir': ('lock', lockdir.LockDir),
1502
'branch4': ('branch-lock', lockable_files.TransportLock),
1504
lock_name, lock_class = lock_map[lock_type]
1505
control_files = lockable_files.LockableFiles(branch_transport,
1506
lock_name, lock_class)
1507
control_files.create_lock()
1509
control_files.lock_write()
1510
except errors.LockContention:
1511
if lock_type != 'branch4':
1517
utf8_files += [('format', self.get_format_string())]
1519
for (filename, content) in utf8_files:
1520
branch_transport.put_bytes(
1522
mode=a_bzrdir._get_file_mode())
1525
control_files.unlock()
1526
return self.open(a_bzrdir, _found=True)
1528
def initialize(self, a_bzrdir):
1529
"""Create a branch of this format in a_bzrdir."""
1530
1632
raise NotImplementedError(self.initialize)
1532
1634
def is_supported(self):
1618
1758
These are all empty initially, because by default nothing should get
1621
Hooks.__init__(self)
1622
self.create_hook(HookPoint('set_rh',
1761
Hooks.__init__(self, "bzrlib.branch", "Branch.hooks")
1762
self.add_hook('set_rh',
1623
1763
"Invoked whenever the revision history has been set via "
1624
1764
"set_revision_history. The api signature is (branch, "
1625
1765
"revision_history), and the branch will be write-locked. "
1626
1766
"The set_rh hook can be expensive for bzr to trigger, a better "
1627
"hook to use is Branch.post_change_branch_tip.", (0, 15), None))
1628
self.create_hook(HookPoint('open',
1767
"hook to use is Branch.post_change_branch_tip.", (0, 15))
1768
self.add_hook('open',
1629
1769
"Called with the Branch object that has been opened after a "
1630
"branch is opened.", (1, 8), None))
1631
self.create_hook(HookPoint('post_push',
1770
"branch is opened.", (1, 8))
1771
self.add_hook('post_push',
1632
1772
"Called after a push operation completes. post_push is called "
1633
1773
"with a bzrlib.branch.BranchPushResult object and only runs in the "
1634
"bzr client.", (0, 15), None))
1635
self.create_hook(HookPoint('post_pull',
1774
"bzr client.", (0, 15))
1775
self.add_hook('post_pull',
1636
1776
"Called after a pull operation completes. post_pull is called "
1637
1777
"with a bzrlib.branch.PullResult object and only runs in the "
1638
"bzr client.", (0, 15), None))
1639
self.create_hook(HookPoint('pre_commit',
1640
"Called after a commit is calculated but before it is is "
1778
"bzr client.", (0, 15))
1779
self.add_hook('pre_commit',
1780
"Called after a commit is calculated but before it is "
1641
1781
"completed. pre_commit is called with (local, master, old_revno, "
1642
1782
"old_revid, future_revno, future_revid, tree_delta, future_tree"
1643
1783
"). old_revid is NULL_REVISION for the first commit to a branch, "
1645
1785
"basis revision. hooks MUST NOT modify this delta. "
1646
1786
" future_tree is an in-memory tree obtained from "
1647
1787
"CommitBuilder.revision_tree() and hooks MUST NOT modify this "
1648
"tree.", (0,91), None))
1649
self.create_hook(HookPoint('post_commit',
1789
self.add_hook('post_commit',
1650
1790
"Called in the bzr client after a commit has completed. "
1651
1791
"post_commit is called with (local, master, old_revno, old_revid, "
1652
1792
"new_revno, new_revid). old_revid is NULL_REVISION for the first "
1653
"commit to a branch.", (0, 15), None))
1654
self.create_hook(HookPoint('post_uncommit',
1793
"commit to a branch.", (0, 15))
1794
self.add_hook('post_uncommit',
1655
1795
"Called in the bzr client after an uncommit completes. "
1656
1796
"post_uncommit is called with (local, master, old_revno, "
1657
1797
"old_revid, new_revno, new_revid) where local is the local branch "
1658
1798
"or None, master is the target branch, and an empty branch "
1659
"receives new_revno of 0, new_revid of None.", (0, 15), None))
1660
self.create_hook(HookPoint('pre_change_branch_tip',
1799
"receives new_revno of 0, new_revid of None.", (0, 15))
1800
self.add_hook('pre_change_branch_tip',
1661
1801
"Called in bzr client and server before a change to the tip of a "
1662
1802
"branch is made. pre_change_branch_tip is called with a "
1663
1803
"bzrlib.branch.ChangeBranchTipParams. Note that push, pull, "
1664
"commit, uncommit will all trigger this hook.", (1, 6), None))
1665
self.create_hook(HookPoint('post_change_branch_tip',
1804
"commit, uncommit will all trigger this hook.", (1, 6))
1805
self.add_hook('post_change_branch_tip',
1666
1806
"Called in bzr client and server after a change to the tip of a "
1667
1807
"branch is made. post_change_branch_tip is called with a "
1668
1808
"bzrlib.branch.ChangeBranchTipParams. Note that push, pull, "
1669
"commit, uncommit will all trigger this hook.", (1, 4), None))
1670
self.create_hook(HookPoint('transform_fallback_location',
1809
"commit, uncommit will all trigger this hook.", (1, 4))
1810
self.add_hook('transform_fallback_location',
1671
1811
"Called when a stacked branch is activating its fallback "
1672
1812
"locations. transform_fallback_location is called with (branch, "
1673
1813
"url), and should return a new url. Returning the same url "
1723
1880
self.old_revno, self.old_revid, self.new_revno, self.new_revid)
1726
class BzrBranchFormat4(BranchFormat):
1727
"""Bzr branch format 4.
1730
- a revision-history file.
1731
- a branch-lock lock file [ to be shared with the bzrdir ]
1734
def get_format_description(self):
1735
"""See BranchFormat.get_format_description()."""
1736
return "Branch format 4"
1738
def initialize(self, a_bzrdir):
1739
"""Create a branch of this format in a_bzrdir."""
1740
utf8_files = [('revision-history', ''),
1741
('branch-name', ''),
1743
return self._initialize_helper(a_bzrdir, utf8_files,
1744
lock_type='branch4', set_format=False)
1747
super(BzrBranchFormat4, self).__init__()
1748
self._matchingbzrdir = bzrdir.BzrDirFormat6()
1750
def network_name(self):
1751
"""The network name for this format is the control dirs disk label."""
1752
return self._matchingbzrdir.get_format_string()
1754
def open(self, a_bzrdir, _found=False, ignore_fallbacks=False):
1755
"""See BranchFormat.open()."""
1757
# we are being called directly and must probe.
1758
raise NotImplementedError
1759
return BzrBranch(_format=self,
1760
_control_files=a_bzrdir._control_files,
1762
_repository=a_bzrdir.open_repository())
1765
return "Bazaar-NG branch format 4"
1883
class BranchInitHookParams(object):
1884
"""Object holding parameters passed to *_branch_init hooks.
1886
There are 4 fields that hooks may wish to access:
1888
:ivar format: the branch format
1889
:ivar bzrdir: the BzrDir where the branch will be/has been initialized
1890
:ivar name: name of colocated branch, if any (or None)
1891
:ivar branch: the branch created
1893
Note that for lightweight checkouts, the bzrdir and format fields refer to
1894
the checkout, hence they are different from the corresponding fields in
1895
branch, which refer to the original branch.
1898
def __init__(self, format, a_bzrdir, name, branch):
1899
"""Create a group of BranchInitHook parameters.
1901
:param format: the branch format
1902
:param a_bzrdir: the BzrDir where the branch will be/has been
1904
:param name: name of colocated branch, if any (or None)
1905
:param branch: the branch created
1907
Note that for lightweight checkouts, the bzrdir and format fields refer
1908
to the checkout, hence they are different from the corresponding fields
1909
in branch, which refer to the original branch.
1911
self.format = format
1912
self.bzrdir = a_bzrdir
1914
self.branch = branch
1916
def __eq__(self, other):
1917
return self.__dict__ == other.__dict__
1920
return "<%s of %s>" % (self.__class__.__name__, self.branch)
1923
class SwitchHookParams(object):
1924
"""Object holding parameters passed to *_switch hooks.
1926
There are 4 fields that hooks may wish to access:
1928
:ivar control_dir: BzrDir of the checkout to change
1929
:ivar to_branch: branch that the checkout is to reference
1930
:ivar force: skip the check for local commits in a heavy checkout
1931
:ivar revision_id: revision ID to switch to (or None)
1934
def __init__(self, control_dir, to_branch, force, revision_id):
1935
"""Create a group of SwitchHook parameters.
1937
:param control_dir: BzrDir of the checkout to change
1938
:param to_branch: branch that the checkout is to reference
1939
:param force: skip the check for local commits in a heavy checkout
1940
:param revision_id: revision ID to switch to (or None)
1942
self.control_dir = control_dir
1943
self.to_branch = to_branch
1945
self.revision_id = revision_id
1947
def __eq__(self, other):
1948
return self.__dict__ == other.__dict__
1951
return "<%s for %s to (%s, %s)>" % (self.__class__.__name__,
1952
self.control_dir, self.to_branch,
1768
1956
class BranchFormatMetadir(BranchFormat):
1974
2200
"""See BranchFormat.get_format_description()."""
1975
2201
return "Checkout reference format 1"
1977
def get_reference(self, a_bzrdir):
2203
def get_reference(self, a_bzrdir, name=None):
1978
2204
"""See BranchFormat.get_reference()."""
1979
transport = a_bzrdir.get_branch_transport(None)
2205
transport = a_bzrdir.get_branch_transport(None, name=name)
1980
2206
return transport.get_bytes('location')
1982
def set_reference(self, a_bzrdir, to_branch):
2208
def set_reference(self, a_bzrdir, name, to_branch):
1983
2209
"""See BranchFormat.set_reference()."""
1984
transport = a_bzrdir.get_branch_transport(None)
2210
transport = a_bzrdir.get_branch_transport(None, name=name)
1985
2211
location = transport.put_bytes('location', to_branch.base)
1987
def initialize(self, a_bzrdir, target_branch=None):
2213
def initialize(self, a_bzrdir, name=None, target_branch=None,
1988
2215
"""Create a branch of this format in a_bzrdir."""
1989
2216
if target_branch is None:
1990
2217
# this format does not implement branch itself, thus the implicit
1991
2218
# creation contract must see it as uninitializable
1992
2219
raise errors.UninitializableFormat(self)
1993
mutter('creating branch reference in %s', a_bzrdir.transport.base)
1994
branch_transport = a_bzrdir.get_branch_transport(self)
2220
mutter('creating branch reference in %s', a_bzrdir.user_url)
2221
branch_transport = a_bzrdir.get_branch_transport(self, name=name)
1995
2222
branch_transport.put_bytes('location',
1996
target_branch.bzrdir.root_transport.base)
2223
target_branch.bzrdir.user_url)
1997
2224
branch_transport.put_bytes('format', self.get_format_string())
1999
a_bzrdir, _found=True,
2226
a_bzrdir, name, _found=True,
2000
2227
possible_transports=[target_branch.bzrdir.root_transport])
2228
self._run_post_branch_init_hooks(a_bzrdir, name, branch)
2002
2231
def __init__(self):
2003
2232
super(BranchReferenceFormat, self).__init__()
2988
3260
raise NotImplementedError(self.push)
3263
def copy_content_into(self, revision_id=None):
3264
"""Copy the content of source into target
3266
revision_id: if not None, the revision history in the new branch will
3267
be truncated to end with revision_id.
3269
raise NotImplementedError(self.copy_content_into)
3272
def fetch(self, stop_revision=None):
3275
:param stop_revision: Last revision to fetch
3277
raise NotImplementedError(self.fetch)
2991
3280
class GenericInterBranch(InterBranch):
2992
"""InterBranch implementation that uses public Branch functions.
2996
def _get_branch_formats_to_test():
2997
return BranchFormat._default_format, BranchFormat._default_format
2999
def update_revisions(self, stop_revision=None, overwrite=False,
3001
"""See InterBranch.update_revisions()."""
3281
"""InterBranch implementation that uses public Branch functions."""
3284
def is_compatible(klass, source, target):
3285
# GenericBranch uses the public API, so always compatible
3289
def _get_branch_formats_to_test(klass):
3290
return [(format_registry.get_default(), format_registry.get_default())]
3293
def unwrap_format(klass, format):
3294
if isinstance(format, remote.RemoteBranchFormat):
3295
format._ensure_real()
3296
return format._custom_format
3300
def copy_content_into(self, revision_id=None):
3301
"""Copy the content of source into target
3303
revision_id: if not None, the revision history in the new branch will
3304
be truncated to end with revision_id.
3306
self.source.update_references(self.target)
3307
self.source._synchronize_history(self.target, revision_id)
3309
parent = self.source.get_parent()
3310
except errors.InaccessibleParent, e:
3311
mutter('parent was not accessible to copy: %s', e)
3314
self.target.set_parent(parent)
3315
if self.source._push_should_merge_tags():
3316
self.source.tags.merge_to(self.target.tags)
3319
def fetch(self, stop_revision=None):
3320
if self.target.base == self.source.base:
3002
3322
self.source.lock_read()
3004
other_revno, other_last_revision = self.source.last_revision_info()
3005
stop_revno = None # unknown
3006
if stop_revision is None:
3007
stop_revision = other_last_revision
3008
if _mod_revision.is_null(stop_revision):
3009
# if there are no commits, we're done.
3011
stop_revno = other_revno
3013
# what's the current last revision, before we fetch [and change it
3015
last_rev = _mod_revision.ensure_null(self.target.last_revision())
3016
# we fetch here so that we don't process data twice in the common
3017
# case of having something to pull, and so that the check for
3018
# already merged can operate on the just fetched graph, which will
3019
# be cached in memory.
3020
self.target.fetch(self.source, stop_revision)
3021
# Check to see if one is an ancestor of the other
3024
graph = self.target.repository.get_graph()
3025
if self.target._check_if_descendant_or_diverged(
3026
stop_revision, last_rev, graph, self.source):
3027
# stop_revision is a descendant of last_rev, but we aren't
3028
# overwriting, so we're done.
3030
if stop_revno is None:
3032
graph = self.target.repository.get_graph()
3033
this_revno, this_last_revision = \
3034
self.target.last_revision_info()
3035
stop_revno = graph.find_distance_to_null(stop_revision,
3036
[(other_last_revision, other_revno),
3037
(this_last_revision, this_revno)])
3038
self.target.set_last_revision_info(stop_revno, stop_revision)
3324
fetch_spec_factory = fetch.FetchSpecFactory()
3325
fetch_spec_factory.source_branch = self.source
3326
fetch_spec_factory.source_branch_stop_revision_id = stop_revision
3327
fetch_spec_factory.source_repo = self.source.repository
3328
fetch_spec_factory.target_repo = self.target.repository
3329
fetch_spec_factory.target_repo_kind = fetch.TargetRepoKinds.PREEXISTING
3330
fetch_spec = fetch_spec_factory.make_fetch_spec()
3331
return self.target.repository.fetch(self.source.repository,
3332
fetch_spec=fetch_spec)
3040
3334
self.source.unlock()
3337
def _update_revisions(self, stop_revision=None, overwrite=False,
3339
other_revno, other_last_revision = self.source.last_revision_info()
3340
stop_revno = None # unknown
3341
if stop_revision is None:
3342
stop_revision = other_last_revision
3343
if _mod_revision.is_null(stop_revision):
3344
# if there are no commits, we're done.
3346
stop_revno = other_revno
3348
# what's the current last revision, before we fetch [and change it
3350
last_rev = _mod_revision.ensure_null(self.target.last_revision())
3351
# we fetch here so that we don't process data twice in the common
3352
# case of having something to pull, and so that the check for
3353
# already merged can operate on the just fetched graph, which will
3354
# be cached in memory.
3355
self.fetch(stop_revision=stop_revision)
3356
# Check to see if one is an ancestor of the other
3359
graph = self.target.repository.get_graph()
3360
if self.target._check_if_descendant_or_diverged(
3361
stop_revision, last_rev, graph, self.source):
3362
# stop_revision is a descendant of last_rev, but we aren't
3363
# overwriting, so we're done.
3365
if stop_revno is None:
3367
graph = self.target.repository.get_graph()
3368
this_revno, this_last_revision = \
3369
self.target.last_revision_info()
3370
stop_revno = graph.find_distance_to_null(stop_revision,
3371
[(other_last_revision, other_revno),
3372
(this_last_revision, this_revno)])
3373
self.target.set_last_revision_info(stop_revno, stop_revision)
3042
3376
def pull(self, overwrite=False, stop_revision=None,
3043
possible_transports=None, _hook_master=None, run_hooks=True,
3377
possible_transports=None, run_hooks=True,
3044
3378
_override_hook_target=None, local=False):
3379
"""Pull from source into self, updating my master if any.
3047
:param _hook_master: Private parameter - set the branch to
3048
be supplied as the master to pull hooks.
3049
3381
:param run_hooks: Private parameter - if false, this branch
3050
3382
is being called because it's the master of the primary branch,
3051
3383
so it should not run its hooks.
3052
:param _override_hook_target: Private parameter - set the branch to be
3053
supplied as the target_branch to pull hooks.
3054
:param local: Only update the local branch, and not the bound branch.
3056
# This type of branch can't be bound.
3385
bound_location = self.target.get_bound_location()
3386
if local and not bound_location:
3058
3387
raise errors.LocalRequiresBoundBranch()
3059
result = PullResult()
3060
result.source_branch = self.source
3061
if _override_hook_target is None:
3062
result.target_branch = self.target
3064
result.target_branch = _override_hook_target
3065
self.source.lock_read()
3388
master_branch = None
3389
source_is_master = (self.source.user_url == bound_location)
3390
if not local and bound_location and not source_is_master:
3391
# not pulling from master, so we need to update master.
3392
master_branch = self.target.get_master_branch(possible_transports)
3393
master_branch.lock_write()
3067
# We assume that during 'pull' the target repository is closer than
3069
self.source.update_references(self.target)
3070
graph = self.target.repository.get_graph(self.source.repository)
3071
# TODO: Branch formats should have a flag that indicates
3072
# that revno's are expensive, and pull() should honor that flag.
3074
result.old_revno, result.old_revid = \
3075
self.target.last_revision_info()
3076
self.target.update_revisions(self.source, stop_revision,
3077
overwrite=overwrite, graph=graph)
3078
# TODO: The old revid should be specified when merging tags,
3079
# so a tags implementation that versions tags can only
3080
# pull in the most recent changes. -- JRV20090506
3081
result.tag_conflicts = self.source.tags.merge_to(self.target.tags,
3083
result.new_revno, result.new_revid = self.target.last_revision_info()
3085
result.master_branch = _hook_master
3086
result.local_branch = result.target_branch
3088
result.master_branch = result.target_branch
3089
result.local_branch = None
3091
for hook in Branch.hooks['post_pull']:
3396
# pull from source into master.
3397
master_branch.pull(self.source, overwrite, stop_revision,
3399
return self._pull(overwrite,
3400
stop_revision, _hook_master=master_branch,
3401
run_hooks=run_hooks,
3402
_override_hook_target=_override_hook_target,
3403
merge_tags_to_master=not source_is_master)
3094
self.source.unlock()
3406
master_branch.unlock()
3097
3408
def push(self, overwrite=False, stop_revision=None,
3098
3409
_override_hook_source_branch=None):
3164
def is_compatible(self, source, target):
3165
# GenericBranch uses the public API, so always compatible
3169
class InterToBranch5(GenericInterBranch):
3172
def _get_branch_formats_to_test():
3173
return BranchFormat._default_format, BzrBranchFormat5()
3175
def pull(self, overwrite=False, stop_revision=None,
3176
possible_transports=None, run_hooks=True,
3177
_override_hook_target=None, local=False):
3178
"""Pull from source into self, updating my master if any.
3495
def _pull(self, overwrite=False, stop_revision=None,
3496
possible_transports=None, _hook_master=None, run_hooks=True,
3497
_override_hook_target=None, local=False,
3498
merge_tags_to_master=True):
3501
This function is the core worker, used by GenericInterBranch.pull to
3502
avoid duplication when pulling source->master and source->local.
3504
:param _hook_master: Private parameter - set the branch to
3505
be supplied as the master to pull hooks.
3180
3506
:param run_hooks: Private parameter - if false, this branch
3181
3507
is being called because it's the master of the primary branch,
3182
3508
so it should not run its hooks.
3509
is being called because it's the master of the primary branch,
3510
so it should not run its hooks.
3511
:param _override_hook_target: Private parameter - set the branch to be
3512
supplied as the target_branch to pull hooks.
3513
:param local: Only update the local branch, and not the bound branch.
3184
bound_location = self.target.get_bound_location()
3185
if local and not bound_location:
3515
# This type of branch can't be bound.
3186
3517
raise errors.LocalRequiresBoundBranch()
3187
master_branch = None
3188
if not local and bound_location and self.source.base != bound_location:
3189
# not pulling from master, so we need to update master.
3190
master_branch = self.target.get_master_branch(possible_transports)
3191
master_branch.lock_write()
3518
result = PullResult()
3519
result.source_branch = self.source
3520
if _override_hook_target is None:
3521
result.target_branch = self.target
3523
result.target_branch = _override_hook_target
3524
self.source.lock_read()
3194
# pull from source into master.
3195
master_branch.pull(self.source, overwrite, stop_revision,
3197
return super(InterToBranch5, self).pull(overwrite,
3198
stop_revision, _hook_master=master_branch,
3199
run_hooks=run_hooks,
3200
_override_hook_target=_override_hook_target)
3526
# We assume that during 'pull' the target repository is closer than
3528
self.source.update_references(self.target)
3529
graph = self.target.repository.get_graph(self.source.repository)
3530
# TODO: Branch formats should have a flag that indicates
3531
# that revno's are expensive, and pull() should honor that flag.
3533
result.old_revno, result.old_revid = \
3534
self.target.last_revision_info()
3535
self._update_revisions(stop_revision, overwrite=overwrite,
3537
# TODO: The old revid should be specified when merging tags,
3538
# so a tags implementation that versions tags can only
3539
# pull in the most recent changes. -- JRV20090506
3540
result.tag_conflicts = self.source.tags.merge_to(self.target.tags,
3541
overwrite, ignore_master=not merge_tags_to_master)
3542
result.new_revno, result.new_revid = self.target.last_revision_info()
3544
result.master_branch = _hook_master
3545
result.local_branch = result.target_branch
3547
result.master_branch = result.target_branch
3548
result.local_branch = None
3550
for hook in Branch.hooks['post_pull']:
3203
master_branch.unlock()
3553
self.source.unlock()
3206
3557
InterBranch.register_optimiser(GenericInterBranch)
3207
InterBranch.register_optimiser(InterToBranch5)