17
17
"""Foreign branch utilities."""
19
from bzrlib import errors, log, osutils, registry
20
19
from bzrlib.branch import Branch
21
20
from bzrlib.commands import Command, Option
22
from bzrlib.errors import InvalidRevisionId
23
21
from bzrlib.repository import Repository
24
22
from bzrlib.revision import Revision
25
from bzrlib.trace import info
27
class VcsMapping(object):
28
"""Describes the mapping between the semantics of Bazaar and a foreign vcs.
31
# Whether this is an experimental mapping that is still open to changes.
34
# Whether this mapping supports exporting and importing all bzr semantics.
37
# Prefix used when importing native foreign revisions (not roundtripped)
41
def revision_id_bzr_to_foreign(self, bzr_revid):
42
"""Parse a bzr revision id and convert it to a foreign revid.
44
:param bzr_revid: The bzr revision id (a string).
45
:return: A foreign revision id, can be any sort of object.
47
raise NotImplementedError(self.revision_id_bzr_to_foreign)
49
def revision_id_foreign_to_bzr(self, foreign_revid):
50
"""Parse a foreign revision id and convert it to a bzr revid.
52
:param foreign_revid: Foreign revision id, can be any sort of object.
53
:return: A bzr revision id.
55
raise NotImplementedError(self.revision_id_foreign_to_bzr)
57
def show_foreign_revid(self, foreign_revid):
58
"""Prepare a foreign revision id for formatting using bzr log.
60
:param foreign_revid: Foreign revision id.
61
:return: Dictionary mapping string keys to string values.
66
class VcsMappingRegistry(registry.Registry):
67
"""Registry for Bazaar<->foreign VCS mappings.
69
There should be one instance of this registry for every foreign VCS.
72
def register(self, key, factory, help):
73
"""Register a mapping between Bazaar and foreign VCS semantics.
75
The factory must be a callable that takes one parameter: the key.
76
It must produce an instance of VcsMapping when called.
79
raise ValueError("mapping name can not contain colon (:)")
80
registry.Registry.register(self, key, factory, help)
82
def set_default(self, key):
83
"""Set the 'default' key to be a clone of the supplied key.
85
This method must be called once and only once.
87
self._set_default_key(key)
89
def get_default(self):
90
"""Convenience function for obtaining the default mapping to use."""
91
return self.get(self._get_default_key())
93
def revision_id_bzr_to_foreign(self, revid):
94
"""Convert a bzr revision id to a foreign revid."""
95
raise NotImplementedError(self.revision_id_bzr_to_foreign)
98
class ForeignVcs(object):
99
"""A foreign version control system."""
101
def __init__(self, mapping_registry):
102
self.mapping_registry = mapping_registry
105
class ForeignVcsRegistry(registry.Registry):
106
"""Registry for Foreign VCSes.
110
def register(self, key, foreign_vcs, help):
111
"""Register a foreign VCS.
114
if ":" in key or "-" in key:
115
raise ValueError("vcs name can not contain : or -")
116
registry.Registry.register(self, key, foreign_vcs, help)
118
def parse_revision_id(self, revid):
120
raise InvalidRevisionId(revid, None)
122
foreign_vcs = self.get(revid.split("-")[0])
124
raise InvalidRevisionId(revid, None)
125
return foreign_vcs.mapping_registry.revision_id_bzr_to_foreign(revid)
23
from bzrlib.lazy_import import lazy_import
24
lazy_import(globals(), """
128
34
class ForeignBranch(Branch):
136
42
"""Pull deltas from another branch.
138
44
:note: This does not, like pull, retain the revision ids from
45
the source branch and will, rather than adding bzr-specific metadata,
46
push only those semantics of the revision that can be natively
47
represented in this branch.
141
49
:param source: Source branch
142
50
:param stop_revision: Revision to pull, defaults to last revision.
144
raise NotImplementedError(self.pull)
52
raise NotImplementedError(self.dpull)
55
class ForeignRepository(Repository):
57
def has_foreign_revision(self, foreign_revid):
58
raise NotImplementedError(self.has_foreign_revision)
60
def _all_revision_ids(self, mapping=None):
61
raise NotImplementedError(self._all_revision_ids)
63
def get_mapping(self):
64
raise NotImplementedError(self.get_mapping)
66
def get_inventory_xml(self, revision_id):
67
"""See Repository.get_inventory_xml()."""
68
return self.serialise_inventory(self.get_inventory(revision_id))
70
def get_inventory_sha1(self, revision_id):
71
"""Get the sha1 for the XML representation of an inventory.
73
:param revision_id: Revision id of the inventory for which to return
78
return osutils.sha_string(self.get_inventory_xml(revision_id))
80
def get_revision_xml(self, revision_id):
81
"""Return the XML representation of a revision.
83
:param revision_id: Revision for which to return the XML.
86
return self._serializer.write_revision_to_string(self.get_revision(revision_id))
147
90
class ForeignRepository(Repository):
292
class ForeignRevision(Revision):
293
"""A Revision from a Foreign repository. Remembers
294
information about foreign revision id and mapping.
298
def __init__(self, foreign_revid, mapping, *args, **kwargs):
299
if not "inventory_sha1" in kwargs:
300
kwargs["inventory_sha1"] = ""
301
super(ForeignRevision, self).__init__(*args, **kwargs)
302
self.foreign_revid = foreign_revid
303
self.mapping = mapping
306
def show_foreign_properties(rev):
307
"""Custom log displayer for foreign revision identifiers.
309
:param rev: Revision object.
311
# Revision comes directly from a foreign repository
312
if isinstance(rev, ForeignRevision):
313
return rev.mapping.show_foreign_revid(rev.foreign_revid)
315
# Revision was once imported from a foreign repository
317
foreign_revid, mapping = foreign_vcs_registry.parse_revision_id(rev.revision_id)
318
except InvalidRevisionId:
321
return mapping.show_foreign_revid(foreign_revid)
323
if not "foreign" in log.properties_handler_registry:
324
log.properties_handler_registry.register("foreign",
325
show_foreign_properties,
326
"Show foreign VCS properties")
328
foreign_vcs_registry = ForeignVcsRegistry()