evolve: add pre-check logic for content-divergence in rewriteutil.precheck()
authorSushil khanchi <sushilkhanchi97@gmail.com>
Mon, 04 Nov 2019 01:30:50 +0530
changeset 5079 1f92a6aa40d6
parent 5078 66f01dd79f5d
child 5083 e50f4fc6cc6d
child 5244 670e1c2b6844
evolve: add pre-check logic for content-divergence in rewriteutil.precheck() For now, pre-check will abort if rewriting a rev create divergence (and config experimental.evolution.allowdivergence is not set to True). But this behaviour can be improved where instead of abort maybe we can confirm the user to either proceed with divergence or some other options depends on what command user is running. Changes in test file are used to overrides the pre-check for testing purpose (using experimental.evolution.allowdivergence=yes).
CHANGELOG
hgext3rd/evolve/rewriteutil.py
tests/test-amend.t
tests/test-evolve-content-divergent-basic.t
tests/test-evolve-content-divergent-corner-cases.t
tests/test-evolve-content-divergent-first-changeset.t
tests/test-evolve-content-divergent-interrupted.t
tests/test-evolve-content-divergent-meta.t
tests/test-evolve-obshistory-content-divergent.t
tests/test-evolve-order.t
tests/test-evolve-public-content-divergent-corner-cases.t
tests/test-evolve-public-content-divergent-discard.t
tests/test-evolve-public-content-divergent-main.t
tests/test-evolve-templates.t
tests/test-fold.t
tests/test-topic-stack-complex.t
tests/test-touch.t
tests/test-uncommit.t
--- a/CHANGELOG	Wed Jan 01 21:36:21 2020 +0530
+++ b/CHANGELOG	Mon Nov 04 01:30:50 2019 +0530
@@ -11,6 +11,8 @@
   * obslog: make templatable
   * compat: cleanup some compatibility code for mercurial < 4.5
   * compat: compatibility with some changes of the upcoming Mercurial 5.3
+  * evolve: add content divergence checking to the standard pre-rewrite check,
+  * evolve: improve the message associated with content divergence.
 
 9.2.2 - in progress
 -------------------
--- a/hgext3rd/evolve/rewriteutil.py	Wed Jan 01 21:36:21 2020 +0530
+++ b/hgext3rd/evolve/rewriteutil.py	Mon Nov 04 01:30:50 2019 +0530
@@ -77,6 +77,31 @@
         msg %= (action, len(newunstable))
         hint = _(b"see 'hg help evolution.instability'")
         raise error.Abort(msg, hint=hint)
+    divrisk = revs_hascontentdivrisk(repo, revs)
+    allowdivergence = repo.ui.configbool(b'experimental',
+                                         b'evolution.allowdivergence')
+    if divrisk and not allowdivergence:
+        localdiv = repo[divrisk[0]]
+        otherdiv, base = repo[divrisk[1][0]], repo[divrisk[1][1]]
+        msg = _(b"%s of %s creates content-divergence "
+                b"with %s") % (action, localdiv, otherdiv)
+        if localdiv.rev() != base.rev():
+            msg += _(b', from %s') % base
+        hint = _(b"add --verbose for details or see "
+                 b"'hg help evolution.instability'")
+        if repo.ui.verbose:
+            if localdiv.rev() != base.rev():
+                msg += _(b'\n    changeset %s is an evolution of '
+                         b'changeset %s') % (localdiv, base)
+            msg += _(b'\n    changeset %s already have a successors as '
+                     b'changeset %s\n'
+                     b'    rewriting changeset %s would create '
+                     b'"content-divergence"\n'
+                     b'    set experimental.evolution.allowdivergence=True to '
+                     b'overwrite this check') % (base, otherdiv, localdiv)
+            hint = _(b"see 'hg help evolution.instability' for details "
+                     b"on content-divergence")
+        raise error.Abort(msg, hint=hint)
 
 def bookmarksupdater(repo, oldid, tr):
     """Return a callable update(newid) updating the current bookmark
@@ -89,6 +114,14 @@
             repo._bookmarks.applychanges(repo, tr, bmchanges)
     return updatebookmarks
 
+def revs_hascontentdivrisk(repo, revs):
+    obsrevs = repo.revs(b'%ld and obsolete()', revs)
+    for r in obsrevs:
+        div = precheck_contentdiv(repo, repo[r])
+        if div:
+            return [r, div]
+    return []
+
 def disallowednewunstable(repo, revs):
     """Check that editing <revs> will not create disallowed unstable
 
