--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hgext3rd/evolve/rewind.py Sat Jun 16 23:11:52 2018 +0200
@@ -0,0 +1,72 @@
+from __future__ import absolute_import
+
+import hashlib
+
+from mercurial import (
+ error,
+ obsolete,
+ scmutil,
+)
+
+from mercurial.i18n import _
+
+from . import (
+ exthelper,
+ rewriteutil,
+ compat,
+)
+
+eh = exthelper.exthelper()
+
+# flag in obsolescence markers to link to identical version
+identicalflag = 4
+
+@eh.command(
+ '^rewind',
+ [('', 'to', [], _("rewind to these revision")),
+ ],
+ _(''))
+def rewind(ui, repo, **opts):
+ """rewind stacks of changeset to a previous content
+ """
+ unfi = repo.unfiltered()
+
+ if not opts.get('to'):
+ raise error.Abort('no revision to rewind to')
+
+ rewinded = scmutil.revrange(repo, opts.get('to'))
+
+ with repo.wlock(), repo.lock():
+ # Check that we can rewind these changesets
+ with repo.transaction('rewind'):
+ for rev in rewinded:
+ _revive_revision(unfi, rev)
+
+def _revive_revision(unfi, rev):
+ """rewind a single revision rev.
+ """
+ ctx = unfi[rev]
+ extra = ctx.extra().copy()
+ # rewind hash should be unique over multiple rewind.
+ user = unfi.ui.config('devel', 'user.obsmarker')
+ if not user:
+ user = unfi.ui.username()
+ date = unfi.ui.configdate('devel', 'default-date')
+ if date is None:
+ date = compat.makedate()
+ noise = "%s\0%s\0%d\0%d" % (ctx.node(), user, date[0], date[1])
+ extra['__rewind-hash__'] = hashlib.sha256(noise).hexdigest()
+
+ p1 = ctx.p1().node()
+ p2 = ctx.p2().node()
+
+ extradict = {'extra': extra}
+
+ new, unusedvariable = rewriteutil.rewrite(unfi, ctx, [], ctx,
+ [p1, p2],
+ commitopts=extradict)
+
+ obsolete.createmarkers(unfi, [(ctx, (unfi[new],))],
+ flag=identicalflag, operation='rewind')
+
+ return new