drawdag: support obsmarker creation in comments
This patch adds special comment handling so one can create obsmarkers in
drawdag comments like "# replace: A -> B -> C", "# prune: X, Y, Z",
"split: P -> M, N" and they are just self-explained.
--- a/tests/drawdag.py Mon Jun 26 23:31:53 2017 -0700
+++ b/tests/drawdag.py Tue Jun 27 00:01:17 2017 -0700
@@ -72,10 +72,18 @@
This is because 'o' is specially handled in the input: instead of using 'o' as
the node name, the word to the right will be used.
+
+Some special comments could have side effects:
+
+ - Create obsmarkers
+ # replace: A -> B -> C -> D # chained 1 to 1 replacements
+ # split: A -> B, C # 1 to many
+ # prune: A, B, C # many to nothing
"""
from __future__ import absolute_import, print_function
import collections
+import contextlib
import itertools
from mercurial.i18n import _
@@ -83,6 +91,7 @@
context,
error,
node,
+ obsolete,
registrar,
scmutil,
tags as tagsmod,
@@ -268,6 +277,13 @@
if leaf in v:
v.remove(leaf)
+@contextlib.contextmanager
+def transaction(repo):
+ with repo.wlock():
+ with repo.lock():
+ with repo.transaction('drawdag'):
+ yield
+
@command('debugdrawdag', [])
def debugdrawdag(ui, repo, **opts):
"""read an ASCII graph from stdin and create changesets
@@ -314,3 +330,33 @@
committed[name] = n
tagsmod.tag(repo, name, n, message=None, user=None, date=None,
local=True)
+
+ # handle special comments
+ with transaction(repo):
+ getctx = lambda x: repo.unfiltered()[committed[x.strip()]]
+ for line in text.splitlines():
+ if ' # ' not in line:
+ continue
+
+ rels = [] # obsolete relationships
+ comment = line.split(' # ', 1)[1].split(' # ')[0].strip()
+ args = comment.split(':', 1)
+ if len(args) <= 1:
+ continue
+
+ cmd = args[0].strip()
+ arg = args[1].strip()
+
+ if cmd in ('replace', 'rebase', 'amend'):
+ nodes = [getctx(m) for m in arg.split('->')]
+ for i in range(len(nodes) - 1):
+ rels.append((nodes[i], (nodes[i + 1],)))
+ elif cmd in ('split',):
+ pre, succs = arg.split('->')
+ succs = succs.split(',')
+ rels.append((getctx(pre), (getctx(s) for s in succs)))
+ elif cmd in ('prune',):
+ for n in arg.split(','):
+ rels.append((getctx(n), ()))
+ if rels:
+ obsolete.createmarkers(repo, rels, date=(0, 0), operation=cmd)
--- a/tests/test-drawdag.t Mon Jun 26 23:31:53 2017 -0700
+++ b/tests/test-drawdag.t Tue Jun 27 00:01:17 2017 -0700
@@ -1,6 +1,8 @@
$ cat >> $HGRCPATH<<EOF
> [extensions]
> drawdag=$TESTDIR/drawdag.py
+ > [experimental]
+ > evolution=all
> EOF
$ reinit () {
@@ -178,3 +180,43 @@
> EOS
abort: the graph has cycles
[255]
+
+Create obsmarkers via comments
+
+ $ reinit
+
+ $ hg debugdrawdag <<'EOS'
+ > G
+ > |
+ > I D C F # split: B -> E, F, G
+ > \ \| | # replace: C -> D -> H
+ > H B E # prune: F, I
+ > \|/
+ > A
+ > EOS
+
+ $ hg log -r 'sort(all(), topo)' -G --hidden -T '{desc} {node}'
+ o G 711f53bbef0bebd12eb6f0511d5e2e998b984846
+ |
+ x F 64a8289d249234b9886244d379f15e6b650b28e3
+ |
+ o E 7fb047a69f220c21711122dfd94305a9efb60cba
+ |
+ | x D be0ef73c17ade3fc89dc41701eb9fc3a91b58282
+ | |
+ | | x C 26805aba1e600a82e93661149f2313866a221a7b
+ | |/
+ | x B 112478962961147124edd43549aedd1a335e44bf
+ |/
+ | x I 58e6b987bf7045fcd9c54f496396ca1d1fc81047
+ | |
+ | o H 575c4b5ec114d64b681d33f8792853568bfb2b2c
+ |/
+ o A 426bada5c67598ca65036d57d9e4b64b0c1ce7a0
+
+ $ hg debugobsolete
+ 112478962961147124edd43549aedd1a335e44bf 7fb047a69f220c21711122dfd94305a9efb60cba 64a8289d249234b9886244d379f15e6b650b28e3 711f53bbef0bebd12eb6f0511d5e2e998b984846 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
+ 26805aba1e600a82e93661149f2313866a221a7b be0ef73c17ade3fc89dc41701eb9fc3a91b58282 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
+ be0ef73c17ade3fc89dc41701eb9fc3a91b58282 575c4b5ec114d64b681d33f8792853568bfb2b2c 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
+ 64a8289d249234b9886244d379f15e6b650b28e3 0 {7fb047a69f220c21711122dfd94305a9efb60cba} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
+ 58e6b987bf7045fcd9c54f496396ca1d1fc81047 0 {575c4b5ec114d64b681d33f8792853568bfb2b2c} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}