comparison hgext/fix.py @ 40570:ad71c792a8d8

fix: add extra field to fixed revisions to avoid creating obsolescence cycles The extra field prevents sequential invocations of fix from producing the same hash twice. Previously, this could cause problems because it would create an obsolescence cycle instead of the expected new successor. This change also adds an explicit check for whether a new revision should be committed. Until now, the code relied on memctx.commit() to quietly do nothing if the node already exists. Because of the new extra field, this no longer covers the case where we don't want to replace an unchanged node. Differential Revision: https://phab.mercurial-scm.org/D5245
author Danny Hooper <hooper@google.com>
date Thu, 08 Nov 2018 12:35:26 -0800
parents b9557567cc3f
children d8f5c615e811
comparison
equal deleted inserted replaced
40569:19e1c26213f1 40570:ad71c792a8d8
584 p1rev, p2rev = repo.changelog.parentrevs(ctx.rev()) 584 p1rev, p2rev = repo.changelog.parentrevs(ctx.rev())
585 p1ctx, p2ctx = repo[p1rev], repo[p2rev] 585 p1ctx, p2ctx = repo[p1rev], repo[p2rev]
586 newp1node = replacements.get(p1ctx.node(), p1ctx.node()) 586 newp1node = replacements.get(p1ctx.node(), p1ctx.node())
587 newp2node = replacements.get(p2ctx.node(), p2ctx.node()) 587 newp2node = replacements.get(p2ctx.node(), p2ctx.node())
588 588
589 # We don't want to create a revision that has no changes from the original,
590 # but we should if the original revision's parent has been replaced.
591 # Otherwise, we would produce an orphan that needs no actual human
592 # intervention to evolve. We can't rely on commit() to avoid creating the
593 # un-needed revision because the extra field added below produces a new hash
594 # regardless of file content changes.
595 if (not filedata and
596 p1ctx.node() not in replacements and
597 p2ctx.node() not in replacements):
598 return
599
589 def filectxfn(repo, memctx, path): 600 def filectxfn(repo, memctx, path):
590 if path not in ctx: 601 if path not in ctx:
591 return None 602 return None
592 fctx = ctx[path] 603 fctx = ctx[path]
593 copied = fctx.renamed() 604 copied = fctx.renamed()
600 data=filedata.get(path, fctx.data()), 611 data=filedata.get(path, fctx.data()),
601 islink=fctx.islink(), 612 islink=fctx.islink(),
602 isexec=fctx.isexec(), 613 isexec=fctx.isexec(),
603 copied=copied) 614 copied=copied)
604 615
616 extra = ctx.extra().copy()
617 extra['fix_source'] = ctx.hex()
618
605 memctx = context.memctx( 619 memctx = context.memctx(
606 repo, 620 repo,
607 parents=(newp1node, newp2node), 621 parents=(newp1node, newp2node),
608 text=ctx.description(), 622 text=ctx.description(),
609 files=set(ctx.files()) | set(filedata.keys()), 623 files=set(ctx.files()) | set(filedata.keys()),
610 filectxfn=filectxfn, 624 filectxfn=filectxfn,
611 user=ctx.user(), 625 user=ctx.user(),
612 date=ctx.date(), 626 date=ctx.date(),
613 extra=ctx.extra(), 627 extra=extra,
614 branch=ctx.branch(), 628 branch=ctx.branch(),
615 editor=None) 629 editor=None)
616 sucnode = memctx.commit() 630 sucnode = memctx.commit()
617 prenode = ctx.node() 631 prenode = ctx.node()
618 if prenode == sucnode: 632 if prenode == sucnode: