[PATCH 3 of 5] obsolete: detect divergent changesets
Pierre-Yves David
pierre-yves.david at ens-lyon.org
Fri Nov 9 19:23:46 CST 2012
# HG changeset patch
# User Pierre-Yves David <pierre-yves.david at logilab.fr>
# Date 1352509811 -3600
# Node ID 135802bc01b47fc34154dd41a698b18fb882c83a
# Parent 929a4dc33ad3401ced4b099bdbf29d714115d2df
obsolete: detect divergent changesets
Divergent changeset are final successors (non obsolete) of a changeset who
compete with another set of final successors for this same changeset.
For example if you have two obsolescence markers A -> B and A -> C, B and C are
both "divergent" because they compete to be the one true successors of A.
Public revision can't be divergent.
diff --git a/mercurial/obsolete.py b/mercurial/obsolete.py
--- a/mercurial/obsolete.py
+++ b/mercurial/obsolete.py
@@ -625,6 +625,28 @@
query = '%ld - obsolete() - public()'
return set(repo.revs(query, _knownrevs(repo, successors)))
+ at cachefor('divergent')
+def _computedivergentset(repo):
+ """the set of rev that compete to be the final successors of some revision.
+ """
+ divergent = set()
+ obsstore = repo.obsstore
+ newermap = {}
+ for ctx in repo.set('(not public()) - obsolete()'):
+ mark = obsstore.precursors.get(ctx.node(), ())
+ toprocess = set(mark)
+ while toprocess:
+ prec = toprocess.pop()[0]
+ if prec not in newermap:
+ successorssets(repo, prec, newermap)
+ newer = [n for n in newermap[prec] if n]
+ if len(newer) > 1:
+ divergent.add(ctx.rev())
+ break
+ toprocess.update(obsstore.precursors.get(prec, ()))
+ return divergent
+
+
def createmarkers(repo, relations, flag=0, metadata=None):
"""Add obsolete markers between changesets in a repo
diff --git a/mercurial/revset.py b/mercurial/revset.py
--- a/mercurial/revset.py
+++ b/mercurial/revset.py
@@ -641,6 +641,15 @@
return [r for r in subset if r in dests]
+def divergent(repo, subset, x):
+ """``divergent()``
+ Final successors of changesets with an alternative set of final successors.
+ """
+ # i18n: "divergent" is a keyword
+ getargs(x, 0, 0, _("divergent takes no arguments"))
+ divergent = obsmod.getrevs(repo, 'divergent')
+ return [r for r in subset if r in divergent]
+
def draft(repo, subset, x):
"""``draft()``
Changeset in draft phase."""
@@ -1536,6 +1545,7 @@
"descendants": descendants,
"_firstdescendants": _firstdescendants,
"destination": destination,
+ "divergent": divergent,
"draft": draft,
"extinct": extinct,
"extra": extra,
diff --git a/tests/test-obsolete-divergent.t b/tests/test-obsolete-divergent.t
--- a/tests/test-obsolete-divergent.t
+++ b/tests/test-obsolete-divergent.t
@@ -81,6 +81,9 @@
82623d38b9ba
392fd25390da
392fd25390da
+ $ hg log -r 'divergent()'
+ 2:82623d38b9ba A_1
+ 3:392fd25390da A_2
$ cd ..
@@ -116,6 +119,9 @@
01f36c5a8fda
01f36c5a8fda
01f36c5a8fda
+ $ hg log -r 'divergent()'
+ 2:82623d38b9ba A_1
+ 4:01f36c5a8fda A_3
$ cd ..
@@ -145,6 +151,9 @@
82623d38b9ba
392fd25390da
392fd25390da
+ $ hg log -r 'divergent()'
+ 2:82623d38b9ba A_1
+ 3:392fd25390da A_2
$ cd ..
do not take unknown node in account if they are final
@@ -195,6 +204,7 @@
01f36c5a8fda
01f36c5a8fda
01f36c5a8fda
+ $ hg log -r 'divergent()'
$ cd ..
split is not divergences
@@ -220,6 +230,7 @@
82623d38b9ba
392fd25390da
392fd25390da
+ $ hg log -r 'divergent()'
Even when subsequente rewriting happen
@@ -266,6 +277,7 @@
e442cfc57690
e442cfc57690
e442cfc57690
+ $ hg log -r 'divergent()'
Check more complexe obsolescence graft (with divergence)
@@ -334,6 +346,11 @@
14608b260df8
bed64f5d2f5a
bed64f5d2f5a
+ $ hg log -r 'divergent()'
+ 4:01f36c5a8fda A_3
+ 8:7ae126973a96 A_7
+ 9:14608b260df8 A_8
+ 10:bed64f5d2f5a A_9
fix the divergence
@@ -393,6 +410,7 @@
a139f71be9da
a139f71be9da
a139f71be9da
+ $ hg log -r 'divergent()'
$ cd ..
More information about the Mercurial-devel
mailing list