changeset 3858:bb4f5ad63877

rewind: add a proto version of the command This first version focus on rewinding a single revision without care for the consequence.
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Sat, 16 Jun 2018 23:11:52 +0200
parents 9672de8055cd
children 6e3d844b56f2
files hgext3rd/evolve/__init__.py hgext3rd/evolve/rewind.py tests/test-rewind.t
diffstat 3 files changed, 299 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- 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 ..