evolve: refactor content-divergence resolution logic
> What is the case we are looking at?
This is about refactoring the part of content-div resolution logic where it
decides which cset should be relocated and where.
> What is a "topologicial common ancestors" vs a "greatest common ancestors"?
`tca` is an ancestor which we can decide/find by looking at the at graph
visually for e.g
```
c3(*) c4(*)
| |
c2(x) c1(x)
c5 | /
\ | /
c0
```
(c5 is the successor of c2 and c1)
now here,
`tca` of c3 and c4 is: c0
`gca` of c3 and c4 is: c5
> What is the new top-level logic/behavior that makes it better?
The old code had some unnecessary edge cases just because we were using `gca`,
since it can point to a revision that is not a topological ancestor.
For e.g see b779b40f996e
Eventually, the code around this was getting messy unnecessarily. So I looked
into it and found a simple and more robust approach.
And in new code, it is simple and straightforward (and easy to understand),
where we handle the following 4 cases when solving content-div:
1) when both are on the same parent
=> (no need to do anything special, and simply proceed)
2) both are on the different parent but a) `tca` is the parent of one of them
or b) there is no non-obsolete revision between `tca` and one of the
divergent cset.
=> (relocate one to the other side and proceed)
3) both are on different parents and `tca` is not the parent of any of them and
there is at least one non-obsolete cset between tca and both the divergent
cset i.e (tca::div1) and (tca::div2) both the ranges have at least one non-obs
revision.
=> (this is the case which we don't handle yet, but the solution would be to
prompt the user to choose an evolve destination.)
4) both are in the parent-child relation
=> (both are merged and new cset will be based on the successor of `tca`)
Changes in test-evolve-issue5958.t demonstrate that new code also covered case4
because in a resolution of "two divergent csets with parent-child relation"
there should be one cset as a result and no orphan revs (as you can see there
was an orphan before this patch).
$ cat >> $HGRCPATH <<EOF
> [defaults]
> amend=-d "0 0"
> [web]
> push_ssl = false
> allow_push = *
> [phases]
> publish = False
> [alias]
> qlog = log --template='{rev} - {node|short} {desc} ({phase})\n'
> [diff]
> git = 1
> unified = 0
> [extensions]
> EOF
$ echo "evolve=$(echo $(dirname $TESTDIR))/hgext3rd/evolve/" >> $HGRCPATH
$ mkcommit() {
> echo "$1" >> "$1"
> hg add "$1"
> hg ci -m "add $1"
> }
$ hg init local
$ hg init other
$ cd local
$ touch 1 2 3 4 5 6 7 8 9 0
$ hg add 1 2 3 4 5 6 7 8 9 0
$ mkcommit A
$ mkcommit B
$ mkcommit C
$ hg log -G
@ changeset: 2:829b19580856
| tag: tip
| user: test
| date: Thu Jan 01 00:00:00 1970 +0000
| summary: add C
|
o changeset: 1:97b8f02ab29e
| user: test
| date: Thu Jan 01 00:00:00 1970 +0000
| summary: add B
|
o changeset: 0:5d8dabd3961b
user: test
date: Thu Jan 01 00:00:00 1970 +0000
summary: add A
$ hg push ../other
pushing to ../other
searching for changes
adding changesets
adding manifests
adding file changes
added 3 changesets with 13 changes to 13 files
$ hg -R ../other verify
checking changesets
checking manifests
crosschecking files in changesets and manifests
checking files
checked 3 changesets with 13 changes to 13 files
$ mkcommit D
$ mkcommit E
$ hg up -q .^^
$ hg revert -r tip -a -q
$ hg ci -m 'coin' -q
$ hg log -G
@ changeset: 5:8313a6afebbb
| tag: tip
| parent: 2:829b19580856
| user: test
| date: Thu Jan 01 00:00:00 1970 +0000
| summary: coin
|
| o changeset: 4:076ec8ade1ac
| | user: test
| | date: Thu Jan 01 00:00:00 1970 +0000
| | summary: add E
| |
| o changeset: 3:824d9bb109f6
|/ user: test
| date: Thu Jan 01 00:00:00 1970 +0000
| summary: add D
|
o changeset: 2:829b19580856
| user: test
| date: Thu Jan 01 00:00:00 1970 +0000
| summary: add C
|
o changeset: 1:97b8f02ab29e
| user: test
| date: Thu Jan 01 00:00:00 1970 +0000
| summary: add B
|
o changeset: 0:5d8dabd3961b
user: test
date: Thu Jan 01 00:00:00 1970 +0000
summary: add A
$ hg prune --fold -n -1 -- -2 -3
2 changesets pruned
$ hg push ../other
pushing to ../other
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 2 changes to 2 files
2 new obsolescence markers
$ hg -R ../other verify
checking changesets
checking manifests
crosschecking files in changesets and manifests
checking files
checked 4 changesets with 15 changes to 15 files