obsolete: closest divergent support
Add a closest argument to successorssets changing the definition of latest
successors.
With "closest=false" (current behavior), latest successors are "leafs" on the
obsmarker graph. They don't have any successor and are known locally.
With "closest=true", latest successors are the closest locally-known
changesets that are visible in the repository or repoview. Closest successors
can be then obsolete, orphan.
This will be used in a later patch to show the closest successor of
changesets with the successorssets template.
--- a/mercurial/debugcommands.py Fri Jun 30 15:02:19 2017 +0200
+++ b/mercurial/debugcommands.py Fri Jun 30 15:27:19 2017 +0200
@@ -2067,13 +2067,14 @@
ui.write((' revision %s\n') % v[1])
@command('debugsuccessorssets',
- [],
+ [('', 'closest', False, _('return closest successors sets only'))],
_('[REV]'))
-def debugsuccessorssets(ui, repo, *revs):
+def debugsuccessorssets(ui, repo, *revs, **opts):
"""show set of successors for revision
A successors set of changeset A is a consistent group of revisions that
- succeed A. It contains non-obsolete changesets only.
+ succeed A. It contains non-obsolete changesets only unless closests
+ successors set is set.
In most cases a changeset A has a single successors set containing a single
successor (changeset A replaced by A').
@@ -2111,7 +2112,9 @@
for rev in scmutil.revrange(repo, revs):
ctx = repo[rev]
ui.write('%s\n'% ctx2str(ctx))
- for succsset in obsutil.successorssets(repo, ctx.node(), cache=cache):
+ for succsset in obsutil.successorssets(repo, ctx.node(),
+ closest=opts['closest'],
+ cache=cache):
if succsset:
ui.write(' ')
ui.write(node2str(succsset[0]))
--- a/mercurial/obsutil.py Fri Jun 30 15:02:19 2017 +0200
+++ b/mercurial/obsutil.py Fri Jun 30 15:27:19 2017 +0200
@@ -311,12 +311,15 @@
obsoleted.add(rev)
return obsoleted
-def successorssets(repo, initialnode, cache=None):
+def successorssets(repo, initialnode, closest=False, cache=None):
"""Return set of all latest successors of initial nodes
The successors set of a changeset A are the group of revisions that succeed
A. It succeeds A as a consistent whole, each revision being only a partial
- replacement. The successors set contains non-obsolete changesets only.
+ replacement. By default, the successors set contains non-obsolete
+ changesets only, walking the obsolescence graph until reaching a leaf. If
+ 'closest' is set to True, closest successors-sets are return (the
+ obsolescence walk stops on known changesets).
This function returns the full list of successor sets which is why it
returns a list of tuples and not just a single tuple. Each tuple is a valid
@@ -342,12 +345,19 @@
(pruned: obsoleted without any successors). (Final: successors not affected
by markers).
+ The 'closest' mode respect the repoview filtering. For example, without
+ filter it will stop at the first locally known changeset, with 'visible'
+ filter it will stop on visible changesets).
+
The optional `cache` parameter is a dictionary that may contains
precomputed successors sets. It is meant to reuse the computation of a
previous call to `successorssets` when multiple calls are made at the same
time. The cache dictionary is updated in place. The caller is responsible
for its life span. Code that makes multiple calls to `successorssets`
*should* use this cache mechanism or risk a performance hit.
+
+ Since results are different depending of the 'closest' most, the same cache
+ cannot be reused for both mode.
"""
succmarkers = repo.obsstore.successors
@@ -394,8 +404,10 @@
#
# 1) We already know the successors sets of CURRENT:
# -> mission accomplished, pop it from the stack.
- # 2) Node is not obsolete:
- # -> the node is its own successors sets. Add it to the cache.
+ # 2) Stop the walk:
+ # default case: Node is not obsolete
+ # closest case: Node is known at this repo filter level
+ # -> the node is its own successors sets. Add it to the cache.
# 3) We do not know successors set of direct successors of CURRENT:
# -> We add those successors to the stack.
# 4) We know successors sets of all direct successors of CURRENT:
@@ -403,13 +415,20 @@
# cache.
#
current = toproceed[-1]
+
+ # case 2 condition is a bit hairy because of closest,
+ # we compute it on its own
+ case2condition = ((current not in succmarkers)
+ or (closest and current != initialnode
+ and current in repo))
+
if current in cache:
# case (1): We already know the successors sets
stackedset.remove(toproceed.pop())
- elif current not in succmarkers:
- # case (2): The node is not obsolete.
+ elif case2condition:
+ # case (2): end of walk.
if current in repo:
- # We have a valid last successors.
+ # We have a valid successors.
cache[current] = [(current,)]
else:
# Final obsolete version is unknown locally.
--- a/tests/test-completion.t Fri Jun 30 15:02:19 2017 +0200
+++ b/tests/test-completion.t Fri Jun 30 15:27:19 2017 +0200
@@ -284,7 +284,7 @@
debugrevspec: optimize, show-revs, show-set, show-stage, no-optimized, verify-optimized
debugsetparents:
debugsub: rev
- debugsuccessorssets:
+ debugsuccessorssets: closest
debugtemplate: rev, define
debugupdatecaches:
debugupgraderepo: optimize, run
--- a/tests/test-obsolete-divergent.t Fri Jun 30 15:02:19 2017 +0200
+++ b/tests/test-obsolete-divergent.t Fri Jun 30 15:27:19 2017 +0200
@@ -80,6 +80,23 @@
$ hg log -r 'divergent()'
2:82623d38b9ba A_1
3:392fd25390da A_2
+ $ hg debugsuccessorssets 'all()' --closest
+ d20a80d4def3
+ d20a80d4def3
+ 82623d38b9ba
+ 82623d38b9ba
+ 392fd25390da
+ 392fd25390da
+ $ hg debugsuccessorssets 'all()' --closest --hidden
+ d20a80d4def3
+ d20a80d4def3
+ 007dc284c1f8
+ 82623d38b9ba
+ 392fd25390da
+ 82623d38b9ba
+ 82623d38b9ba
+ 392fd25390da
+ 392fd25390da
check that mercurial refuse to push
@@ -128,6 +145,25 @@
$ hg log -r 'divergent()'
2:82623d38b9ba A_1
4:01f36c5a8fda A_3
+ $ hg debugsuccessorssets 'all()' --closest
+ d20a80d4def3
+ d20a80d4def3
+ 82623d38b9ba
+ 82623d38b9ba
+ 01f36c5a8fda
+ 01f36c5a8fda
+ $ hg debugsuccessorssets 'all()' --closest --hidden
+ d20a80d4def3
+ d20a80d4def3
+ 007dc284c1f8
+ 82623d38b9ba
+ 392fd25390da
+ 82623d38b9ba
+ 82623d38b9ba
+ 392fd25390da
+ 392fd25390da
+ 01f36c5a8fda
+ 01f36c5a8fda
$ cd ..
@@ -160,6 +196,23 @@
$ hg log -r 'divergent()'
2:82623d38b9ba A_1
3:392fd25390da A_2
+ $ hg debugsuccessorssets 'all()' --closest
+ d20a80d4def3
+ d20a80d4def3
+ 82623d38b9ba
+ 82623d38b9ba
+ 392fd25390da
+ 392fd25390da
+ $ hg debugsuccessorssets 'all()' --closest --hidden
+ d20a80d4def3
+ d20a80d4def3
+ 007dc284c1f8
+ 82623d38b9ba
+ 392fd25390da
+ 82623d38b9ba
+ 82623d38b9ba
+ 392fd25390da
+ 392fd25390da
$ cd ..
do not take unknown node in account if they are final
@@ -175,6 +228,10 @@
$ hg debugsuccessorssets --hidden 'desc('A_0')'
007dc284c1f8
392fd25390da
+ $ hg debugsuccessorssets 'desc('A_0')' --closest
+ $ hg debugsuccessorssets 'desc('A_0')' --closest --hidden
+ 007dc284c1f8
+ 82623d38b9ba
$ cd ..
@@ -211,6 +268,23 @@
01f36c5a8fda
01f36c5a8fda
$ hg log -r 'divergent()'
+ $ hg debugsuccessorssets 'all()' --closest
+ d20a80d4def3
+ d20a80d4def3
+ 01f36c5a8fda
+ 01f36c5a8fda
+ $ hg debugsuccessorssets 'all()' --closest --hidden
+ d20a80d4def3
+ d20a80d4def3
+ 007dc284c1f8
+ 82623d38b9ba
+ 392fd25390da
+ 82623d38b9ba
+ 82623d38b9ba
+ 392fd25390da
+ 392fd25390da
+ 01f36c5a8fda
+ 01f36c5a8fda
$ cd ..
split is not divergences
@@ -237,6 +311,22 @@
392fd25390da
392fd25390da
$ hg log -r 'divergent()'
+ $ hg debugsuccessorssets 'all()' --closest
+ d20a80d4def3
+ d20a80d4def3
+ 82623d38b9ba
+ 82623d38b9ba
+ 392fd25390da
+ 392fd25390da
+ $ hg debugsuccessorssets 'all()' --closest --hidden
+ d20a80d4def3
+ d20a80d4def3
+ 007dc284c1f8
+ 82623d38b9ba 392fd25390da
+ 82623d38b9ba
+ 82623d38b9ba
+ 392fd25390da
+ 392fd25390da
Even when subsequent rewriting happen
@@ -283,6 +373,28 @@
e442cfc57690
e442cfc57690
e442cfc57690
+ $ hg debugsuccessorssets 'all()' --closest
+ d20a80d4def3
+ d20a80d4def3
+ 01f36c5a8fda
+ 01f36c5a8fda
+ e442cfc57690
+ e442cfc57690
+ $ hg debugsuccessorssets 'all()' --closest --hidden
+ d20a80d4def3
+ d20a80d4def3
+ 007dc284c1f8
+ 82623d38b9ba 392fd25390da
+ 82623d38b9ba
+ 82623d38b9ba
+ 392fd25390da
+ 392fd25390da
+ 01f36c5a8fda
+ 01f36c5a8fda
+ 6a411f0d7a0a
+ e442cfc57690
+ e442cfc57690
+ e442cfc57690
$ hg log -r 'divergent()'
Check more complex obsolescence graft (with divergence)
@@ -352,6 +464,40 @@
14608b260df8
bed64f5d2f5a
bed64f5d2f5a
+ $ hg debugsuccessorssets 'all()' --closest
+ d20a80d4def3
+ d20a80d4def3
+ 01f36c5a8fda
+ 01f36c5a8fda
+ 7ae126973a96
+ 7ae126973a96
+ 14608b260df8
+ 14608b260df8
+ bed64f5d2f5a
+ bed64f5d2f5a
+ $ hg debugsuccessorssets 'all()' --closest --hidden
+ d20a80d4def3
+ d20a80d4def3
+ 007dc284c1f8
+ 82623d38b9ba 392fd25390da
+ 82623d38b9ba
+ 82623d38b9ba
+ 392fd25390da
+ 392fd25390da
+ 01f36c5a8fda
+ 01f36c5a8fda
+ 6a411f0d7a0a
+ e442cfc57690
+ e442cfc57690
+ e442cfc57690
+ 3750ebee865d
+ 392fd25390da
+ 7ae126973a96
+ 7ae126973a96
+ 14608b260df8
+ 14608b260df8
+ bed64f5d2f5a
+ bed64f5d2f5a
$ hg log -r 'divergent()'
4:01f36c5a8fda A_3
8:7ae126973a96 A_7
@@ -416,6 +562,38 @@
a139f71be9da
a139f71be9da
a139f71be9da
+ $ hg debugsuccessorssets 'all()' --closest
+ d20a80d4def3
+ d20a80d4def3
+ 01f36c5a8fda
+ 01f36c5a8fda
+ a139f71be9da
+ a139f71be9da
+ $ hg debugsuccessorssets 'all()' --closest --hidden
+ d20a80d4def3
+ d20a80d4def3
+ 007dc284c1f8
+ 82623d38b9ba 392fd25390da
+ 82623d38b9ba
+ 82623d38b9ba
+ 392fd25390da
+ 392fd25390da
+ 01f36c5a8fda
+ 01f36c5a8fda
+ 6a411f0d7a0a
+ e442cfc57690
+ e442cfc57690
+ e442cfc57690
+ 3750ebee865d
+ 392fd25390da
+ 7ae126973a96
+ a139f71be9da
+ 14608b260df8
+ a139f71be9da
+ bed64f5d2f5a
+ a139f71be9da
+ a139f71be9da
+ a139f71be9da
$ hg log -r 'divergent()'
$ cd ..
@@ -433,5 +611,9 @@
$ hg debugsuccessorssets --hidden 'desc('A_0')'
007dc284c1f8
82623d38b9ba 392fd25390da
+ $ hg debugsuccessorssets 'desc('A_0')' --closest
+ $ hg debugsuccessorssets 'desc('A_0')' --closest --hidden
+ 007dc284c1f8
+ 82623d38b9ba 392fd25390da
$ cd ..