# HG changeset patch # User Boris Feld # Date 1495561684 -7200 # Node ID 262d684851dc493db9c1143f48f8fa3aca1113d8 # Parent db565cc05987420d1173bf2bc398c5660899e806 obshistory: add the all option to obslog to show the while obs tree Add a --all option to obslog in order to display also the successors of each obs markers. It has the effect of showing a more comprehensive graph when a split or a divergence happened. diff -r db565cc05987 -r 262d684851dc README --- a/README Fri May 26 16:12:07 2017 +0200 +++ b/README Tue May 23 19:48:04 2017 +0200 @@ -116,6 +116,7 @@ ------------------- - olog: add an 'obslog' alias + - olog: add an '--all' option to show the whole obsolescence history tree. 6.2.2 - in progress ------------------- diff -r db565cc05987 -r 262d684851dc hgext3rd/evolve/obshistory.py --- a/hgext3rd/evolve/obshistory.py Fri May 26 16:12:07 2017 +0200 +++ b/hgext3rd/evolve/obshistory.py Tue May 23 19:48:04 2017 +0200 @@ -28,7 +28,8 @@ @eh.command( 'obslog|olog', [('G', 'graph', True, _("show the revision DAG")), - ('r', 'rev', [], _('show the specified revision or revset'), _('REV')) + ('r', 'rev', [], _('show the specified revision or revset'), _('REV')), + ('a', 'all', False, _('show all related changesets, not only precursors')) ] + commands.formatteropts, _('hg olog [OPTION]... [REV]')) def cmdobshistory(ui, repo, *revs, **opts): @@ -158,14 +159,14 @@ stack.pop() return False -def _obshistorywalker(repo, revs): +def _obshistorywalker(repo, revs, walksuccessors=False): """ Directly inspired by graphmod.dagwalker, walk the obs marker tree and yield (id, CHANGESET, ctx, [parentinfo]) tuples """ # Get the list of nodes and links between them - candidates, nodesucc, nodeprec = _obshistorywalker_links(repo, revs) + candidates, nodesucc, nodeprec = _obshistorywalker_links(repo, revs, walksuccessors) # Shown, set of nodes presents in items shown = set() @@ -216,15 +217,19 @@ childrens = [(graphmod.PARENT, x) for x in nodeprec.get(cand, ())] yield (cand, 'M', changectx, childrens) -def _obshistorywalker_links(repo, revs): +def _obshistorywalker_links(repo, revs, walksuccessors=False): """ Iterate the obs history tree starting from revs, traversing each revision precursors recursively. + If walksuccessors is True, also check that every successor has been + walked, which ends up walking on all connected obs markers. It helps + getting a better view with splits and divergences. Return a tuple of: - The list of node crossed - The dictionnary of each node successors, values are a set - The dictionnary of each node precursors, values are a list """ precursors = repo.obsstore.precursors + successors = repo.obsstore.successors nodec = repo.changelog.node # Parents, set of parents nodes seen during walking the graph for node @@ -257,12 +262,21 @@ seen.add(precnode) nodes.append(precnode) + # Also walk on successors if the option is enabled + if walksuccessors: + for successor in successors.get(node, ()): + for succnodeid in successor[1]: + if succnodeid not in seen: + seen.add(succnodeid) + nodes.append(succnodeid) + return sorted(seen), nodesucc, nodeprec def _debugobshistorygraph(ui, repo, revs, opts): displayer = obsmarker_printer(ui, repo.unfiltered(), None, opts, buffered=True) edges = graphmod.asciiedges - cmdutil.displaygraph(ui, repo, _obshistorywalker(repo.unfiltered(), revs), displayer, edges) + walker = _obshistorywalker(repo.unfiltered(), revs, opts.get('all', False)) + cmdutil.displaygraph(ui, repo, walker, displayer, edges) def _debugobshistorysingle(fm, repo, revs): """ Display the obsolescence history for a single revision diff -r db565cc05987 -r 262d684851dc tests/test-evolve-cycles.t --- a/tests/test-evolve-cycles.t Fri May 26 16:12:07 2017 +0200 +++ b/tests/test-evolve-cycles.t Tue May 23 19:48:04 2017 +0200 @@ -117,6 +117,19 @@ | rewritten by test (*) as a8df460dbbfe (glob) | +Check that all option don't crash on a cycle either + + $ hg obslog "desc(C)" --hidden --all + @ 2a34000d3544 (1) A + | rewritten by test (*) as c473644ee0e9 (glob) + | + x a8df460dbbfe (3) C + | rewritten by test (*) as 2a34000d3544 (glob) + | + x c473644ee0e9 (2) B + | rewritten by test (*) as a8df460dbbfe (glob) + | + Test with multiple cyles ======================== @@ -247,7 +260,26 @@ x | c473644ee0e9 (2) B | | rewritten by test (*) as a8df460dbbfe (glob) | | - +Check that all option don't crash either on a cycle + $ hg obslog --all --hidden "desc(F)" + x 0da815c333f6 (5) E + | rewritten by test (*) as d9f908fde1a1 (glob) + | + @ 868d2e0eb19c (4) D + |\ rewritten by test (*) as 0da815c333f6 (glob) + | | + | x d9f908fde1a1 (6) F + | | rewritten by test (*) as 868d2e0eb19c (glob) + | | + +---x 2a34000d3544 (1) A + | | rewritten by test (*) as c473644ee0e9 (glob) + | | + x | a8df460dbbfe (3) C + | | rewritten by test (*) as 2a34000d3544, 868d2e0eb19c (glob) + | | + x | c473644ee0e9 (2) B + | | rewritten by test (*) as a8df460dbbfe (glob) + | | Check the json output is valid in this case $ hg obslog "desc(D)" --hidden --no-graph -Tjson | python -m json.tool @@ -362,3 +394,4 @@ "debugobshistory.shortdescription": "A" } ] + diff -r db565cc05987 -r 262d684851dc tests/test-evolve-obshistory-complex.t --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-evolve-obshistory-complex.t Tue May 23 19:48:04 2017 +0200 @@ -0,0 +1,428 @@ +Global setup +============ + + $ . $TESTDIR/testlib/common.sh + $ cat >> $HGRCPATH < [ui] + > interactive = true + > [phases] + > publish=False + > [extensions] + > evolve = + > EOF + +Test obslog with split + fold + split +===================================== + +Test setup +---------- + + $ hg init $TESTTMP/splitfoldsplit + $ cd $TESTTMP/splitfoldsplit + $ mkcommit ROOT + $ mkcommit A + $ mkcommit B + $ mkcommit C + $ mkcommit D + $ mkcommit E + $ mkcommit F + $ hg log -G + @ changeset: 6:d9f908fde1a1 + | tag: tip + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: F + | + o changeset: 5:0da815c333f6 + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: E + | + o changeset: 4:868d2e0eb19c + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: D + | + o changeset: 3:a8df460dbbfe + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: C + | + o changeset: 2:c473644ee0e9 + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: B + | + o changeset: 1:2a34000d3544 + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: A + | + o changeset: 0:ea207398892e + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: ROOT + +Split commits two by two +------------------------ + + $ hg fold --exact -r 1 -r 2 --date "0 0" -m "fold0" + 2 changesets folded + 4 new unstable changesets + $ hg fold --exact -r 3 -r 4 --date "0 0" -m "fold1" + 2 changesets folded + $ hg fold --exact -r 5 -r 6 --date "0 0" -m "fold2" + 2 changesets folded + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ hg log -G + @ changeset: 9:100cc25b765f + | tag: tip + | parent: 4:868d2e0eb19c + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | trouble: unstable + | summary: fold2 + | + | o changeset: 8:d15d0ffc75f6 + | | parent: 2:c473644ee0e9 + | | user: test + | | date: Thu Jan 01 00:00:00 1970 +0000 + | | trouble: unstable + | | summary: fold1 + | | + | | o changeset: 7:b868bc49b0a4 + | | | parent: 0:ea207398892e + | | | user: test + | | | date: Thu Jan 01 00:00:00 1970 +0000 + | | | summary: fold0 + | | | + x | | changeset: 4:868d2e0eb19c + | | | user: test + | | | date: Thu Jan 01 00:00:00 1970 +0000 + | | | summary: D + | | | + x | | changeset: 3:a8df460dbbfe + |/ / user: test + | | date: Thu Jan 01 00:00:00 1970 +0000 + | | summary: C + | | + x | changeset: 2:c473644ee0e9 + | | user: test + | | date: Thu Jan 01 00:00:00 1970 +0000 + | | summary: B + | | + x | changeset: 1:2a34000d3544 + |/ user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: A + | + o changeset: 0:ea207398892e + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: ROOT + + +Then split +---------- + + $ hg split "desc(fold0)" -d "0 0" << EOF + > Y + > Y + > N + > N + > Y + > Y + > EOF + 0 files updated, 0 files merged, 6 files removed, 0 files unresolved + adding A + adding B + diff --git a/A b/A + new file mode 100644 + examine changes to 'A'? [Ynesfdaq?] Y + + @@ -0,0 +1,1 @@ + +A + record change 1/2 to 'A'? [Ynesfdaq?] Y + + diff --git a/B b/B + new file mode 100644 + examine changes to 'B'? [Ynesfdaq?] N + + created new head + Done splitting? [yN] N + diff --git a/B b/B + new file mode 100644 + examine changes to 'B'? [Ynesfdaq?] Y + + @@ -0,0 +1,1 @@ + +B + record this change to 'B'? [Ynesfdaq?] Y + + no more change to split + $ hg split "desc(fold1)" -d "0 0" << EOF + > Y + > Y + > N + > N + > Y + > Y + > EOF + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + adding C + adding D + diff --git a/C b/C + new file mode 100644 + examine changes to 'C'? [Ynesfdaq?] Y + + @@ -0,0 +1,1 @@ + +C + record change 1/2 to 'C'? [Ynesfdaq?] Y + + diff --git a/D b/D + new file mode 100644 + examine changes to 'D'? [Ynesfdaq?] N + + created new head + Done splitting? [yN] N + diff --git a/D b/D + new file mode 100644 + examine changes to 'D'? [Ynesfdaq?] Y + + @@ -0,0 +1,1 @@ + +D + record this change to 'D'? [Ynesfdaq?] Y + + no more change to split + $ hg split "desc(fold2)" -d "0 0" << EOF + > Y + > Y + > N + > N + > Y + > Y + > EOF + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + adding E + adding F + diff --git a/E b/E + new file mode 100644 + examine changes to 'E'? [Ynesfdaq?] Y + + @@ -0,0 +1,1 @@ + +E + record change 1/2 to 'E'? [Ynesfdaq?] Y + + diff --git a/F b/F + new file mode 100644 + examine changes to 'F'? [Ynesfdaq?] N + + created new head + Done splitting? [yN] N + diff --git a/F b/F + new file mode 100644 + examine changes to 'F'? [Ynesfdaq?] Y + + @@ -0,0 +1,1 @@ + +F + record this change to 'F'? [Ynesfdaq?] Y + + no more change to split + $ hg log -G + @ changeset: 15:d4a000f63ee9 + | tag: tip + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | trouble: unstable + | summary: fold2 + | + o changeset: 14:ec31316faa9d + | parent: 4:868d2e0eb19c + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | trouble: unstable + | summary: fold2 + | + | o changeset: 13:d0f33db50670 + | | user: test + | | date: Thu Jan 01 00:00:00 1970 +0000 + | | trouble: unstable + | | summary: fold1 + | | + | o changeset: 12:7b3290f6e0a0 + | | parent: 2:c473644ee0e9 + | | user: test + | | date: Thu Jan 01 00:00:00 1970 +0000 + | | trouble: unstable + | | summary: fold1 + | | + | | o changeset: 11:e036916b63ea + | | | user: test + | | | date: Thu Jan 01 00:00:00 1970 +0000 + | | | summary: fold0 + | | | + | | o changeset: 10:19e14c8397fc + | | | parent: 0:ea207398892e + | | | user: test + | | | date: Thu Jan 01 00:00:00 1970 +0000 + | | | summary: fold0 + | | | + x | | changeset: 4:868d2e0eb19c + | | | user: test + | | | date: Thu Jan 01 00:00:00 1970 +0000 + | | | summary: D + | | | + x | | changeset: 3:a8df460dbbfe + |/ / user: test + | | date: Thu Jan 01 00:00:00 1970 +0000 + | | summary: C + | | + x | changeset: 2:c473644ee0e9 + | | user: test + | | date: Thu Jan 01 00:00:00 1970 +0000 + | | summary: B + | | + x | changeset: 1:2a34000d3544 + |/ user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: A + | + o changeset: 0:ea207398892e + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: ROOT + + +Connect them all +---------------- + + $ hg prune -s 12 -r 11 + 1 changesets pruned + $ hg prune -s 14 -r 13 + 1 changesets pruned + $ hg log -G + @ changeset: 15:d4a000f63ee9 + | tag: tip + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | trouble: unstable + | summary: fold2 + | + o changeset: 14:ec31316faa9d + | parent: 4:868d2e0eb19c + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | trouble: unstable + | summary: fold2 + | + | o changeset: 12:7b3290f6e0a0 + | | parent: 2:c473644ee0e9 + | | user: test + | | date: Thu Jan 01 00:00:00 1970 +0000 + | | trouble: unstable + | | summary: fold1 + | | + | | o changeset: 10:19e14c8397fc + | | | parent: 0:ea207398892e + | | | user: test + | | | date: Thu Jan 01 00:00:00 1970 +0000 + | | | summary: fold0 + | | | + x | | changeset: 4:868d2e0eb19c + | | | user: test + | | | date: Thu Jan 01 00:00:00 1970 +0000 + | | | summary: D + | | | + x | | changeset: 3:a8df460dbbfe + |/ / user: test + | | date: Thu Jan 01 00:00:00 1970 +0000 + | | summary: C + | | + x | changeset: 2:c473644ee0e9 + | | user: test + | | date: Thu Jan 01 00:00:00 1970 +0000 + | | summary: B + | | + x | changeset: 1:2a34000d3544 + |/ user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: A + | + o changeset: 0:ea207398892e + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: ROOT + +Actual Test +=========== + +Obslog should show a subset of the obs history, this test check that the +walking algorithm works no matter the level of successors + precursors + + $ hg obslog 12 + o 7b3290f6e0a0 (12) fold1 + |\ + x | d15d0ffc75f6 (8) fold1 + |\ \ rewritten by test (*) as 7b3290f6e0a0, d0f33db50670 (glob) + | | | + | | x e036916b63ea (11) fold0 + | | | rewritten by test (*) as 7b3290f6e0a0 (glob) + | | | + x | | 868d2e0eb19c (4) D + / / rewritten by test (*) as d15d0ffc75f6 (glob) + | | + x | a8df460dbbfe (3) C + / rewritten by test (*) as d15d0ffc75f6 (glob) + | + x b868bc49b0a4 (7) fold0 + |\ rewritten by test (*) as 19e14c8397fc, e036916b63ea (glob) + | | + x | 2a34000d3544 (1) A + / rewritten by test (*) as b868bc49b0a4 (glob) + | + x c473644ee0e9 (2) B + rewritten by test (*) as b868bc49b0a4 (glob) + +While with all option, we should see 15 changesets + + $ hg obslog --all 15 + o 19e14c8397fc (10) fold0 + | + | o 7b3290f6e0a0 (12) fold1 + | |\ + | | | @ d4a000f63ee9 (15) fold2 + | | | | + | | | | o ec31316faa9d (14) fold2 + | | | |/| + | | | x | 100cc25b765f (9) fold2 + | | | |\ \ rewritten by test (*) as d4a000f63ee9, ec31316faa9d (glob) + | | | | | | + | +-------x d0f33db50670 (13) fold1 + | | | | | rewritten by test (*) as ec31316faa9d (glob) + | | | | | + +---x | | e036916b63ea (11) fold0 + | | / / rewritten by test (*) as 7b3290f6e0a0 (glob) + | | | | + | | x | 0da815c333f6 (5) E + | | / rewritten by test (*) as 100cc25b765f (glob) + | | | + x | | b868bc49b0a4 (7) fold0 + |\ \ \ rewritten by test (*) as 19e14c8397fc, e036916b63ea (glob) + | | | | + | | x | d15d0ffc75f6 (8) fold1 + | | |\ \ rewritten by test (*) as 7b3290f6e0a0, d0f33db50670 (glob) + | | | | | + | | | | x d9f908fde1a1 (6) F + | | | | rewritten by test (*) as 100cc25b765f (glob) + | | | | + x | | | 2a34000d3544 (1) A + / / / rewritten by test (*) as b868bc49b0a4 (glob) + | | | + | x | 868d2e0eb19c (4) D + | / rewritten by test (*) as d15d0ffc75f6 (glob) + | | + | x a8df460dbbfe (3) C + | rewritten by test (*) as d15d0ffc75f6 (glob) + | + x c473644ee0e9 (2) B + rewritten by test (*) as b868bc49b0a4 (glob) + diff -r db565cc05987 -r 262d684851dc tests/test-evolve-obshistory.t --- a/tests/test-evolve-obshistory.t Fri May 26 16:12:07 2017 +0200 +++ b/tests/test-evolve-obshistory.t Tue May 23 19:48:04 2017 +0200 @@ -340,6 +340,15 @@ x 471597cad322 (1) A0 rewritten by test (*) as 337fec4d2edc, f257fde29c7a (glob) +With the all option, it should show the three changesets + $ hg obslog --all 337fec4d2edc + o 337fec4d2edc (2) A0 + | + | @ f257fde29c7a (3) A0 + |/ + x 471597cad322 (1) A0 + rewritten by test (*) as 337fec4d2edc, f257fde29c7a (glob) + Check that debugobshistory on the second successor after split show the revision plus the splitted one $ hg obslog f257fde29c7a @@ -348,6 +357,24 @@ x 471597cad322 (1) A0 rewritten by test (*) as 337fec4d2edc, f257fde29c7a (glob) +With the all option, it should show the three changesets + $ hg obslog f257fde29c7a --all + o 337fec4d2edc (2) A0 + | + | @ f257fde29c7a (3) A0 + |/ + x 471597cad322 (1) A0 + rewritten by test (*) as 337fec4d2edc, f257fde29c7a (glob) + +Obslog with all option all should also works on the splitted commit + $ hg obslog -a 471597cad322 --hidden + o 337fec4d2edc (2) A0 + | + | @ f257fde29c7a (3) A0 + |/ + x 471597cad322 (1) A0 + rewritten by test (*) as 337fec4d2edc, f257fde29c7a (glob) + Check that debugobshistory on both successors after split show a coherent graph $ hg obslog 'f257fde29c7a+337fec4d2edc' @@ -524,6 +551,18 @@ x de7290d8b885 (1) A0 rewritten by test (*) as 1ae8bc733a14, 337fec4d2edc, c7f044602e9b, f257fde29c7a (glob) + $ hg obslog de7290d8b885 --hidden --all + o 1ae8bc733a14 (4) A0 + | + | o 337fec4d2edc (2) A0 + |/ + | @ c7f044602e9b (5) A0 + |/ + | o f257fde29c7a (3) A0 + |/ + x de7290d8b885 (1) A0 + rewritten by test (*) as 1ae8bc733a14, 337fec4d2edc, c7f044602e9b, f257fde29c7a (glob) + $ hg obslog de7290d8b885 --hidden --no-graph -Tjson | python -m json.tool [ { @@ -597,6 +636,18 @@ x de7290d8b885 (1) A0 rewritten by test (*) as 1ae8bc733a14, 337fec4d2edc, c7f044602e9b, f257fde29c7a (glob) + $ hg obslog 5 --all + o 1ae8bc733a14 (4) A0 + | + | o 337fec4d2edc (2) A0 + |/ + | @ c7f044602e9b (5) A0 + |/ + | o f257fde29c7a (3) A0 + |/ + x de7290d8b885 (1) A0 + rewritten by test (*) as 1ae8bc733a14, 337fec4d2edc, c7f044602e9b, f257fde29c7a (glob) + $ hg update de7290d8b885 abort: hidden revision 'de7290d8b885'! (use --hidden to access hidden revisions; successors: 337fec4d2edc, f257fde29c7a and 2 more) @@ -669,12 +720,32 @@ x 471f378eab4c (1) A0 rewritten by test (*) as eb5a0daa2192 (glob) +Check that with all option, all changesets are shown + $ hg obslog --hidden --all 471f378eab4c + @ eb5a0daa2192 (3) C0 + |\ + x | 0dec01379d3b (2) B0 + / rewritten by test (*) as eb5a0daa2192 (glob) + | + x 471f378eab4c (1) A0 + rewritten by test (*) as eb5a0daa2192 (glob) + Check that debugobshistory on the second folded revision show only the revision with the target $ hg obslog --hidden 0dec01379d3b x 0dec01379d3b (2) B0 rewritten by test (*) as eb5a0daa2192 (glob) +Check that with all option, all changesets are shown + $ hg obslog --hidden --all 0dec01379d3b + @ eb5a0daa2192 (3) C0 + |\ + x | 0dec01379d3b (2) B0 + / rewritten by test (*) as eb5a0daa2192 (glob) + | + x 471f378eab4c (1) A0 + rewritten by test (*) as eb5a0daa2192 (glob) + Check that debugobshistory on the successor revision show a coherent graph $ hg obslog eb5a0daa2192 @@ -820,6 +891,17 @@ rewritten by test (*) as 65b757b745b9 (glob) rewritten by test (*) as fdf9bde5129a (glob) + +Check that with all option, every changeset is shown + $ hg obslog --hidden --all 471f378eab4c + @ 65b757b745b9 (3) A2 + | + | o fdf9bde5129a (2) A1 + |/ + x 471f378eab4c (1) A0 + rewritten by test (*) as 65b757b745b9 (glob) + rewritten by test (*) as fdf9bde5129a (glob) + $ hg obslog --hidden 471f378eab4c --no-graph -Tjson | python -m json.tool [ { @@ -861,6 +943,17 @@ rewritten by test (*) as 65b757b745b9 (glob) rewritten by test (*) as fdf9bde5129a (glob) + +Check that all option show all of them + $ hg obslog fdf9bde5129a -a + @ 65b757b745b9 (3) A2 + | + | o fdf9bde5129a (2) A1 + |/ + x 471f378eab4c (1) A0 + rewritten by test (*) as 65b757b745b9 (glob) + rewritten by test (*) as fdf9bde5129a (glob) + Check that debugobshistory on the second diverged revision show the revision and the diverent one $ hg obslog 65b757b745b9 @@ -870,6 +963,16 @@ rewritten by test (*) as 65b757b745b9 (glob) rewritten by test (*) as fdf9bde5129a (glob) +Check that all option show all of them + $ hg obslog 65b757b745b9 -a + @ 65b757b745b9 (3) A2 + | + | o fdf9bde5129a (2) A1 + |/ + x 471f378eab4c (1) A0 + rewritten by test (*) as 65b757b745b9 (glob) + rewritten by test (*) as fdf9bde5129a (glob) + Check that debugobshistory on the both diverged revision show a coherent graph $ hg obslog '65b757b745b9+fdf9bde5129a' @@ -1017,6 +1120,19 @@ x 0dec01379d3b (2) B0 rewritten by test (*) as b7ea6d14e664 (glob) +Check that obslog on ROOT with all option show everything + $ hg obslog 1 --hidden --all + @ eb5a0daa2192 (4) C0 + |\ + x | 471f378eab4c (1) A0 + / rewritten by test (*) as eb5a0daa2192 (glob) + | + x b7ea6d14e664 (3) B1 + | rewritten by test (*) as eb5a0daa2192 (glob) + | + x 0dec01379d3b (2) B0 + rewritten by test (*) as b7ea6d14e664 (glob) + $ hg obslog eb5a0daa2192 --no-graph -Tjson | python -m json.tool [ {