@@ -257,10 +290,12 @@
         lockmod.release(tr, lock, wlock)
 
 def precheck_contentdiv(repo, ctx):
-    """logic to check if rewriting an obsolete cset will create divergence"""
+    """return divergent revision if rewriting an obsolete cset (ctx) will
+    create divergence"""
     # We need to check two cases that can cause divergence:
     # case 1: the rev being rewritten has a non-obsolete successor (easily
     #     detected by successorssets)
+    divergent = [] # contains [divergent_cset, common_precursor]
     sset = obsutil.successorssets(repo, ctx.node())
     nodivergencerisk = (len(sset) == 0
                         or (len(sset) == 1
@@ -271,6 +306,13 @@
         # case 2: one of the precursors of the rev being revived has a
         #     non-obsolete successor (we need divergentsets for this)
         from . import evolvecmd
-        if evolvecmd.divergentsets(repo, ctx):
-            nodivergencerisk = False
-    return not nodivergencerisk
+        divsets = evolvecmd.divergentsets(repo, ctx)
+        if divsets:
+            nsuccset = divsets[0][b'divergentnodes']
+            divergent.append(nsuccset[0])
+            prec = divsets[0][b'commonprecursor']
+            divergent.append(prec)
+    else:
+        divergent.append(sset[0][0])
+        divergent.append(ctx.node())
+    return divergent
--- a/tests/test-amend.t	Wed Jan 01 21:36:21 2020 +0530
+++ b/tests/test-amend.t	Mon Nov 04 01:30:50 2019 +0530
@@ -121,6 +121,9 @@
   update: (current)
   phases: 3 draft
 
+setting the user after we have performed the test with no username
+  $ HGUSER=test
+
 Check the help
   $ hg amend -h
   hg amend [OPTION]... [FILE]...
@@ -170,3 +173,63 @@
   $ hg amend --patch --extract
   abort: cannot use both --patch and --extract
   [255]
+
+  $ cd ..
+
+Check the pre-check logic for content-divergence
+  $ hg init precheckrepo
+  $ cd precheckrepo
+  $ echo a > a
+  $ hg ci -Am "added a"
+  adding a
+  $ echo newchanges > a
+  $ hg amend
+  $ hg up 0 --hidden -q
+  updated to hidden changeset 9092f1db7931
+  (hidden revision '9092f1db7931' was rewritten as: aafaf407b00d)
+  working directory parent is obsolete! (9092f1db7931)
+
+when rewritting an already rewritten changeset (i.e cset being rewritten will
+be the base of divergence)
+  $ hg amend -m "i am gonna create divergence"
+  abort: amend of 9092f1db7931 creates content-divergence with aafaf407b00d
+  (add --verbose for details or see 'hg help evolution.instability')
+  [255]
+  $ hg amend -m "i am gonna create divergence" --verbose
+  abort: amend of 9092f1db7931 creates content-divergence with aafaf407b00d
+      changeset 9092f1db7931 already have a successors as changeset aafaf407b00d
+      rewriting changeset 9092f1db7931 would create "content-divergence"
+      set experimental.evolution.allowdivergence=True to overwrite this check
+  (see 'hg help evolution.instability' for details on content-divergence)
+  [255]
+
+when rewritting a cset which has a predecessor with non-obsolete successor
+
+to prepare the repo
+1) create content-divergence
+2) remove divergence by pruning one of the divergent cset
+  $ echo edited_a > a
+  $ hg ci -m "edited a"
+  1 new orphan changesets
+  $ hg debugobsolete $(hg id -ir 0 --debug) $(hg id -ir 2 --debug)
+  1 new obsolescence markers
+  2 new content-divergent changesets
+
+remove divergence by pruning one side of divergenence
+  $ hg debugobsolete $(hg id -ir 2 --debug)
+  1 new obsolescence markers
+  obsoleted 1 changesets
+
+  $ hg evolve -l
+  $ hg amend -m "i am gonna create divergence"
+  abort: amend of f8c05838af90 creates content-divergence with aafaf407b00d, from 9092f1db7931
+  (add --verbose for details or see 'hg help evolution.instability')
+  [255]
+  $ hg amend -m "i am gonna create divergence" --verbose
+  abort: amend of f8c05838af90 creates content-divergence with aafaf407b00d, from 9092f1db7931
+      changeset f8c05838af90 is an evolution of changeset 9092f1db7931
+      changeset 9092f1db7931 already have a successors as changeset aafaf407b00d
+      rewriting changeset f8c05838af90 would create "content-divergence"
+      set experimental.evolution.allowdivergence=True to overwrite this check
+  (see 'hg help evolution.instability' for details on content-divergence)
+  [255]
--- a/tests/test-evolve-content-divergent-basic.t	Wed Jan 01 21:36:21 2020 +0530
+++ b/tests/test-evolve-content-divergent-basic.t	Mon Nov 04 01:30:50 2019 +0530
@@ -21,6 +21,8 @@
   > unified = 0
   > [ui]
   > logtemplate = {rev}:{node|short}@{branch}({phase}) {desc|firstline} [{instabilities}]\n
