~cjwatson/bzr-rewrite/merge-file-ids

« back to all changes in this revision

Viewing changes to rebase.py

  • Committer: Jelmer Vernooij
  • Date: 2010-03-27 13:34:30 UTC
  • Revision ID: jelmer@samba.org-20100327133430-jxv3zp6e26q0n8dr
Split up large method.

Show diffs side-by-side

added added

removed removed

Lines of Context:
377
377
        pb.finished()
378
378
 
379
379
 
380
 
class SnapshotRevisionRewriter(object):
 
380
class ReplayParentsInconsistent(BzrError):
 
381
    """Raised when parents were inconsistent."""
 
382
    _fmt = """Parents were inconsistent while replaying commit for file id %(fileid)s, revision %(revid)s."""
 
383
 
 
384
    def __init__(self, fileid, revid):
 
385
        BzrError.__init__(self)
 
386
        self.fileid = fileid
 
387
        self.revid = revid
 
388
 
 
389
 
 
390
class CommitBuilderRevisionRewriter(object):
 
391
    """Revision rewriter that use commit builder.
 
392
 
 
393
    :ivar repository: Repository in which the revision is present.
 
394
    """
381
395
 
382
396
    def __init__(self, repository):
383
397
        self.repository = repository
384
398
 
 
399
    def _process_file(self, old_ie, oldtree, oldrevid, newrevid,
 
400
                      old_parent_invs, new_parent_invs, path):
 
401
        ie = old_ie.copy()
 
402
        # Either this file was modified last in this revision,
 
403
        # in which case it has to be rewritten
 
404
        if old_ie.revision == oldrevid:
 
405
            if self.repository.texts.has_key((ie.file_id, newrevid)):
 
406
                # Use the existing text
 
407
                ie.revision = newrevid
 
408
            else:
 
409
                # Create a new text
 
410
                ie.revision = None
 
411
        else:
 
412
            # or it was already there before the commit, in
 
413
            # which case the right revision should be used
 
414
            # one of the old parents had this revision, so find that
 
415
            # and then use the matching new parent
 
416
            old_file_id = oldtree.inventory.path2id(path)
 
417
            assert old_file_id is not None
 
418
            ie = None
 
419
            for (old_pinv, new_pinv) in zip(old_parent_invs, new_parent_invs):
 
420
                if (old_pinv.has_id(old_file_id) and
 
421
                    old_pinv[old_file_id].revision == old_ie.revision):
 
422
                    try:
 
423
                        ie = new_pinv[old_ie.file_id].copy()
 
424
                    except NoSuchId:
 
425
                        raise ReplayParentsInconsistent(old_ie.file_id, old_ie.revision)
 
426
                    break
 
427
            assert ie is not None
 
428
        return ie
 
429
 
 
430
    def _get_present_revisions(self, revids):
 
431
        return tuple([p for p in revids if self.repository.has_revision(p)])
 
432
 
385
433
    def __call__(self, oldrevid, newrevid, new_parents):
386
434
        """Replay a commit by simply commiting the same snapshot with different
387
435
        parents.
388
436
 
389
 
        :param repository: Repository in which the revision is present.
390
437
        :param oldrevid: Revision id of the revision to copy.
391
438
        :param newrevid: Revision id of the revision to create.
392
439
        :param new_parents: Revision ids of the new parent revisions.
393
440
        """
394
 
        assert isinstance(new_parents, tuple), "SnapshotRevisionRewriter: Expected tuple for %r" % new_parents
 
441
        assert isinstance(new_parents, tuple), "CommitBuilderRevisionRewriter: Expected tuple for %r" % new_parents
395
442
        mutter('creating copy %r of %r with new parents %r' %
396
443
                                   (newrevid, oldrevid, new_parents))
397
444
        oldrev = self.repository.get_revision(oldrevid)
400
447
        revprops[REVPROP_REBASE_OF] = oldrevid
401
448
 
402
449
        builder = self.repository.get_commit_builder(branch=None,
403
 
                                                parents=new_parents,
404
 
                                                config=Config(),
405
 
                                                committer=oldrev.committer,
406
 
                                                timestamp=oldrev.timestamp,
407
 
                                                timezone=oldrev.timezone,
408
 
                                                revprops=revprops,
409
 
                                                revision_id=newrevid)
 
450
            parents=new_parents, config=Config(), committer=oldrev.committer,
 
451
            timestamp=oldrev.timestamp, timezone=oldrev.timezone,
 
