# HG changeset patch # User Anton Shestakov # Date 1650565167 -14400 # Node ID 17ffdea0edbbf6702935866608bcc2700f3ee38b # Parent 4298ae0b966dabcaaf529c8824b07029b6b46945 evolve: look for split successors of the correct ancestor (issue6648) Consider two changesets, 1 and 2. 1 is split into two new changesets and 2 is pruned. If we stand on 2 and call hg evolve, _singlesuccessor() will traverse ancestors of wdp in search of a changeset with successors to update to (it will be 1, which was split). In case of a split, select_split_successor() gets control. The issue is this function didn't traverse ancestors, and instead tried to look up successors of the original changeset (i.e. 2 in our case, which was pruned). We can make select_split_successor() aware of _singlesuccessor() logic by using the changeset that actually has successors without traversing ancestors again. It's done by storing that changeset in MultipleSuccessorsError exception. diff -r 4298ae0b966d -r 17ffdea0edbb CHANGELOG --- a/CHANGELOG Sat Apr 09 20:49:43 2022 +0300 +++ b/CHANGELOG Thu Apr 21 22:19:27 2022 +0400 @@ -5,6 +5,8 @@ -------------------- * evolve: avoid updating working copy when --dry-run is given (issue6669) + * evolve: correctly pick successors of a split changeset when its child was + pruned (issue6648) * fixup: work correctly with bookmarks 10.5.0 -- 2022-02-23 diff -r 4298ae0b966d -r 17ffdea0edbb hgext3rd/evolve/evolvecmd.py --- a/hgext3rd/evolve/evolvecmd.py Sat Apr 09 20:49:43 2022 +0300 +++ b/hgext3rd/evolve/evolvecmd.py Thu Apr 21 22:19:27 2022 +0400 @@ -133,7 +133,7 @@ ui.write_err(msg) return (False, b".") if exc.splitflag: - splitsucc = utility.select_split_successor(ui, repo, obs) + splitsucc = utility.select_split_successor(ui, repo, repo[exc.rev]) if not splitsucc: msg = _(b"could not solve instability, " b"ambiguous destination: " @@ -1823,7 +1823,7 @@ ctx = repo[utility._singlesuccessor(repo, oldctx)] except utility.MultipleSuccessorsError as exc: if exc.splitflag: - splitsucc = utility.select_split_successor(ui, repo, oldctx) + splitsucc = utility.select_split_successor(ui, repo, repo[exc.rev]) if splitsucc: ctx = repo[splitsucc] else: diff -r 4298ae0b966d -r 17ffdea0edbb hgext3rd/evolve/utility.py --- a/hgext3rd/evolve/utility.py Sat Apr 09 20:49:43 2022 +0300 +++ b/hgext3rd/evolve/utility.py Thu Apr 21 22:19:27 2022 +0400 @@ -70,12 +70,14 @@ """Exception raised by _singlesuccessor() when multiple successor sets exists Attributes: + rev the revision that has multiple successor sets successorssets the list of successorssets to call to easily recover divergenceflag indicate that changeset has divergent rewriting splitflag indicate that changeset was split """ - def __init__(self, successorssets): + def __init__(self, rev, successorssets): + self.rev = rev self.successorssets = successorssets self.divergenceflag = len(successorssets) > 1 self.splitflag = len(successorssets[0]) > 1 @@ -124,7 +126,7 @@ obs = obs.p1() newer = obsutil.successorssets(repo, obs.node(), cache=cache) if len(newer) > 1 or len(newer[0]) > 1: - raise MultipleSuccessorsError(newer) + raise MultipleSuccessorsError(obs.rev(), newer) return repo[newer[0][0]].rev() diff -r 4298ae0b966d -r 17ffdea0edbb tests/test-check-sdist.t --- a/tests/test-check-sdist.t Sat Apr 09 20:49:43 2022 +0300 +++ b/tests/test-check-sdist.t Thu Apr 21 22:19:27 2022 +0400 @@ -35,7 +35,7 @@ $ tar -tzf hg-evolve-*.tar.gz | sed 's|^hg-evolve-[^/]*/||' | sort > files $ wc -l files - 356 files + 357 files $ fgrep debian files tests/test-check-debian.t $ fgrep __init__.py files diff -r 4298ae0b966d -r 17ffdea0edbb tests/test-evolve-issue6648.t --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-evolve-issue6648.t Thu Apr 21 22:19:27 2022 +0400 @@ -0,0 +1,87 @@ +Finding split successors for the correct ancestor (issue6648) +https://bz.mercurial-scm.org/show_bug.cgi?id=6648 + + $ . $TESTDIR/testlib/common.sh + + $ cat << EOF >> $HGRCPATH + > [extensions] + > evolve = + > EOF + + $ hg init issue6648 + $ cd issue6648 + + $ echo hi > foo + $ hg commit -qAm 'r0' + $ echo foo >> foo + $ echo foo >> foosplit + $ hg commit -qAm 'r1_splitme' + $ echo bar > bar + $ hg commit -qAm 'r2_obsoleteme' + $ echo baz > baz + $ hg commit -qAm 'r3' + + $ hg prune -r 2 + 1 changesets pruned + 1 new orphan changesets + $ hg split -r 1 --no-interactive foosplit + 1 files updated, 0 files merged, 3 files removed, 0 files unresolved + reverting foo + adding foosplit + created new head + no more changes to split + + $ hg update -r 2 + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + working directory parent is obsolete! (5c9b6cf2edc5) + (use 'hg evolve' to update to its parent successor) + + $ hg log -G + o changeset: 5:983ec6453b57 + | tag: tip + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: r1_splitme + | + o changeset: 4:9ca7a4996099 + | parent: 0:e9326971c0ba + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: r1_splitme + | + | * changeset: 3:c1e686af368d + | | user: test + | | date: Thu Jan 01 00:00:00 1970 +0000 + | | instability: orphan + | | summary: r3 + | | + | @ changeset: 2:5c9b6cf2edc5 + | | user: test + | | date: Thu Jan 01 00:00:00 1970 +0000 + | | obsolete: pruned using prune + | | summary: r2_obsoleteme + | | + | x changeset: 1:acdff8eea54c + |/ user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | obsolete: split using split as 4:9ca7a4996099, 5:983ec6453b57 + | summary: r1_splitme + | + o changeset: 0:e9326971c0ba + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: r0 + + +handling obsolete wdp works + + $ hg evolve + update:[5] r1_splitme + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + working directory is now at 983ec6453b57 + +stabilizing the orphan works + + $ hg evolve + move:[3] r3 + atop:[5] r1_splitme