+  > [experimental]
+  > evolution.allowdivergence = True
   > [extensions]
   > EOF
   $ echo "evolve=$(echo $(dirname $TESTDIR))/hgext3rd/evolve/" >> $HGRCPATH
--- a/tests/test-evolve-content-divergent-corner-cases.t	Wed Jan 01 21:36:21 2020 +0530
+++ b/tests/test-evolve-content-divergent-corner-cases.t	Mon Nov 04 01:30:50 2019 +0530
@@ -21,6 +21,8 @@
   > unified = 0
   > [ui]
   > logtemplate = {rev}:{node|short}@{branch}({phase}) {desc|firstline} [{instabilities}]\n
+  > [experimental]
+  > evolution.allowdivergence = True
   > [extensions]
   > EOF
   $ echo "evolve=$(echo $(dirname $TESTDIR))/hgext3rd/evolve/" >> $HGRCPATH
--- a/tests/test-evolve-content-divergent-first-changeset.t	Wed Jan 01 21:36:21 2020 +0530
+++ b/tests/test-evolve-content-divergent-first-changeset.t	Mon Nov 04 01:30:50 2019 +0530
@@ -1,6 +1,11 @@
   $ . $TESTDIR/testlib/pythonpath.sh
-  $ echo "[extensions]" >> $HGRCPATH
-  $ echo "evolve=" >> $HGRCPATH
+  $ cat >> $HGRCPATH << EOF
+  > [extensions]
+  > evolve=
+  > [experimental]
+  > evolution.allowdivergence = True
+  > EOF
+
 
 This test file tests the case of content-divergence resolution of changesets
 that have the null revision as the parent.
--- a/tests/test-evolve-content-divergent-interrupted.t	Wed Jan 01 21:36:21 2020 +0530
+++ b/tests/test-evolve-content-divergent-interrupted.t	Mon Nov 04 01:30:50 2019 +0530
@@ -24,6 +24,8 @@
   > publish = False
   > [alias]
   > glog = log -GT "{rev}:{node|short} {desc}\n ({bookmarks}) {phase}"
+  > [experimental]
+  > evolution.allowdivergence = True
   > [extensions]
   > EOF
   $ echo "evolve=$(echo $(dirname $TESTDIR))/hgext3rd/evolve/" >> $HGRCPATH
--- a/tests/test-evolve-content-divergent-meta.t	Wed Jan 01 21:36:21 2020 +0530
+++ b/tests/test-evolve-content-divergent-meta.t	Mon Nov 04 01:30:50 2019 +0530
@@ -12,6 +12,8 @@
   > glog = log -GT "{rev}:{node|short} {desc|firstline}\n {phase} {instabilities}\n\n"
   > [phases]
   > publish = False
+  > [experimental]
+  > evolution.allowdivergence = True
   > [extensions]
   > rebase =
   > strip =
--- a/tests/test-evolve-obshistory-content-divergent.t	Wed Jan 01 21:36:21 2020 +0530
+++ b/tests/test-evolve-obshistory-content-divergent.t	Mon Nov 04 01:30:50 2019 +0530
@@ -5,6 +5,10 @@
 ============
 
   $ . $TESTDIR/testlib/obshistory_setup.sh
+  $ cat >> $HGRCPATH << EOF
+  > [experimental]
+  > evolution.allowdivergence = True
+  > EOF
 
 Test output with content-divergence
 ===================================
--- a/tests/test-evolve-order.t	Wed Jan 01 21:36:21 2020 +0530
+++ b/tests/test-evolve-order.t	Mon Nov 04 01:30:50 2019 +0530
@@ -15,6 +15,8 @@
   > unified = 0
   > [ui]
   > logtemplate = {rev}:{node|short}@{branch}({phase}) {desc|firstline}\n
