rewind: add a proto version of the command
This first version focus on rewinding a single revision without care for the
consequence.
--- a/hgext3rd/evolve/__init__.py Fri Jun 29 16:51:56 2018 +0200
+++ b/hgext3rd/evolve/__init__.py Sat Jun 16 23:11:52 2018 +0200
@@ -309,6 +309,7 @@
obscache,
obsexchange,
obshistory,
+ rewind,
rewriteutil,
safeguard,
templatekw,
@@ -362,6 +363,7 @@
eh.merge(templatekw.eh)
eh.merge(compat.eh)
eh.merge(cmdrewrite.eh)
+eh.merge(rewind.eh)
uisetup = eh.final_uisetup
extsetup = eh.final_extsetup
reposetup = eh.final_reposetup
--- /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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-rewind.t Sat Jun 16 23:11:52 2018 +0200
@@ -0,0 +1,225 @@
+This test file test the rewind command in several situations.
+
+Global setup
+============
+
+ $ . $TESTDIR/testlib/common.sh
+ $ cat >> $HGRCPATH <<EOF
+ > [ui]
+ > interactive = true
+ > [phases]
+ > publish=False
+ > [extensions]
+ > evolve =
+ > EOF
+
+ $ hg init rewind-testing-base
+ $ cd rewind-testing-base
+ $ echo a > root
+ $ hg add root
+ $ hg ci -m 'c_ROOT'
+ $ echo a > A
+ $ hg add A
+ $ hg ci -m 'c_A0'
+ $ echo a > B
+ $ hg add B
+ $ hg ci -m 'c_B0'
+ $ hg log -G
+ @ changeset: 2:7e594302a05d
+ | tag: tip
+ | user: test
+ | date: Thu Jan 01 00:00:00 1970 +0000
+ | summary: c_B0
+ |
+ o changeset: 1:579f120ba918
+ | user: test
+ | date: Thu Jan 01 00:00:00 1970 +0000
+ | summary: c_A0
+ |
+ o changeset: 0:eba9c2249fe7
+ user: test
+ date: Thu Jan 01 00:00:00 1970 +0000
+ summary: c_ROOT
+
+
+ $ cd ..
+
+Test rewinding to single changesets
+====================================
+
+ $ hg clone rewind-testing-base rewind-testing-simple-prune
+ updating to branch default
+ 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ $ cd rewind-testing-simple-prune
+
+Prune changeset unrelated to the working copy
+---------------------------------------------
+
+Setup
+`````
+
+Update to an unrelated changeset
+
+ $ hg up 'desc("c_ROOT")'
+ 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
+
+Prune the head
+
+ $ hg prune -r 'desc("c_B0")'
+ 1 changesets pruned
+ $ hg log -G
+ o changeset: 1:579f120ba918
+ | tag: tip
+ | user: test
+ | date: Thu Jan 01 00:00:00 1970 +0000
+ | summary: c_A0
+ |
+ @ changeset: 0:eba9c2249fe7
+ user: test
+ date: Thu Jan 01 00:00:00 1970 +0000
+ summary: c_ROOT
+
+
+Actual rewind
+`````````````
+
+ $ hg rewind --hidden --to 'desc("c_B0")'
+ $ hg debugobsolete
+ 7e594302a05d3769b27be88fc3cdfd39d7498498 0 {579f120ba91885449adc92eedf48ef3569742cee} (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '0', 'operation': 'prune', 'user': 'test'}
+ 7e594302a05d3769b27be88fc3cdfd39d7498498 073989a581cf430a844192364fa37606357cbbc2 4 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '2', 'operation': 'rewind', 'user': 'test'}
+ $ hg obslog -r 'desc("c_B0")'
+ o 073989a581cf (3) c_B0
+ |
+ x 7e594302a05d (2) c_B0
+ pruned using prune by test (Thu Jan 01 00:00:00 1970 +0000)
+ rewritten(meta) as 073989a581cf using rewind by test (Thu Jan 01 00:00:00 1970 +0000)
+
+ $ hg log -G
+ o changeset: 3:073989a581cf
+ | tag: tip
+ | parent: 1:579f120ba918
+ | user: test
+ | date: Thu Jan 01 00:00:00 1970 +0000
+ | summary: c_B0
+ |
+ o changeset: 1:579f120ba918
+ | user: test
+ | date: Thu Jan 01 00:00:00 1970 +0000
+ | summary: c_A0
+ |
+ @ changeset: 0:eba9c2249fe7
+ user: test
+ date: Thu Jan 01 00:00:00 1970 +0000
+ summary: c_ROOT
+
+XXX-TODO: fix the obsfate from "meta-changed as 3" to "identical" or something.
+
+ $ hg log -G --hidden
+ o changeset: 3:073989a581cf
+ | tag: tip
+ | parent: 1:579f120ba918
+ | user: test
+ | date: Thu Jan 01 00:00:00 1970 +0000
+ | summary: c_B0
+ |
+ | x changeset: 2:7e594302a05d
+ |/ user: test
+ | date: Thu Jan 01 00:00:00 1970 +0000
+ | obsolete: meta-changed using rewind as 3:073989a581cf
+ | summary: c_B0
+ |
+ o changeset: 1:579f120ba918
+ | user: test
+ | date: Thu Jan 01 00:00:00 1970 +0000
+ | summary: c_A0
+ |
+ @ changeset: 0:eba9c2249fe7
+ user: test
+ date: Thu Jan 01 00:00:00 1970 +0000
+ summary: c_ROOT
+
+
+Other independant rewind create a different revision
+----------------------------------------------------------
+
+setup
+`````
+
+note: we use "default-date" to make it a "different rewind"
+
+ $ echo '[devel]' >> $HGRCPATH
+ $ echo 'default-date = 1 0' >> $HGRCPATH
+
+Actual rewind
+`````````````
+
+ $ hg prune 'desc("c_B0")'
+ 1 changesets pruned
+ $ hg rewind --hidden --to 'min(desc("c_B0"))'
+ $ hg debugobsolete
+ 7e594302a05d3769b27be88fc3cdfd39d7498498 0 {579f120ba91885449adc92eedf48ef3569742cee} (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '0', 'operation': 'prune', 'user': 'test'}
+ 7e594302a05d3769b27be88fc3cdfd39d7498498 073989a581cf430a844192364fa37606357cbbc2 4 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '2', 'operation': 'rewind', 'user': 'test'}
+ 073989a581cf430a844192364fa37606357cbbc2 0 {579f120ba91885449adc92eedf48ef3569742cee} (Thu Jan 01 00:00:01 1970 +0000) {'ef1': '0', 'operation': 'prune', 'user': 'test'}
+ 7e594302a05d3769b27be88fc3cdfd39d7498498 48acf2c0d9c8961859ce9a913671eb2adc9b057b 4 (Thu Jan 01 00:00:01 1970 +0000) {'ef1': '34', 'operation': 'rewind', 'user': 'test'}
+ $ hg obslog -r 'desc("c_B0")' --all
+ x 073989a581cf (3) c_B0
+ | pruned using prune by test (Thu Jan 01 00:00:01 1970 +0000)
+ |
+ | o 48acf2c0d9c8 (4) c_B0
+ |/
+ x 7e594302a05d (2) c_B0
+ pruned using prune by test (Thu Jan 01 00:00:00 1970 +0000)
+ rewritten(meta) as 073989a581cf using rewind by test (Thu Jan 01 00:00:00 1970 +0000)
+ rewritten(meta, date) as 48acf2c0d9c8 using rewind by test (Thu Jan 01 00:00:01 1970 +0000)
+
+ $ hg log -G
+ o changeset: 4:48acf2c0d9c8
+ | tag: tip
+ | parent: 1:579f120ba918
+ | user: test
+ | date: Thu Jan 01 00:00:01 1970 +0000
+ | summary: c_B0
+ |
+ o changeset: 1:579f120ba918
+ | user: test
+ | date: Thu Jan 01 00:00:00 1970 +0000
+ | summary: c_A0
+ |
+ @ changeset: 0:eba9c2249fe7
+ user: test
+ date: Thu Jan 01 00:00:00 1970 +0000
+ summary: c_ROOT
+
+ $ hg log -G --hidden
+ o changeset: 4:48acf2c0d9c8
+ | tag: tip
+ | parent: 1:579f120ba918
+ | user: test
+ | date: Thu Jan 01 00:00:01 1970 +0000
+ | summary: c_B0
+ |
+ | x changeset: 3:073989a581cf
+ |/ parent: 1:579f120ba918
+ | user: test
+ | date: Thu Jan 01 00:00:00 1970 +0000
+ | obsolete: pruned using prune
+ | summary: c_B0
+ |
+ | x changeset: 2:7e594302a05d
+ |/ user: test
+ | date: Thu Jan 01 00:00:00 1970 +0000
+ | obsolete: rewritten using rewind as 4:48acf2c0d9c8
+ | obsolete: meta-changed using rewind as 3:073989a581cf
+ | summary: c_B0
+ |
+ o changeset: 1:579f120ba918
+ | user: test
+ | date: Thu Jan 01 00:00:00 1970 +0000
+ | summary: c_A0
+ |
+ @ changeset: 0:eba9c2249fe7
+ user: test
+ date: Thu Jan 01 00:00:00 1970 +0000
+ summary: c_ROOT
+
+ $ cd ..