452
            revprops=revprops, revision_id=newrevid)
410
453
        try:
411
454
            # Check what new_ie.file_id should be
412
455
            # use old and new parent inventories to generate new_id map
413
 
            nonghost_oldparents = tuple([p for p in oldrev.parent_ids if self.repository.has_revision(p)])
414
 
            nonghost_newparents = tuple([p for p in new_parents if self.repository.has_revision(p)])
415
 
            fileid_map = map_file_ids(self.repository, nonghost_oldparents, nonghost_newparents)
 
456
            nonghost_oldparents = self._get_present_revisions(oldrev.parent_ids)
 
457
            nonghost_newparents = self._get_present_revisions(new_parents)
 
458
            fileid_map = map_file_ids(self.repository, nonghost_oldparents,
 
459
                nonghost_newparents)
416
460
            oldtree = self.repository.revision_tree(oldrevid)
417
461
            mappedtree = MapTree(oldtree, fileid_map)
 
462
            old_parent_invs = list(self.repository.iter_inventories(nonghost_oldparents))
 
463
            new_parent_invs = list(self.repository.iter_inventories(nonghost_newparents))
418
464
            pb = ui.ui_factory.nested_progress_bar()
419
465
            try:
420
 
                old_parent_invs = list(self.repository.iter_inventories(nonghost_oldparents))
421
 
                new_parent_invs = list(self.repository.iter_inventories(nonghost_newparents))
422
466
                for i, (path, old_ie) in enumerate(mappedtree.inventory.iter_entries()):
423
467
                    pb.update('upgrading file', i, len(mappedtree.inventory))
424
 
                    ie = old_ie.copy()
425
 
                    # Either this file was modified last in this revision,
426
 
                    # in which case it has to be rewritten
427
 
                    if old_ie.revision == oldrevid:
428
 
                        if self.repository.texts.has_key((ie.file_id, newrevid)):
429
 
                            # Use the existing text
430
 
                            ie.revision = newrevid
431
 
                        else:
432
 
                            # Create a new text
433
 
                            ie.revision = None
434
 
                    else:
435
 
                        # or it was already there before the commit, in
436
 
                        # which case the right revision should be used
437
 
                        # one of the old parents had this revision, so find that
438
 
                        # and then use the matching new parent
439
 
                        old_file_id = oldtree.inventory.path2id(path)
440
 
                        assert old_file_id is not None
441
 
                        ie = None
442
 
                        for (old_pinv, new_pinv) in zip(old_parent_invs, new_parent_invs):
443
 
                            if (old_pinv.has_id(old_file_id) and
444
 
                                old_pinv[old_file_id].revision == old_ie.revision):
445
 
                                try:
446
 
                                    ie = new_pinv[old_ie.file_id].copy()
447
 
                                except NoSuchId:
448
 
                                    raise ReplayParentsInconsistent(old_ie.file_id, old_ie.revision)
449
 
                                break
450
 
                        assert ie is not None
451
 
                    builder.record_entry_contents(ie, new_parent_invs, path, mappedtree,
 
468
                    ie = self._process_file(old_ie, oldtree, oldrevid, newrevid,
 
469
                        old_parent_invs, new_parent_invs, path)
 
470
                    builder.record_entry_contents(ie,
 
471
                            new_parent_invs, path, mappedtree,
452
472
                            mappedtree.path_content_summary(path))
453
473
            finally:
454
474
                pb.finished()
521
541
        if len(oldparents) == 1:
522
542
            return oldparents[0]
523
543
 
524
 
        # In case the rhs parent(s) of the origin revision has already been merged
525
 
        # in the new branch, use diff between rhs parent and diff from
 
544
        # In case the rhs parent(s) of the origin revision has already been
 
545
        # merged in the new branch, use diff between rhs parent and diff from
526
546
        # original revision
527
547
        if len(newparents) == 1:
528
548
            # FIXME: Find oldparents entry that matches newparents[0]
593
613
        self.msg = msg
594
614
 
595
615
 
596
 
class ReplayParentsInconsistent(BzrError):
597
 
    """Raised when parents were inconsistent."""
598
 
    _fmt = """Parents were inconsistent while replaying commit for file id %(fileid)s, revision %(revid)s."""
599
616
 
600
 
    def __init__(self, fileid, revid):
601
 
        BzrError.__init__(self)
602
 
        self.fileid = fileid
603
 
        self.revid = revid