hgext3rd/evolve/rewind.py
changeset 3858 bb4f5ad63877
child 3859 6e3d844b56f2
--- /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