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."""
384
def __init__(self, fileid, revid):
385
BzrError.__init__(self)
390
class CommitBuilderRevisionRewriter(object):
391
"""Revision rewriter that use commit builder.
393
:ivar repository: Repository in which the revision is present.
382
396
def __init__(self, repository):
383
397
self.repository = repository
399
def _process_file(self, old_ie, oldtree, oldrevid, newrevid,
400
old_parent_invs, new_parent_invs, path):
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
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
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):
423
ie = new_pinv[old_ie.file_id].copy()
425
raise ReplayParentsInconsistent(old_ie.file_id, old_ie.revision)
427
assert ie is not None
430
def _get_present_revisions(self, revids):
431
return tuple([p for p in revids if self.repository.has_revision(p)])
385
433
def __call__(self, oldrevid, newrevid, new_parents):
386
434
"""Replay a commit by simply commiting the same snapshot with different
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.
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
402
449
builder = self.repository.get_commit_builder(branch=None,
405
committer=oldrev.committer,
406
timestamp=oldrev.timestamp,
407
timezone=oldrev.timezone,
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)
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,
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()
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))
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
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
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):
446
ie = new_pinv[old_ie.file_id].copy()
448
raise ReplayParentsInconsistent(old_ie.file_id, old_ie.revision)
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))