+  > [experimental]
+  > evolution.allowdivergence = True
   > [extensions]
   > EOF
   $ echo "evolve=$(echo $(dirname $TESTDIR))/hgext3rd/evolve/" >> $HGRCPATH
--- a/tests/test-evolve-public-content-divergent-corner-cases.t	Wed Jan 01 21:36:21 2020 +0530
+++ b/tests/test-evolve-public-content-divergent-corner-cases.t	Mon Nov 04 01:30:50 2019 +0530
@@ -12,6 +12,8 @@
   > glog = log -GT "{rev}:{node|short} {desc|firstline}\n {phase} {instabilities}\n\n"
   > [phases]
   > publish = False
+  > [experimental]
+  > evolution.allowdivergence = True
   > [extensions]
   > rebase =
   > EOF
--- a/tests/test-evolve-public-content-divergent-discard.t	Wed Jan 01 21:36:21 2020 +0530
+++ b/tests/test-evolve-public-content-divergent-discard.t	Mon Nov 04 01:30:50 2019 +0530
@@ -17,6 +17,8 @@
   > glog = log -GT "{rev}:{node|short} {desc|firstline}\n {phase} {instabilities}\n\n"
   > [phases]
   > publish = False
+  > [experimental]
+  > evolution.allowdivergence = True
   > [extensions]
   > rebase =
   > EOF
--- a/tests/test-evolve-public-content-divergent-main.t	Wed Jan 01 21:36:21 2020 +0530
+++ b/tests/test-evolve-public-content-divergent-main.t	Mon Nov 04 01:30:50 2019 +0530
@@ -15,6 +15,8 @@
   > glog = log -GT "{rev}:{node|short} {desc|firstline}\n {phase} {instabilities}\n\n"
   > [phases]
   > publish = False
+  > [experimental]
+  > evolution.allowdivergence = True
   > [extensions]
   > rebase =
   > EOF
--- a/tests/test-evolve-templates.t	Wed Jan 01 21:36:21 2020 +0530
+++ b/tests/test-evolve-templates.t	Mon Nov 04 01:30:50 2019 +0530
@@ -9,6 +9,8 @@
   > interactive = true
   > [phases]
   > publish=False
+  > [experimental]
+  > evolution.allowdivergence = True
   > [extensions]
   > evolve =
   > [alias]
--- a/tests/test-fold.t	Wed Jan 01 21:36:21 2020 +0530
+++ b/tests/test-fold.t	Mon Nov 04 01:30:50 2019 +0530
@@ -405,8 +405,8 @@
 
   $ hg fold --exact -r 'desc("A")::desc("B")' -m 'second fold' \
   >         --config experimental.evolution.allowdivergence=no
-  abort: folding obsolete revisions may cause divergence
-  (set experimental.evolution.allowdivergence=yes to allow folding them)
+  abort: fold of 4b34ecfb0d56 creates content-divergence with fcfd42a7fa46
+  (add --verbose for details or see 'hg help evolution.instability')
   [255]
 
 but if we allow divergence, this should work and should create new content-divergent changesets
--- a/tests/test-topic-stack-complex.t	Wed Jan 01 21:36:21 2020 +0530
+++ b/tests/test-topic-stack-complex.t	Mon Nov 04 01:30:50 2019 +0530
@@ -7,6 +7,7 @@
   $ cat << EOF >> $HGRCPATH
   > [experimental]
   > evolution = all
+  > evolution.allowdivergence = True
   > [ui]
   > interactive = True
   > [extensions]
--- a/tests/test-touch.t	Wed Jan 01 21:36:21 2020 +0530
+++ b/tests/test-touch.t	Mon Nov 04 01:30:50 2019 +0530
@@ -6,6 +6,8 @@
   > amend=-d "0 0"
   > [alias]
   > glog = log -GT "{rev}: {desc}"
+  > [experimental]
+  > evolution.allowdivergence = True
   > [extensions]
   > hgext.rebase=
   > EOF
--- a/tests/test-uncommit.t	Wed Jan 01 21:36:21 2020 +0530
+++ b/tests/test-uncommit.t	Mon Nov 04 01:30:50 2019 +0530
@@ -1,4 +1,6 @@
   $ cat >> $HGRCPATH <<EOF
+  > [experimental]
+  > evolution.allowdivergence = True
   > [extensions]
   > EOF
   $ echo "evolve=$(echo $(dirname $TESTDIR))/hgext3rd/evolve/" >> $HGRCPATH