[PATCH evolve-ext] evolve: support hg continue and hg abort

Luke Granger-Brown lukegb at lukegb.com
Sun Mar 13 19:12:57 UTC 2022


# HG changeset patch
# User Luke Granger-Brown <hg at lukegb.com>
# Date 1647196527 0
#      Sun Mar 13 18:35:27 2022 +0000
# Node ID f1d7992cefc201ed029723b1666328d77ff7000e
# Parent  9e0aa8929206db3080cc434089978384077c03fe
evolve: support hg continue and hg abort

`hg evolve` and `hg pick` both already support `hg abort`, but neither of them
support `hg continue`, and `hg fixup` supports neither `hg continue` nor `hg
abort`.

To make the UX a little more consistent with Mercurial core, add support for
continue and abort to all three commands.

diff --git a/hgext3rd/evolve/__init__.py b/hgext3rd/evolve/__init__.py
--- a/hgext3rd/evolve/__init__.py
+++ b/hgext3rd/evolve/__init__.py
@@ -1167,13 +1167,17 @@ def setupevolveunfinished(ui):
         statemod.addunfinished(b'evolve', fname=b'evolvestate',
                                continueflag=True, stopflag=True,
                                statushint=_msg,
-                               abortfunc=evolvecmd.hgabortevolve)
+                               abortfunc=evolvecmd.hgabortevolve,
+                               continuefunc=evolvecmd.hgcontinueevolve)
         statemod.addunfinished(b'pick', fname=b'pickstate', continueflag=True,
-                               abortfunc=cmdrewrite.hgabortpick)
+                               abortfunc=cmdrewrite.hgabortpick,
+                               continuefunc=cmdrewrite.hgcontinuepick)
         _fixup_msg = _(b'To continue:    hg fixup --continue\n'
                        b'To abort:       hg fixup --abort\n')
         statemod.addunfinished(b'fixup', fname=b'fixup-state',
-                               continueflag=True, statushint=_fixup_msg)
+                               continueflag=True, statushint=_fixup_msg,
+                               abortfunc=cmdrewrite.hgabortfixup,
+                               continuefunc=cmdrewrite.hgcontinuefixup)
     else:
         # hg <= 5.0 (5f2f6912c9e6)
         estate = (b'evolvestate', False, False, _(b'evolve in progress'),
diff --git a/hgext3rd/evolve/cmdrewrite.py b/hgext3rd/evolve/cmdrewrite.py
--- a/hgext3rd/evolve/cmdrewrite.py
+++ b/hgext3rd/evolve/cmdrewrite.py
@@ -1403,28 +1403,41 @@ def cmdpick(ui, repo, *revs, **opts):
                 pickstate.save()
                 raise error.InterventionRequired(_(b"unresolved merge conflicts"
                                                    b" (see hg help resolve)"))
-        overrides = {(b'phases', b'new-commit'): origctx.phase()}
-        with repo.ui.configoverride(overrides, b'pick'):
-            newnode = repo.commit(text=origctx.description(),
-                                  user=origctx.user(),
-                                  date=origctx.date(), extra=origctx.extra())
-        repo.dirstate.setbranch(origctx.branch())
+        return _dopick(ui, repo, pickstate, origctx)
+
+def _dopick(ui, repo, pickstate, origctx):
+    """shared logic for performing or continuing a pick"""
+    overrides = {(b'phases', b'new-commit'): origctx.phase()}
+    with repo.ui.configoverride(overrides, b'pick'):
+        newnode = repo.commit(text=origctx.description(),
+                              user=origctx.user(),
+                              date=origctx.date(), extra=origctx.extra())
+    repo.dirstate.setbranch(origctx.branch())
 
-        if pickstate:
-            pickstate.delete()
-        if newnode is None:
-            replacements = {(origctx.node(),): []}
-        else:
-            newctx = repo[newnode]
-            replacements = {(origctx.node(),): [newctx.node()]}
-        compat.cleanupnodes(repo, replacements, operation=b"pick")
+    if pickstate:
+        pickstate.delete()
+    if newnode is None:
+        replacements = {(origctx.node(),): []}
+    else:
+        newctx = repo[newnode]
+        replacements = {(origctx.node(),): [newctx.node()]}
+    compat.cleanupnodes(repo, replacements, operation=b"pick")
 
-        if newnode is None:
-            ui.warn(_(b"note: picking %d:%s created no changes to commit\n") %
-                    (origctx.rev(), origctx))
-            return 0
+    if newnode is None:
+        ui.warn(_(b"note: picking %d:%s created no changes to commit\n") %
+                (origctx.rev(), origctx))
+        return 0
+
+    return 0
 
-        return 0
+def hgcontinuepick(ui, repo):
+    """logic to continue pick using 'hg continue'"""
+    with repo.wlock(), repo.lock():
+        pickstate = state.cmdstate(repo, path=b'pickstate')
+        pickstate.load()
+        orignode = pickstate[b'orignode']
+        origctx = repo[orignode]
+        return _dopick(ui, repo, pickstate, orignode, origctx)
 
 def abortpick(ui, repo, pickstate, abortcmd=False):
     """logic to abort pick"""
@@ -1576,6 +1589,13 @@ def continuefixup(ui, repo, fixup_state)
         compat.update(repo.unfiltered()[tempnode])
         return 0
 
+def hgcontinuefixup(ui, repo):
+    """logic for handling `hg continue' for fixup"""
+    with repo.wlock(), repo.lock():
+        fixup_state = state.cmdstate(repo, b'fixup-state')
+        fixup_state.load()
+        return continuefixup(ui, repo, fixup_state)
+
 def abortfixup(ui, repo, fixup_state):
     """logic for handling of `hg fixup --abort`"""
     with repo.wlock(), repo.lock():
@@ -1594,3 +1614,10 @@ def abortfixup(ui, repo, fixup_state):
     ui.status(_(b'working directory is now at %s\n') % pctx)
     fixup_state.delete()
     return 0
+
+def hgabortfixup(ui, repo):
+    """logic for handling `hg abort' for fixup"""
+    with repo.wlock(), repo.lock():
+        fixup_state = state.cmdstate(repo, b'fixup-state')
+        fixup_state.load()
+        return abortfixup(ui, repo, fixup_state)
diff --git a/hgext3rd/evolve/evolvecmd.py b/hgext3rd/evolve/evolvecmd.py
--- a/hgext3rd/evolve/evolvecmd.py
+++ b/hgext3rd/evolve/evolvecmd.py
@@ -2047,6 +2047,23 @@ def continueevolve(ui, repo, evolvestate
     progress.complete()
     return headnode
 
+def hgcontinueevolve(ui, repo):
+    """logic for continuing evolve using 'hg continue'"""
+    with repo.wlock(), repo.lock():
+        evolvestate = state.cmdstate(repo)
+        evolvestate.load()
+        headnode = continueevolve(ui, repo, evolvestate)
+        if evolvestate[b'command'] != b'evolve':
+            evolvestate.delete()
+            return
+        startnode = evolvestate[b'startnode']
+        shouldupdate = False
+        if b'update' in evolvestate:
+            shouldupdate = evolvestate[b'update']
+        evolvestate.delete()
+
+        _cleanup(ui, repo, startnode, shouldupdate, headnode)
+
 def _continuecontentdivergent(ui, repo, evolvestate, progresscb):
     """function to continue the interrupted content-divergence resolution."""
     tr = repo.transaction(b'evolve')
diff --git a/tests/test-abort.t b/tests/test-abort.t
new file mode 100644
--- /dev/null
+++ b/tests/test-abort.t
@@ -0,0 +1,116 @@
+Test for hg abort support
+
+  $ cat >> $HGRCPATH <<EOF
+  > [alias]
+  > glog = log -G -T "{rev}:{node|short} {desc}\n"
+  > glf = log -GT "{rev}: {desc} ({files})\n"
+  > [extensions]
+  > EOF
+  $ echo "evolve=$(echo $(dirname $TESTDIR))/hgext3rd/evolve/" >> $HGRCPATH
+
+  $ mkcommit() {
+  >    echo "$1" > "$1"
+  >    hg add "$1"
+  >    hg ci -m "add $1"
+  > }
+
+  $ hg init repo
+  $ cd repo
+
+  $ mkcommit a
+  $ mkcommit b
+  $ mkcommit c
+
+  $ hg glog
+  @  2:4538525df7e2 add c
+  |
+  o  1:7c3bad9141dc add b
+  |
+  o  0:1f0dee641bb7 add a
+  
+
+Test hg abort with pick
+
+  $ hg up 'desc("add a")'
+  0 files updated, 0 files merged, 2 files removed, 0 files unresolved
+
+  $ echo conflict > b
+  $ echo conflict > c
+  $ hg ci -Aqm "conflict b/c"
+  $ hg pick -r 'desc("add b")'
+  picking 1:7c3bad9141dc "add b"
+  merging b
+  warning: conflicts while merging b! (edit, then use 'hg resolve --mark')
+  unresolved merge conflicts (see hg help resolve)
+  [240]
+  $ echo merged > b
+  $ hg resolve --all --mark
+  (no more unresolved files)
+  continue: hg pick --continue
+  $ hg abort
+  pick aborted
+  working directory is now at 2edd1d9ca33f
+  $ hg glog
+  @  3:2edd1d9ca33f conflict b/c
+  |
+  | o  2:4538525df7e2 add c
+  | |
+  | o  1:7c3bad9141dc add b
+  |/
+  o  0:1f0dee641bb7 add a
+  
+Test hg abort with evolve
+
+  $ hg prune -r 'desc("add b")' -s 'desc("conflict b/c")'
+  1 changesets pruned
+  1 new orphan changesets
+  $ hg evolve
+  move:[2] add c
+  atop:[3] conflict b/c
+  merging c
+  warning: conflicts while merging c! (edit, then use 'hg resolve --mark')
+  unresolved merge conflicts
+  (see 'hg help evolve.interrupted')
+  [240]
+  $ hg abort
+  evolve aborted
+  working directory is now at 2edd1d9ca33f
+  $ hg glog
+  @  3:2edd1d9ca33f conflict b/c
+  |
+  | *  2:4538525df7e2 add c
+  | |
+  | x  1:7c3bad9141dc add b
+  |/
+  o  0:1f0dee641bb7 add a
+  
+
+Test hg abort with fixup
+
+  $ echo hello >> b
+  $ hg ci -Aqm "add hello b"
+  $ echo conflict >> b
+  $ hg fix-up -r 'desc("conflict b/c")'
+  merging b
+  warning: conflicts while merging b! (edit, then use 'hg resolve --mark')
+  unresolved merge conflicts
+  (see 'hg help evolve.interrupted')
+  [240]
+  $ hg resolve --all --mark
+  (no more unresolved files)
+  continue: hg fixup --continue
+  $ hg abort
+  fixup aborted
+  working directory is now at 821b31258e9b
+  $ hg glog
+  @  4:821b31258e9b add hello b
+  |
+  o  3:2edd1d9ca33f conflict b/c
+  |
+  | *  2:4538525df7e2 add c
+  | |
+  | x  1:7c3bad9141dc add b
+  |/
+  o  0:1f0dee641bb7 add a
+  
+
diff --git a/tests/test-continue.t b/tests/test-continue.t
new file mode 100644
--- /dev/null
+++ b/tests/test-continue.t
@@ -0,0 +1,121 @@
+Test for hg continue support
+
+  $ cat >> $HGRCPATH <<EOF
+  > [alias]
+  > glog = log -G -T "{rev}:{node|short} {desc}\n"
+  > glf = log -GT "{rev}: {desc} ({files})\n"
+  > [extensions]
+  > EOF
+  $ echo "evolve=$(echo $(dirname $TESTDIR))/hgext3rd/evolve/" >> $HGRCPATH
+
+  $ mkcommit() {
+  >    echo "$1" > "$1"
+  >    hg add "$1"
+  >    hg ci -m "add $1"
+  > }
+
+  $ hg init repo
+  $ cd repo
+
+  $ mkcommit a
+  $ mkcommit b
+  $ mkcommit c
+
+  $ hg glog
+  @  2:4538525df7e2 add c
+  |
+  o  1:7c3bad9141dc add b
+  |
+  o  0:1f0dee641bb7 add a
+  
+
+Test hg continue with pick
+
+  $ hg up 'desc("add a")'
+  0 files updated, 0 files merged, 2 files removed, 0 files unresolved
+
+  $ echo conflict > b
+  $ echo conflict > c
+  $ hg ci -Aqm "conflict b/c"
+  $ hg pick -r 'desc("add b")'
+  picking 1:7c3bad9141dc "add b"
+  merging b
+  warning: conflicts while merging b! (edit, then use 'hg resolve --mark')
+  unresolved merge conflicts (see hg help resolve)
+  [240]
+  $ echo merged > b
+  $ hg resolve --all --mark
+  (no more unresolved files)
+  continue: hg pick --continue
+  $ hg continue
+  1 new orphan changesets
+  $ hg glog
+  @  4:cb17a452ebae add b
+  |
+  o  3:2edd1d9ca33f conflict b/c
+  |
+  | *  2:4538525df7e2 add c
+  | |
+  | x  1:7c3bad9141dc add b
+  |/
+  o  0:1f0dee641bb7 add a
+  
+Test hg continue with evolve
+
+  $ hg evolve
+  move:[2] add c
+  atop:[4] add b
+  merging c
+  warning: conflicts while merging c! (edit, then use 'hg resolve --mark')
+  unresolved merge conflicts
+  (see 'hg help evolve.interrupted')
+  [240]
+  $ echo merged > c
+  $ hg resolve --all --mark
+  (no more unresolved files)
+  continue: hg evolve --continue
+  $ hg continue
+  evolving 2:4538525df7e2 "add c"
+  $ hg glog
+  o  5:ba2a3cf75863 add c
+  |
+  @  4:cb17a452ebae add b
+  |
+  o  3:2edd1d9ca33f conflict b/c
+  |
+  o  0:1f0dee641bb7 add a
+  
+
+Test hg continue with fixup
+
+  $ echo hello >> b
+  $ hg ci -Aqm "add hello b"
+  $ echo conflict >> b
+  $ hg fix-up -r 'desc("conflict b/c")'
+  merging b
+  warning: conflicts while merging b! (edit, then use 'hg resolve --mark')
+  unresolved merge conflicts
+  (see 'hg help evolve.interrupted')
+  [240]
+  $ hg resolve --all --mark
+  (no more unresolved files)
+  continue: hg fixup --continue
+  $ hg continue
+  evolving 7:879308e8b4ce "temporary fixup commit"
+  3 new orphan changesets
+  $ hg glog
+  o  9:fe8ff2cf1f6a conflict b/c
+  |
+  | @  7:879308e8b4ce temporary fixup commit
+  | |
+  | *  6:4202b8dd5346 add hello b
+  | |
+  | | *  5:ba2a3cf75863 add c
+  | |/
+  | *  4:cb17a452ebae add b
+  | |
+  | x  3:2edd1d9ca33f conflict b/c
+  |/
+  o  0:1f0dee641bb7 add a
+  
+
diff --git a/tests/test-evolve-progress.t b/tests/test-evolve-progress.t
--- a/tests/test-evolve-progress.t
+++ b/tests/test-evolve-progress.t
@@ -188,4 +188,82 @@ Test progress with --continue
   getting a
   updating: a 2/2 files (100.00%)
 
+Test progress with hg continue
+  $ hg co -q 'desc("first")'
+  $ echo conflict2 > a
+  $ hg amend -m 'first v5'
+  3 new orphan changesets
+  $ hg evolve --all --config progress.debug=yes --debug
+  evolve: 1/3 changesets (33.33%)
+  move:[11] second
+  atop:[14] first v5
+  hg rebase -r 60a86497fbfe -d 0cbc15354f23
+  evolve: 1/3 changesets (33.33%)
+  resolving manifests
+   branchmerge: True, force: True, partial: False
+   ancestor: f8d7d38c0a88, local: 0cbc15354f23+, remote: 60a86497fbfe
+  starting 4 threads for background file closing (?)
+   preserving a for resolve of a
+   a: versions differ -> m
+  updating: a 1/1 files (100.00%)
+  picked tool ':merge' for a (binary False symlink False changedelete False)
+  merging a
+  my a at 0cbc15354f23+ other a at 60a86497fbfe ancestor a at f8d7d38c0a88
+  warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
+  unresolved merge conflicts
+  (see 'hg help evolve.interrupted')
+  [240]
+  $ echo resolved > a
+  $ hg resolve -m a
+  (no more unresolved files)
+  continue: hg evolve --continue
+  $ hg continue --config progress.debug=yes --debug
+  evolving 11:60a86497fbfe "second"
+  committing files:
+  a
+  committing manifest
+  committing changelog
+  updating the branch cache
+  obscache is out of date
+  move:[12] third
+  atop:[15] second
+  hg rebase -r b2de95304e32 -d 8d7767a678b3
+  evolve: 2/3 changesets (66.67%)
+  resolving manifests
+   branchmerge: True, force: True, partial: False
+   ancestor: 60a86497fbfe, local: 8d7767a678b3+, remote: b2de95304e32
+   b: remote created -> g
+  getting b
+  updating: b 1/1 files (100.00%)
+  committing files:
+  b
+  committing manifest
+  committing changelog
+  move:[13] fourth
+  hg rebase -r c6e6fdb1d046 -d 97af772a84aa
+  evolve: 3/3 changesets (100.00%)
+  resolving manifests
+   branchmerge: True, force: True, partial: False
+   ancestor: b2de95304e32, local: 97af772a84aa+, remote: c6e6fdb1d046
+   b: remote is newer -> g
+  getting b
+  updating: b 1/1 files (100.00%)
+  committing files:
+  b
+  committing manifest
+  committing changelog
+  updating the branch cache
+  obscache is out of date
+  invalid branch cache (served): tip differs
+  invalid branch cache (served.hidden): tip differs
+  resolving manifests
+   branchmerge: False, force: False, partial: False
+   ancestor: 2a62ff95fd62, local: 2a62ff95fd62+, remote: 0cbc15354f23
+   b: other deleted -> r
+  removing b
+  updating: b 1/2 files (50.00%)
+   a: remote is newer -> g
+  getting a
+  updating: a 2/2 files (100.00%)
+
   $ cd ..




More information about the Mercurial-devel mailing list