Excerpts from Jun Wu's message of 2017-03-26 11:41:41 -0700: > # HG changeset patch > # User Jun Wu <qu...@fb.com> > # Date 1490552007 25200 > # Sun Mar 26 11:13:27 2017 -0700 > # Node ID b6766d75404fb8c5d26af016caa76f44b47ce156 > # Parent 336512ee2f947f07149e399a84927f9d820d2b62 > # Available At https://bitbucket.org/quark-zju/hg-draft > # hg pull https://bitbucket.org/quark-zju/hg-draft -r > b6766d75404f > histedit: revive commits on demand > > This is to address the "histedit --abort" issue mentioned in [1]. > > This solution is safer than what [1] proposed because it does not use unsafe > history writing ("strip"). The "strip" has caused several repo corruptions > in production. > > It's similar to what "hg touch" in mutable-history does [3], without using > random number. So it could be more reliably tested. > > Note that if we have obsolete marker versions, and obsoleted revisions are > revived automatically, as I proposed in [2], the "revive" hack will be no > longer necessary. > > [1]: > https://www.mercurial-scm.org/pipermail/mercurial-devel/2017-March/095572.html > > [2]: > https://www.mercurial-scm.org/pipermail/mercurial-devel/2017-March/094586.html > > [3]: > https://bitbucket.org/marmoute/mutable-history/src/c7da63d48/hgext3rd/evolve/__init__.py?at=default&fileviewer=file-view-default#__init__.py-2541 > > > diff --git a/hgext/histedit.py b/hgext/histedit.py > --- a/hgext/histedit.py > +++ b/hgext/histedit.py > @@ -507,4 +507,30 @@ class histeditaction(object): > return ctx, [(self.node, (ctx.node(),))] > > +def _revive(repo, n, updatedirstate=True): > + """given a node, make sure it's not obsoleted by adding noises > + > + If updatedirstate is True and new node is created, set dirstate parent to > + the new node. > + > + Return new node that is not obsoleted. > + """ > + unfi = repo.unfiltered() > + origctx = ctx = unfi[n] > + while ctx.obsolete(): > + extra = dict(ctx.extra()) > + revive = int(extra.get('__revive__', '0')) + 1 > + extra['__revive__'] = str(revive) > + newctx = context.metadataonlyctx(repo, ctx, date=ctx.date(), > + user=ctx.user(), extra=extra) > + newnode = newctx.commit() > + repo.ui.debug('node %s was revived as %s (revive=%d)\n' > + % (node.short(ctx.node()), node.short(newnode), > revive)) > + ctx = unfi[newnode] > + if origctx != ctx and updatedirstate: > + repo.dirstate.beginparentchange() > + repo.dirstate.setparents(ctx.node()) > + repo.dirstate.endparentchange() > + return ctx.node() > +
Maybe this should be in core commit function as it should also applies to cases like "graft" etc. > def commitfuncfor(repo, src): > """Build a commit function for the replacement of <src> > @@ -524,5 +550,6 @@ def commitfuncfor(repo, src): > extra['histedit_source'] = src.hex() > kwargs['extra'] = extra > - return repo.commit(**kwargs) > + newnode = repo.commit(**kwargs) > + return _revive(repo, newnode) > return commitfunc > > diff --git a/tests/test-histedit-obsolete.t b/tests/test-histedit-obsolete.t > --- a/tests/test-histedit-obsolete.t > +++ b/tests/test-histedit-obsolete.t > @@ -552,5 +552,5 @@ Abort > Re-run a similar histedit plan > > - $ hg histedit -r 'b449568bf7fc' --commands - << EOF > + $ hg histedit --debug -r 'b449568bf7fc' --commands - << EOF | grep revive > > pick b449568bf7fc 13 f > > pick 7395e1ff83bd 15 h > @@ -560,4 +560,21 @@ Re-run a similar histedit plan > > pick ee118ab9fa44 18 k > > EOF > - abort: 00changelog.i@4dc06258baa667440b8af3c849ddd9c10a4b0cb8: filtered > node! > - [255] > + node 4dc06258baa6 was revived as 7bd549b16383 (revive=1) > + > + $ hg log -G > + @ 27:563ef4a77b72 (secret) k > + | > + o 26:f371aa2c4158 (secret) j > + | > + o 25:5bfeafa73282 (secret) i > + | > + o 24:c53c6695c868 (draft) g > + | > + o 23:7bd549b16383 (draft) h > + | > + o 13:b449568bf7fc (draft) f > + | > + o 12:40db8afa467b (public) c > + | > + o 0:cb9a9f314b8b (public) a > + _______________________________________________ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel