119
117
self.mapping = mapping
120
def show_foreign_properties(rev):
121
"""Custom log displayer for foreign revision identifiers.
123
:param rev: Revision object.
125
# Revision comes directly from a foreign repository
126
if isinstance(rev, ForeignRevision):
127
return rev.mapping.show_foreign_revid(rev.foreign_revid)
129
# Revision was once imported from a foreign repository
131
foreign_revid, mapping = \
132
foreign_vcs_registry.parse_revision_id(rev.revision_id)
133
except errors.InvalidRevisionId:
136
return mapping.show_foreign_revid(foreign_revid)
122
139
class ForeignVcs(object):
123
140
"""A foreign version control system."""
127
repository_format = None
129
def __init__(self, mapping_registry, abbreviation=None):
130
"""Create a new foreign vcs instance.
132
:param mapping_registry: Registry with mappings for this VCS.
133
:param abbreviation: Optional abbreviation ('bzr', 'svn', 'git', etc)
135
self.abbreviation = abbreviation
142
def __init__(self, mapping_registry):
136
143
self.mapping_registry = mapping_registry
138
def show_foreign_revid(self, foreign_revid):
139
"""Prepare a foreign revision id for formatting using bzr log.
141
:param foreign_revid: Foreign revision id.
142
:return: Dictionary mapping string keys to string values.
146
def serialize_foreign_revid(self, foreign_revid):
147
"""Serialize a foreign revision id for this VCS.
149
:param foreign_revid: Foreign revision id
150
:return: Bytestring with serialized revid, will not contain any
153
raise NotImplementedError(self.serialize_foreign_revid)
156
146
class ForeignVcsRegistry(registry.Registry):
157
147
"""Registry for Foreign VCSes.
159
There should be one entry per foreign VCS. Example entries would be
149
There should be one entry per foreign VCS. Example entries would be
160
150
"git", "svn", "hg", "darcs", etc.
164
154
def register(self, key, foreign_vcs, help):
225
215
"""Get the default mapping for this repository."""
226
216
raise NotImplementedError(self.get_default_mapping)
229
class ForeignBranch(Branch):
230
"""Branch that exists in a foreign version control system."""
232
def __init__(self, mapping):
233
self.mapping = mapping
234
super(ForeignBranch, self).__init__()
237
def update_workingtree_fileids(wt, target_tree):
238
"""Update the file ids in a working tree based on another tree.
240
:param wt: Working tree in which to update file ids
241
:param target_tree: Tree to retrieve new file ids from, based on path
243
tt = transform.TreeTransform(wt)
245
for f, p, c, v, d, n, k, e in target_tree.iter_changes(wt):
246
if v == (True, False):
247
trans_id = tt.trans_id_tree_path(p[0])
248
tt.unversion_file(trans_id)
249
elif v == (False, True):
250
trans_id = tt.trans_id_tree_path(p[1])
251
tt.version_file(f, trans_id)
255
if len(wt.get_parent_ids()) == 1:
256
wt.set_parent_trees([(target_tree.get_revision_id(), target_tree)])
258
wt.set_last_revision(target_tree.get_revision_id())
261
class cmd_dpush(Command):
262
__doc__ = """Push into a different VCS without any custom bzr metadata.
264
This will afterwards rebase the local branch on the remote
265
branch unless the --no-rebase option is used, in which case
266
the two branches will be out of sync after the push.
269
takes_args = ['location?']
273
help='Branch to push from, '
274
'rather than the one containing the working directory.',
278
Option('no-rebase', help="Do not rebase after push."),
280
help='Refuse to push if there are uncommitted changes in'
281
' the working tree, --no-strict disables the check.'),
284
def run(self, location=None, remember=False, directory=None,
285
no_rebase=False, strict=None):
286
from bzrlib import urlutils
287
from bzrlib.bzrdir import BzrDir
288
from bzrlib.errors import BzrCommandError, NoWorkingTree
289
from bzrlib.workingtree import WorkingTree
291
if directory is None:
294
source_wt = WorkingTree.open_containing(directory)[0]
295
source_branch = source_wt.branch
296
except NoWorkingTree:
297
source_branch = Branch.open(directory)
299
if source_wt is not None:
300
source_wt.check_changed_or_out_of_date(
301
strict, 'dpush_strict',
302
more_error='Use --no-strict to force the push.',
303
more_warning='Uncommitted changes will not be pushed.')
304
stored_loc = source_branch.get_push_location()
306
if stored_loc is None:
307
raise BzrCommandError("No push location known or specified.")
309
display_url = urlutils.unescape_for_display(stored_loc,
311
self.outf.write("Using saved location: %s\n" % display_url)
312
location = stored_loc
314
bzrdir = BzrDir.open(location)
315
target_branch = bzrdir.open_branch()
316
target_branch.lock_write()
319
push_result = source_branch.lossy_push(target_branch)
320
except errors.LossyPushToSameVCS:
321
raise BzrCommandError("%r and %r are in the same VCS, lossy "
322
"push not necessary. Please use regular push." %
323
(source_branch, target_branch))
324
# We successfully created the target, remember it
325
if source_branch.get_push_location() is None or remember:
326
source_branch.set_push_location(target_branch.base)
328
old_last_revid = source_branch.last_revision()
329
source_branch.pull(target_branch, overwrite=True)
330
new_last_revid = source_branch.last_revision()
331
if source_wt is not None and old_last_revid != new_last_revid:
332
source_wt.lock_write()
334
target = source_wt.branch.repository.revision_tree(
336
update_workingtree_fileids(source_wt, target)
339
push_result.report(self.outf)
341
target_branch.unlock()
344
class InterToForeignBranch(InterBranch):
346
def lossy_push(self, stop_revision=None):
347
"""Push deltas into another branch.
349
:note: This does not, like push, retain the revision ids from
350
the source branch and will, rather than adding bzr-specific
351
metadata, push only those semantics of the revision that can be
352
natively represented by this branch' VCS.
354
:param target: Target branch
355
:param stop_revision: Revision to push, defaults to last revision.
356
:return: BranchPushResult with an extra member revidmap:
357
A dictionary mapping revision ids from the target branch
358
to new revision ids in the target branch, for each
359
revision that was pushed.
361
raise NotImplementedError(self.lossy_push)
218
def get_inventory_xml(self, revision_id):
219
"""See Repository.get_inventory_xml()."""
220
return self.serialise_inventory(self.get_inventory(revision_id))
222
def get_inventory_sha1(self, revision_id):
223
"""Get the sha1 for the XML representation of an inventory.
225
:param revision_id: Revision id of the inventory for which to return
230
return osutils.sha_string(self.get_inventory_xml(revision_id))
232
def get_revision_xml(self, revision_id):
233
"""Return the XML representation of a revision.
235
:param revision_id: Revision for which to return the XML.
238
return self._serializer.write_revision_to_string(
239
self.get_revision(revision_id))