diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py --- a/mercurial/cmdutil.py +++ b/mercurial/cmdutil.py @@ -2652,14 +2652,18 @@ revmatchfn = None if filematcher is not None: revmatchfn = filematcher(ctx.rev()) - displayer.show(ctx, copies=copies, matchfn=revmatchfn) + edges = edgefn(type, char, state, rev, parents) + firstedge = next(edges) + width = firstedge[2] + displayer.show(ctx, copies=copies, matchfn=revmatchfn, + _graphwidth=width) lines = displayer.hunk.pop(rev).split('\n') if not lines[-1]: del lines[-1] displayer.flush(ctx) - edges = edgefn(type, char, lines, state, rev, parents) - for type, char, lines, coldata in edges: + for type, char, width, coldata in itertools.chain([firstedge], edges): graphmod.ascii(ui, state, type, char, lines, coldata) + lines = [] displayer.close() def graphlog(ui, repo, pats, opts): diff --git a/mercurial/graphmod.py b/mercurial/graphmod.py --- a/mercurial/graphmod.py +++ b/mercurial/graphmod.py @@ -172,7 +172,7 @@ yield (cur, type, data, (col, color), edges) seen = next -def asciiedges(type, char, lines, state, rev, parents): +def asciiedges(type, char, state, rev, parents): """adds edge info to changelog DAG walk suitable for ascii()""" seen = state['seen'] if rev not in seen: @@ -192,6 +192,7 @@ state['edges'][parent] = state['styles'].get(ptype, '|') ncols = len(seen) + width = 1 + ncols * 2 nextseen = seen[:] nextseen[nodeidx:nodeidx + 1] = newparents edges = [(nodeidx, nextseen.index(p)) for p in knownparents] @@ -205,9 +206,9 @@ edges.append((nodeidx, nodeidx)) edges.append((nodeidx, nodeidx + 1)) nmorecols = 1 - yield (type, char, lines, (nodeidx, edges, ncols, nmorecols)) + width += 2 + yield (type, char, width, (nodeidx, edges, ncols, nmorecols)) char = '\\' - lines = [] nodeidx += 1 ncols += 1 edges = [] @@ -218,9 +219,11 @@ if len(newparents) > 1: edges.append((nodeidx, nodeidx + 1)) nmorecols = len(nextseen) - ncols + if nmorecols > 0: + width += 2 # remove current node from edge characters, no longer needed state['edges'].pop(rev, None) - yield (type, char, lines, (nodeidx, edges, ncols, nmorecols)) + yield (type, char, width, (nodeidx, edges, ncols, nmorecols)) def _fixlongrightedges(edges): for (i, (start, end)) in enumerate(edges): diff --git a/mercurial/templatekw.py b/mercurial/templatekw.py --- a/mercurial/templatekw.py +++ b/mercurial/templatekw.py @@ -469,6 +469,13 @@ else: return 'o' +@templatekeyword('graphwidth') +def showgraphwidth(repo, ctx, templ, **args): + """Integer. The width of the graph drawn by 'log --graph' or zero.""" + # The value args['graphwidth'] will be this function, so we use an internal + # name to pass the value through props into this function. + return args.get('_graphwidth', 0) + @templatekeyword('index') def showindex(**args): """Integer. The current iteration of the loop. (0 indexed)""" diff --git a/tests/test-command-template.t b/tests/test-command-template.t --- a/tests/test-command-template.t +++ b/tests/test-command-template.t @@ -4319,3 +4319,155 @@ custom $ cd .. + +Test 'graphwidth' in 'hg log' on various topologies. The key here is that the +printed graphwidths 3, 5, 7, etc. should all line up in their respective +columns. We don't care about other aspects of the graph rendering here. + + $ hg init graphwidth + $ cd graphwidth + + $ wrappabletext="a a a a a a a a a a a a" + + $ printf "first\n" > file + $ hg add file + $ hg commit -m "$wrappabletext" + + $ printf "first\nsecond\n" > file + $ hg commit -m "$wrappabletext" + + $ hg checkout 0 + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ printf "third\nfirst\n" > file + $ hg commit -m "$wrappabletext" + created new head + + $ hg merge + merging file + 0 files updated, 1 files merged, 0 files removed, 0 files unresolved + (branch merge, don't forget to commit) + + $ hg log --graph -T "{graphwidth}" + @ 3 + | + | @ 5 + |/ + o 3 + + $ hg commit -m "$wrappabletext" + + $ hg log --graph -T "{graphwidth}" + @ 5 + |\ + | o 5 + | | + o | 5 + |/ + o 3 + + + $ hg checkout 0 + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ printf "third\nfirst\nsecond\n" > file + $ hg commit -m "$wrappabletext" + created new head + + $ hg log --graph -T "{graphwidth}" + @ 3 + | + | o 7 + | |\ + +---o 7 + | | + | o 5 + |/ + o 3 + + + $ hg log --graph -T "{graphwidth}" -r 3 + o 5 + |\ + ~ ~ + + $ hg log --graph -T "{graphwidth}" -r 1 + o 3 + | + ~ + + $ hg merge + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + (branch merge, don't forget to commit) + $ hg commit -m "$wrappabletext" + + $ printf "seventh\n" >> file + $ hg commit -m "$wrappabletext" + + $ hg log --graph -T "{graphwidth}" + @ 3 + | + o 5 + |\ + | o 5 + | | + o | 7 + |\ \ + | o | 7 + | |/ + o / 5 + |/ + o 3 + + +The point of graphwidth is to allow wrapping that accounts for the space taken +by the graph. + + $ COLUMNS=10 hg log --graph -T "{fill(desc, termwidth - graphwidth)}" + @ a a a a + | a a a a + | a a a a + o a a a + |\ a a a + | | a a a + | | a a a + | o a a a + | | a a a + | | a a a + | | a a a + o | a a + |\ \ a a + | | | a a + | | | a a + | | | a a + | | | a a + | o | a a + | |/ a a + | | a a + | | a a + | | a a + | | a a + o | a a a + |/ a a a + | a a a + | a a a + o a a a a + a a a a + a a a a + +Something tricky happens when there are elided nodes; the next drawn row of +edges can be more than one column wider, but the graph width only increases by +one column. The remaining columns are added in between the nodes. + + $ hg log --graph -T "{graphwidth}" -r "0|2|4|5" + o 5 + |\ + | \ + | :\ + o : : 7 + :/ / + : o 5 + :/ + o 3 + + + $ cd .. +