[PATCH] histedit: handle obsolete commits unknown to histedit state
Kostia Balytskyi
ikostia at fb.com
Thu Jan 14 19:19:41 UTC 2016
# HG changeset patch
# User Kostia Balytskyi <ikostia at fb.com>
# Date 1452727707 28800
# Wed Jan 13 15:28:27 2016 -0800
# Node ID 5a36c6cdb955ffb1f8b4c2f26d369b3d331c0492
# Parent 443848eece189002c542339dc1cf84f49a94c824
histedit: handle obsolete commits unknown to histedit state
This fix is intended to solve issue4800. It 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,27 @@
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.
+ """
+ result = []
+ for cl in nodes:
+ succset = obsolete.successorssets(repo, cl)
+ if len(succset) > 1:
+ # successorsset for diverged changeset
+ # weird situation that should not happen while
+ # editing history, indicates an error
+ msg = _("diverged obsolete changeset found " +
+ "among nodes in histedit: %s")
+ raise error.Abort(msg % node.hex(cl))
+ elif len(succset) == 1:
+ # non-divergent successor set
+ result += succset[0]
+ # else: changeset has been pruned, nothing needs to be done
+ return result
def processreplacement(state):
"""process the list of replacements to return
@@ -1408,11 +1429,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)
# computed topmost element (necessary for bookmark)
if new:
- newtopmost = sorted(new, key=state.repo.changelog.rev)[-1]
+ nonobsoletenew = nonobsoletesuccessors(state.repo, new)
+ 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 +1445,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"""
More information about the Mercurial-devel
mailing list