~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/foreign.py

  • Committer: Robert J. Tanner
  • Date: 2009-04-20 08:37:32 UTC
  • mfrom: (4299 +trunk)
  • mto: This revision was merged to the branch mainline in revision 4300.
  • Revision ID: tanner@real-time.com-20090420083732-bzx919oo7wpmqc2u
[merge] 1.14rc2 back into bzr.dev (Bob Tanner)

Show diffs side-by-side

added added

removed removed

Lines of Context:
28
28
    errors,
29
29
    osutils,
30
30
    registry,
 
31
    transform,
31
32
    )
32
33
""")
33
34
 
245
246
            self.get_revision(revision_id))
246
247
 
247
248
 
 
249
class ForeignBranch(Branch):
 
250
    """Branch that exists in a foreign version control system."""
 
251
 
 
252
    def __init__(self, mapping):
 
253
        self.mapping = mapping
 
254
        super(ForeignBranch, self).__init__()
 
255
 
 
256
    def dpull(self, source, stop_revision=None):
 
257
        """Pull deltas from another branch.
 
258
 
 
259
        :note: This does not, like pull, retain the revision ids from 
 
260
            the source branch and will, rather than adding bzr-specific 
 
261
            metadata, push only those semantics of the revision that can be 
 
262
            natively represented by this branch' VCS.
 
263
 
 
264
        :param source: Source branch
 
265
        :param stop_revision: Revision to pull, defaults to last revision.
 
266
        :return: Dictionary mapping revision ids from the source branch 
 
267
            to new revision ids in the target branch, for each 
 
268
            revision that was pull.
 
269
        """
 
270
        raise NotImplementedError(self.dpull)
 
271
 
 
272
 
 
273
def update_workingtree_fileids(wt, target_tree):
 
274
    """Update the file ids in a working tree based on another tree.
 
275
 
 
276
    :param wt: Working tree in which to update file ids
 
277
    :param target_tree: Tree to retrieve new file ids from, based on path
 
278
    """
 
279
    tt = transform.TreeTransform(wt)
 
280
    try:
 
281
        for f, p, c, v, d, n, k, e in target_tree.iter_changes(wt):
 
282
            if v == (True, False):
 
283
                trans_id = tt.trans_id_tree_path(p[0])
 
284
                tt.unversion_file(trans_id)
 
285
            elif v == (False, True):
 
286
                trans_id = tt.trans_id_tree_path(p[1])
 
287
                tt.version_file(f, trans_id)
 
288
        tt.apply()
 
289
    finally:
 
290
        tt.finalize()
 
291
    if len(wt.get_parent_ids()) == 1:
 
292
        wt.set_parent_trees([(target_tree.get_revision_id(), target_tree)])
 
293
    else:
 
294
        wt.set_last_revision(target_tree.get_revision_id())
 
295
 
 
296
 
 
297
class cmd_dpush(Command):
 
298
    """Push diffs into a foreign version control system without any 
 
299
    Bazaar-specific metadata.
 
300
 
 
301
    This will afterwards rebase the local Bazaar branch on the remote
 
302
    branch unless the --no-rebase option is used, in which case 
 
303
    the two branches will be out of sync. 
 
304
    """
 
305
    hidden = True
 
306
    takes_args = ['location?']
 
307
    takes_options = ['remember', Option('directory',
 
308
            help='Branch to push from, '
 
309
                 'rather than the one containing the working directory.',
 
310
            short_name='d',
 
311
            type=unicode,
 
312
            ),
 
313
            Option('no-rebase', help="Do not rebase after push.")]
 
314
 
 
315
    def run(self, location=None, remember=False, directory=None, 
 
316
            no_rebase=False):
 
317
        from bzrlib import urlutils
 
318
        from bzrlib.bzrdir import BzrDir
 
319
        from bzrlib.errors import BzrCommandError, NoWorkingTree
 
320
        from bzrlib.trace import info
 
321
        from bzrlib.workingtree import WorkingTree
 
322
 
 
323
        if directory is None:
 
324
            directory = "."
 
325
        try:
 
326
            source_wt = WorkingTree.open_containing(directory)[0]
 
327
            source_branch = source_wt.branch
 
328
        except NoWorkingTree:
 
329
            source_branch = Branch.open(directory)
 
330
            source_wt = None
 
331
        stored_loc = source_branch.get_push_location()
 
332
        if location is None:
 
333
            if stored_loc is None:
 
334
                raise BzrCommandError("No push location known or specified.")
 
335
            else:
 
336
                display_url = urlutils.unescape_for_display(stored_loc,
 
337
                        self.outf.encoding)
 
338
                self.outf.write("Using saved location: %s\n" % display_url)
 
339
                location = stored_loc
 
340
 
 
341
        bzrdir = BzrDir.open(location)
 
342
        target_branch = bzrdir.open_branch()
 
343
        dpull = getattr(target_branch, "dpull", None)
 
344
        if dpull is None:
 
345
            raise BzrCommandError("%r is not a foreign branch, use "
 
346
                                  "regular push." % target_branch)
 
347
        target_branch.lock_write()
 
348
        try:
 
349
            revid_map = dpull(source_branch)
 
350
            # We successfully created the target, remember it
 
351
            if source_branch.get_push_location() is None or remember:
 
352
                source_branch.set_push_location(target_branch.base)
 
353
            if not no_rebase:
 
354
                old_last_revid = source_branch.last_revision()
 
355
                source_branch.pull(target_branch, overwrite=True)
 
356
                new_last_revid = source_branch.last_revision()
 
357
                if source_wt is not None and old_last_revid != new_last_revid:
 
358
                    source_wt.lock_write()
 
359
                    try:
 
360
                        target = source_wt.branch.repository.revision_tree(
 
361
                            new_last_revid)
 
362
                        update_workingtree_fileids(source_wt, target)
 
363
                    finally:
 
364
                        source_wt.unlock()
 
365
        finally:
 
366
            target_branch.unlock()