changeset 4383:3343eac099ec

evolve: add logic to resolve content-divergence with a public cset Public content-divergence is the divergence where a cset is content-divergent with a public cset. To solve public divergence: 1) perform content-divergent resolution 2) resultant node is phase divergent 3) perform phase divergence resolution It is the intial logic to solve public divergence. Next patches will be the covering the cases of: 1) relocation: when we need to relocate to node 2) continue: to add this resolution in case of --continue 3) the case when content-divergence resolution gives a result similar to public cset. Added test-evolve-public-content-divergent.t reflect the added behaviour.
author Sushil khanchi <sushilkhanchi97@gmail.com>
date Mon, 21 Jan 2019 23:06:34 +0530
parents e6ba7e324015
children 8993fd4805d0
files hgext3rd/evolve/evolvecmd.py tests/test-evolve-public-content-divergent.t
diffstat 2 files changed, 147 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/hgext3rd/evolve/evolvecmd.py	Sun Jan 13 19:33:19 2019 +0530
+++ b/hgext3rd/evolve/evolvecmd.py	Mon Jan 21 23:06:34 2019 +0530
@@ -375,6 +375,12 @@
     evolvestate['other-divergent'] = other.node()
     evolvestate['base'] = base.node()
 
+    # haspubdiv: to keep track if we are solving public content-divergence
+    haspubdiv = False
+    if not other.mutable():
+        haspubdiv = True
+        publicdiv = other
+        evolvestate['public-divergent'] = other.node()
     # we don't handle merge content-divergent changesets yet
     if len(other.parents()) > 1:
         msg = _("skipping %s: %s changeset can't be "
@@ -492,8 +498,22 @@
 
     _mergecontentdivergents(repo, progresscb, divergent, other, base,
                             evolvestate)
-    return _completecontentdivergent(ui, repo, progresscb, divergent, other,
-                                     base, evolvestate)
+    res, newnode = _completecontentdivergent(ui, repo, progresscb, divergent,
+                                             other, base, evolvestate)
+    if not haspubdiv:
+        return (res, newnode)
+    else:
+        # when we have content-divergence with a public cset: after completing
+        # content divergence resolution the resulting node will be phase
+        # divergent with that same public cset.
+        # here newnode is phase divergent, lets resolve this divergence.
+        if not res:
+            return (res, newnode)
+
+        prec = publicdiv
+        bumped = repo[newnode]
+        return _resolvephasedivergent(ui, repo, prec=prec, bumped=bumped,
+                                      tmpctx=bumped)
 
 def _mergecontentdivergents(repo, progresscb, divergent, other, base,
                             evolvestate):
@@ -535,6 +555,13 @@
     # whether to store the obsmarker in the evolvestate
     storemarker = False
     resparent = evolvestate['resolutionparent']
+
+    # whether we are solving public divergence
+    haspubdiv = False
+    if evolvestate.get('public-divergent'):
+        haspubdiv = True
+        npublicdiv = evolvestate['public-divergent']
+        publicdiv = repo[npublicdiv]
     try:
         with repo.dirstate.parentchange():
             repo.dirstate.setparents(resparent, nodemod.nullid)
@@ -564,10 +591,17 @@
             new = repo[newnode]
             newnode = new.node()
             hg.updaterepo(repo, new.rev(), False)
-            obsolete.createmarkers(repo, [(divergent, (new,))], operation='evolve')
+            if haspubdiv and publicdiv == divergent:
+                bypassphase(repo, (divergent, new), operation='evolve')
+            else:
+                obsolete.createmarkers(repo, [(divergent, (new,))],
+                                       operation='evolve')
 
         # creating markers and moving phases post-resolution
-        obsolete.createmarkers(repo, [(other, (new,))], operation='evolve')
+        if haspubdiv and publicdiv == other:
+            bypassphase(repo, (other, new), operation='evolve')
+        else:
+            obsolete.createmarkers(repo, [(other, (new,))], operation='evolve')
         if storemarker:
             # storing the marker in the evolvestate
             # we just store the precursors and successor pair for now, we might
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-evolve-public-content-divergent.t	Mon Jan 21 23:06:34 2019 +0530
@@ -0,0 +1,109 @@
+Test for handling of content divergence with public cset using `hg evolve`
+==========================================================================
+
+Setup
+=====
+  $ cat >> $HGRCPATH <<EOF
+  > [alias]
+  > glog = log -GT "{rev}:{node|short} {desc|firstline}\n {phase} {troubles}\n\n"
+  > [phases]
+  > publish = False
+  > [extensions]
+  > rebase =
+  > EOF
+  $ echo "evolve=$(echo $(dirname $TESTDIR))/hgext3rd/evolve/" >> $HGRCPATH
+
+Testing the case when both divergent cset are on the same parent and no-conflict in merging:
+-------------------------------------------------------------------------------------
+
+Prepare the repository:
+
+  $ hg init pubdiv
+  $ cd pubdiv
+  $ for ch in a b; do
+  >   echo $ch > $ch;
+  >   hg ci -Aqm "added "$ch;
+  > done;
+  $ hg glog
+  @  1:5f6d8a4bf34a added b
+  |   draft
+  |
+  o  0:9092f1db7931 added a
+      draft
+  
+
+Make an amend and change phase to public:
+
+  $ sed -i "1 i I am first" b
+  $ hg amend
+  $ hg phase --public
+
+Amend again to create a cset divergent to public one:
+
+  $ hg up 1 --hidden -q
+  updated to hidden changeset 5f6d8a4bf34a
+  (hidden revision '5f6d8a4bf34a' was rewritten as: 44f360db368f)
+  working directory parent is obsolete! (5f6d8a4bf34a)
+
+  $ echo "I am second" >> b
+  $ hg ci --amend -m "updated b"
+  1 new content-divergent changesets
+
+  $ hg glog
+  @  3:dcdaf152280a updated b
+  |   draft content-divergent
+  |
+  | o  2:44f360db368f added b
+  |/    public
+  |
+  o  0:9092f1db7931 added a
+      public
+  
+
+Lets resolve the public content-divergence:
+
+  $ hg evolve --content-divergent
+  merge:[3] updated b
+  with: [2] added b
+  base: [1] added b
+  merging "other" content-divergent changeset '44f360db368f'
+  merging b
+  0 files updated, 1 files merged, 0 files removed, 0 files unresolved
+  computing new diff
+  committed as c1aa9cfb6cf8
+  working directory is now at c1aa9cfb6cf8
+
+Following graph log shows that it correctly merged the two divergent csets:
+
+  $ hg glog -p
+  @  5:c1aa9cfb6cf8 phase-divergent update to 44f360db368f:
+  |   draft
+  |
+  |  diff -r 44f360db368f -r c1aa9cfb6cf8 b
+  |  --- a/b	Thu Jan 01 00:00:00 1970 +0000
+  |  +++ b/b	Thu Jan 01 00:00:00 1970 +0000
+  |  @@ -1,2 +1,3 @@
+  |   I am first
+  |   b
+  |  +I am second
+  |
+  o  2:44f360db368f added b
+  |   public
+  |
+  |  diff -r 9092f1db7931 -r 44f360db368f b
+  |  --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+  |  +++ b/b	Thu Jan 01 00:00:00 1970 +0000
+  |  @@ -0,0 +1,2 @@
+  |  +I am first
+  |  +b
+  |
+  o  0:9092f1db7931 added a
+      public
+  
+     diff -r 000000000000 -r 9092f1db7931 a
+     --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+     +++ b/a	Thu Jan 01 00:00:00 1970 +0000
+     @@ -0,0 +1,1 @@
+     +a
+  
+  $ hg evolve -l