[PATCH] histedit: handle obsolete commits unknown to histedit state (issue4800)

Kostia Balytskyi ikostia at fb.com
Mon Jan 18 12:02:22 UTC 2016


# HG changeset patch
# User Kostia Balytskyi <ikostia at fb.com>
# Date 1453118372 0
#      Mon Jan 18 11:59:32 2016 +0000
# Node ID 289562ec0ef6a732c54900842224a04932009d05
# Parent  443848eece189002c542339dc1cf84f49a94c824
histedit: handle obsolete commits unknown to histedit state (issue4800)

This fix takes sets of final and new commits from
histedit's state and replaces them with their successor sets.

diff --git a/hgext/histedit.py b/hgext/histedit.py
--- a/hgext/histedit.py
+++ b/hgext/histedit.py
@@ -1362,6 +1362,32 @@
     tmpnodes = allsuccs & replaced
     return newnodes, tmpnodes
 
+def nonobsoletesuccessors(repo, nodes):
+    """find all non-obsolete successors for each of the nodes
+
+    This fails if any of the nodes has more than one successor
+    set, e.g. if it diverged at some point and then became obsolete.
+    """
+    if not obsolete.isenabled(repo, obsolete.createmarkersopt):
+        # no obsoletion is enabled, no successors should exist
+        return nodes
+
+    result = []
+    for cl in nodes:
+        succset = obsolete.successorssets(repo, cl)
+        if len(succset) > 1:
+            msg = _("changeset %s split or divergent,"
+                    " cannot determine unique successor")
+            hint =_("solve the issue and run histedit --continue"
+                    " or abort with histedit --abort")
+            raise error.Abort(msg % node.hex(cl), hint=hint)
+        elif len(succset) == 1:
+            # non-divergent successor set
+            result += succset[0]
+        else:
+            # changeset has been pruned, nothing needs to be done
+            pass
+    return result
 
 def processreplacement(state):
     """process the list of replacements to return
@@ -1408,11 +1434,13 @@
     # turn `final` into list (topologically sorted)
     nm = state.repo.changelog.nodemap
     for prec, succs in final.items():
+        succs = nonobsoletesuccessors(state.repo, succs)
         final[prec] = sorted(succs, key=nm.get)
 
+    nonobsoletenew = nonobsoletesuccessors(state.repo, new)
     # computed topmost element (necessary for bookmark)
-    if new:
-        newtopmost = sorted(new, key=state.repo.changelog.rev)[-1]
+    if nonobsoletenew:
+        newtopmost = sorted(nonobsoletenew, key=state.repo.changelog.rev)[-1]
     elif not final:
         # Nothing rewritten at all. we won't need `newtopmost`
         # It is the same as `oldtopmost` and `processreplacement` know it
@@ -1422,7 +1450,7 @@
         r = state.repo.changelog.rev
         newtopmost = state.repo[sorted(final, key=r)[0]].p1().node()
 
-    return final, tmpnodes, new, newtopmost
+    return final, tmpnodes, nonobsoletenew, newtopmost
 
 def movebookmarks(ui, repo, mapping, oldtopmost, newtopmost):
     """Move bookmark from old to newly created node"""
diff --git a/tests/test-histedit-edit.t b/tests/test-histedit-edit.t
--- a/tests/test-histedit-edit.t
+++ b/tests/test-histedit-edit.t
@@ -477,3 +477,33 @@
   #  f, fold = use commit, but combine it with the one above
   #  r, roll = like fold, but discard this commit's description
   #
+
+Ensure that creating obsole revisions while editing commits does not break histedit
+
+  $ hg init boo
+  $ cd boo
+  $ echo a > aaaa
+  $ hg ci -Am a
+  adding aaaa
+  $ echo a > bbbb
+  $ echo a > cccc
+  $ echo a > cccc
+  $ hg ci -Am b
+  adding bbbb
+  adding cccc
+  $ echo a > dddd
+  $ hg ci -Am c
+  adding dddd
+  $ echo "pick `hg log -r -1 -T '{node|short}'`" > plan
+  $ echo "pick `hg log -r -3 -T '{node|short}'`" >> plan
+  $ echo "edit `hg log -r -2 -T '{node|short}'`" >> plan
+  $ hg histedit -qr 'all()' --commands plan
+  Editing \([0-9a-f]{12}\), you may commit or record as needed now. (re)
+  (hg histedit --continue to resume)
+  [1]
+  $ hg st
+  A bbbb
+  A cccc
+  ? plan
+  $ hg commit --amend bbbb
+  saved backup bundle to $TESTTMP/r0/boo/.hg/strip-backup/*-amend-backup.hg (glob)


More information about the Mercurial-devel mailing list