245
230
self.get_revision(revision_id))
233
class ForeignBranch(Branch):
234
"""Branch that exists in a foreign version control system."""
236
def __init__(self, mapping):
237
self.mapping = mapping
238
super(ForeignBranch, self).__init__()
241
def update_workingtree_fileids(wt, target_tree):
242
"""Update the file ids in a working tree based on another tree.
244
:param wt: Working tree in which to update file ids
245
:param target_tree: Tree to retrieve new file ids from, based on path
247
tt = transform.TreeTransform(wt)
249
for f, p, c, v, d, n, k, e in target_tree.iter_changes(wt):
250
if v == (True, False):
251
trans_id = tt.trans_id_tree_path(p[0])
252
tt.unversion_file(trans_id)
253
elif v == (False, True):
254
trans_id = tt.trans_id_tree_path(p[1])
255
tt.version_file(f, trans_id)
259
if len(wt.get_parent_ids()) == 1:
260
wt.set_parent_trees([(target_tree.get_revision_id(), target_tree)])
262
wt.set_last_revision(target_tree.get_revision_id())
265
class cmd_dpush(Command):
266
"""Push into a different VCS without any custom bzr metadata.
268
This will afterwards rebase the local branch on the remote
269
branch unless the --no-rebase option is used, in which case
270
the two branches will be out of sync after the push.
273
takes_args = ['location?']
274
takes_options = ['remember', Option('directory',
275
help='Branch to push from, '
276
'rather than the one containing the working directory.',
280
Option('no-rebase', help="Do not rebase after push.")]
282
def run(self, location=None, remember=False, directory=None,
284
from bzrlib import urlutils
285
from bzrlib.bzrdir import BzrDir
286
from bzrlib.errors import BzrCommandError, NoWorkingTree
287
from bzrlib.trace import info
288
from bzrlib.workingtree import WorkingTree
290
if directory is None:
293
source_wt = WorkingTree.open_containing(directory)[0]
294
source_branch = source_wt.branch
295
except NoWorkingTree:
296
source_branch = Branch.open(directory)
298
stored_loc = source_branch.get_push_location()
300
if stored_loc is None:
301
raise BzrCommandError("No push location known or specified.")
303
display_url = urlutils.unescape_for_display(stored_loc,
305
self.outf.write("Using saved location: %s\n" % display_url)
306
location = stored_loc
308
bzrdir = BzrDir.open(location)
309
target_branch = bzrdir.open_branch()
310
target_branch.lock_write()
313
push_result = source_branch.lossy_push(target_branch)
314
except errors.LossyPushToSameVCS:
315
raise BzrCommandError("%r and %r are in the same VCS, lossy "
316
"push not necessary. Please use regular push." %
317
(source_branch, target_branch))
318
# We successfully created the target, remember it
319
if source_branch.get_push_location() is None or remember:
320
source_branch.set_push_location(target_branch.base)
322
old_last_revid = source_branch.last_revision()
323
source_branch.pull(target_branch, overwrite=True)
324
new_last_revid = source_branch.last_revision()
325
if source_wt is not None and old_last_revid != new_last_revid:
326
source_wt.lock_write()
328
target = source_wt.branch.repository.revision_tree(
330
update_workingtree_fileids(source_wt, target)
333
push_result.report(self.outf)
335
target_branch.unlock()
338
class InterToForeignBranch(InterBranch):
340
def lossy_push(self, stop_revision=None):
341
"""Push deltas into another branch.
343
:note: This does not, like push, retain the revision ids from
344
the source branch and will, rather than adding bzr-specific
345
metadata, push only those semantics of the revision that can be
346
natively represented by this branch' VCS.
348
:param target: Target branch
349
:param stop_revision: Revision to push, defaults to last revision.
350
:return: BranchPushResult with an extra member revidmap:
351
A dictionary mapping revision ids from the target branch
352
to new revision ids in the target branch, for each
353
revision that was pushed.
355
raise NotImplementedError(self.lossy_push)