# 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() + 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