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).
--- 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