660
662
raise errors.UnsupportedOperation(self.get_reference_info, self)
662
664
@needs_write_lock
663
def fetch(self, from_branch, last_revision=None, pb=None):
665
def fetch(self, from_branch, last_revision=None, pb=None, fetch_spec=None):
664
666
"""Copy revisions from from_branch into this branch.
666
668
:param from_branch: Where to copy from.
667
669
:param last_revision: What revision to stop at (None for at the end
669
671
:param pb: An optional progress bar to use.
672
:param fetch_spec: If specified, a SearchResult or
673
PendingAncestryResult that describes which revisions to copy. This
674
allows copying multiple heads at once. Mutually exclusive with
678
if fetch_spec is not None and last_revision is not None:
679
raise AssertionError(
680
"fetch_spec and last_revision are mutually exclusive.")
672
681
if self.base == from_branch.base:
674
683
if pb is not None:
677
686
% "pb parameter to fetch()")
678
687
from_branch.lock_read()
680
if last_revision is None:
689
if last_revision is None and fetch_spec is None:
681
690
last_revision = from_branch.last_revision()
682
691
last_revision = _mod_revision.ensure_null(last_revision)
683
692
return self.repository.fetch(from_branch.repository,
684
693
revision_id=last_revision,
694
pb=pb, fetch_spec=fetch_spec)
687
696
from_branch.unlock()
871
880
# XXX: If you unstack a branch while it has a working tree
872
881
# with a pending merge, the pending-merged revisions will no
873
882
# longer be present. You can (probably) revert and remerge.
875
# XXX: This only fetches up to the tip of the repository; it
876
# doesn't bring across any tags. That's fairly consistent
877
# with how branch works, but perhaps not ideal.
878
self.repository.fetch(old_repository,
879
revision_id=self.last_revision(),
884
tags_to_fetch = set(self.tags.get_reverse_tag_dict())
885
except errors.TagsNotSupported:
886
tags_to_fetch = set()
887
fetch_spec = _mod_graph.NotInOtherForRevs(self.repository,
888
old_repository, required_ids=[self.last_revision()],
889
if_present_ids=tags_to_fetch, find_ghosts=True).execute()
890
self.repository.fetch(old_repository, fetch_spec=fetch_spec)
882
892
old_repository.unlock()
1020
1030
return other_history[self_len:stop_revision]
1022
1032
def update_revisions(self, other, stop_revision=None, overwrite=False,
1033
graph=None, fetch_tags=True):
1024
1034
"""Pull in new perfect-fit revisions.
1026
1036
:param other: Another Branch to pull from
1029
1039
to see if it is a proper descendant.
1030
1040
:param graph: A Graph object that can be used to query history
1031
1041
information. This can be None.
1042
:param fetch_tags: Flag that specifies if tags from other should be
1034
1046
return InterBranch.get(other, self).update_revisions(stop_revision,
1047
overwrite, graph, fetch_tags=fetch_tags)
1049
@deprecated_method(deprecated_in((2, 4, 0)))
1037
1050
def import_last_revision_info(self, source_repo, revno, revid):
1038
1051
"""Set the last revision info, importing from another repo if necessary.
1040
This is used by the bound branch code to upload a revision to
1041
the master branch first before updating the tip of the local branch.
1043
1053
:param source_repo: Source repository to optionally fetch from
1044
1054
:param revno: Revision number of the new tip
1045
1055
:param revid: Revision id of the new tip
1048
1058
self.repository.fetch(source_repo, revision_id=revid)
1049
1059
self.set_last_revision_info(revno, revid)
1061
def import_last_revision_info_and_tags(self, source, revno, revid):
1062
"""Set the last revision info, importing from another repo if necessary.
1064
This is used by the bound branch code to upload a revision to
1065
the master branch first before updating the tip of the local branch.
1066
Revisions referenced by source's tags are also transferred.
1068
:param source: Source branch to optionally fetch from
1069
:param revno: Revision number of the new tip
1070
:param revid: Revision id of the new tip
1072
if not self.repository.has_same_location(source.repository):
1074
tags_to_fetch = set(source.tags.get_reverse_tag_dict())
1075
except errors.TagsNotSupported:
1076
tags_to_fetch = set()
1077
fetch_spec = _mod_graph.NotInOtherForRevs(self.repository,
1078
source.repository, [revid],
1079
if_present_ids=tags_to_fetch).execute()
1080
self.repository.fetch(source.repository, fetch_spec=fetch_spec)
1081
self.set_last_revision_info(revno, revid)
1051
1083
def revision_id_to_revno(self, revision_id):
1052
1084
"""Given a revision id, return its revno"""
1053
1085
if _mod_revision.is_null(revision_id):
1592
1627
if isinstance(fmt, MetaDirBranchFormatFactory):
1594
1629
result.append(fmt)
1630
return result + klass._extra_formats
1597
1632
def get_reference(self, a_bzrdir, name=None):
1598
1633
"""Get the target reference of the branch in a_bzrdir.
1738
1773
raise NotImplementedError(self.open)
1776
def register_extra_format(klass, format):
1777
"""Register a branch format that can not be part of a metadir.
1779
This is mainly useful to allow custom branch formats, such as
1780
older Bazaar formats and foreign formats, to be tested
1782
klass._extra_formats.append(format)
1783
network_format_registry.register(
1784
format.network_name(), format.__class__)
1741
1787
def register_format(klass, format):
1742
1788
"""Register a metadir format.
1769
1815
def unregister_format(klass, format):
1770
1816
del klass._formats[format.get_format_string()]
1819
def unregister_extra_format(klass, format):
1820
klass._extra_formats.remove(format)
1772
1822
def __str__(self):
1773
1823
return self.get_format_description().rstrip()
2379
2429
BranchFormat.register_format(__format7)
2380
2430
BranchFormat.register_format(__format8)
2381
2431
BranchFormat.set_default_format(__format7)
2382
_legacy_formats = [BzrBranchFormat4(),
2384
network_format_registry.register(
2385
_legacy_formats[0].network_name(), _legacy_formats[0].__class__)
2432
BranchFormat.register_extra_format(BzrBranchFormat4())
2388
2435
class BranchWriteLockResult(LogicalLockResult):
3339
3386
@needs_write_lock
3340
3387
def update_revisions(self, stop_revision=None, overwrite=False,
3388
graph=None, fetch_tags=True):
3342
3389
"""Pull in new perfect-fit revisions.
3344
3391
:param stop_revision: Updated until the given revision
3346
3393
to see if it is a proper descendant.
3347
3394
:param graph: A Graph object that can be used to query history
3348
3395
information. This can be None.
3396
:param fetch_tags: Flag that specifies if tags from source should be
3351
3400
raise NotImplementedError(self.update_revisions)
3410
3459
@needs_write_lock
3411
3460
def update_revisions(self, stop_revision=None, overwrite=False,
3461
graph=None, fetch_tags=True):
3413
3462
"""See InterBranch.update_revisions()."""
3414
3463
other_revno, other_last_revision = self.source.last_revision_info()
3415
3464
stop_revno = None # unknown
3427
3476
# case of having something to pull, and so that the check for
3428
3477
# already merged can operate on the just fetched graph, which will
3429
3478
# be cached in memory.
3430
self.target.fetch(self.source, stop_revision)
3480
fetch_spec_factory = fetch.FetchSpecFactory()
3481
fetch_spec_factory.source_branch = self.source
3482
fetch_spec_factory.source_branch_stop_revision_id = stop_revision
3483
fetch_spec_factory.source_repo = self.source.repository
3484
fetch_spec_factory.target_repo = self.target.repository
3485
fetch_spec_factory.target_repo_kind = fetch.TargetRepoKinds.PREEXISTING
3486
fetch_spec = fetch_spec_factory.make_fetch_spec()
3488
fetch_spec = _mod_graph.NotInOtherForRevs(self.target.repository,
3489
self.source.repository, revision_ids=[stop_revision]).execute()
3490
self.target.fetch(self.source, fetch_spec=fetch_spec)
3431
3491
# Check to see if one is an ancestor of the other
3432
3492
if not overwrite:
3433
3493
if graph is None: