##// END OF EJS Templates
init: create target directory recursively...
init: create target directory recursively Subrepos with relative paths must often be cloned to locations deep in the directory structure. This allows clone over ssh (init+push) work.

File last commit:

r11448:25430ff2 stable
r11640:c3e8ab80 stable
Show More
graphlog.py
382 lines | 13.0 KiB | text/x-python | PythonLexer
Joel Rosdahl
Add graphlog extension
r4344 # ASCII graph log extension for Mercurial
#
# Copyright 2007 Joel Rosdahl <joel@rosdahl.net>
Thomas Arendsen Hein
Removed trailing whitespace and tabs from python files
r4516 #
Martin Geisler
updated license to be explicit about GPL version 2
r8225 # This software may be used and distributed according to the terms of the
Matt Mackall
Update license to GPLv2+
r10263 # GNU General Public License version 2 or any later version.
Martin Geisler
add blank line after copyright notices and after header
r8228
Dirkjan Ochtman
extensions: change descriptions for extensions providing a few commands
r8934 '''command to view revision graphs from a shell
Alpar Juttner
Graphlog extension adds a --graph option to log/in/out...
r7426
This extension adds a --graph option to the incoming, outgoing and log
Martin Geisler
graphlog: wrap docstrings at 70 characters
r9259 commands. When this options is given, an ASCII representation of the
revision graph is also shown.
Alpar Juttner
Graphlog extension adds a --graph option to log/in/out...
r7426 '''
Joel Rosdahl
Add graphlog extension
r4344
Christian Ebert
graphlog: remove unused import
r10333 import os
Joel Rosdahl
Add graphlog extension
r4344 from mercurial.cmdutil import revrange, show_changeset
Peter Arrenbrecht
cleanup: drop unused imports
r7873 from mercurial.commands import templateopts
Joel Rosdahl
Add graphlog extension
r4344 from mercurial.i18n import _
Joel Rosdahl
Remove unused imports
r6212 from mercurial.node import nullrev
Alpar Juttner
Graphlog extension adds a --graph option to log/in/out...
r7426 from mercurial import bundlerepo, changegroup, cmdutil, commands, extensions
Dirkjan Ochtman
move discovery methods from localrepo into new discovery module
r11301 from mercurial import hg, url, util, graphmod, discovery
Steve Borho
graphlog: add filelog revision grapher...
r5938
Peter Arrenbrecht
graphmod/graphlog: make dag walks carry data as type, payload
r8840 ASCIIDATA = 'ASC'
Dirkjan Ochtman
graphlog: move common code into function again, change function types
r9369 def asciiedges(seen, rev, parents):
Peter Arrenbrecht
graphmod/graphlog: make dag walks carry data as type, payload
r8840 """adds edge info to changelog DAG walk suitable for ascii()"""
Dirkjan Ochtman
graphlog: move common code into function again, change function types
r9369 if rev not in seen:
seen.append(rev)
nodeidx = seen.index(rev)
Steve Borho
graphlog: add filelog revision grapher...
r5938
Dirkjan Ochtman
graphlog: move common code into function again, change function types
r9369 knownparents = []
newparents = []
for parent in parents:
if parent in seen:
knownparents.append(parent)
else:
newparents.append(parent)
Steve Borho
graphlog: add filelog revision grapher...
r5938
Dirkjan Ochtman
graphlog: move common code into function again, change function types
r9369 ncols = len(seen)
seen[nodeidx:nodeidx + 1] = newparents
edges = [(nodeidx, seen.index(p)) for p in knownparents]
Peter Arrenbrecht
graphlog: refactor common grapher code...
r7370
Dirkjan Ochtman
graphlog: move common code into function again, change function types
r9369 if len(newparents) > 0:
edges.append((nodeidx, nodeidx))
if len(newparents) > 1:
edges.append((nodeidx, nodeidx + 1))
nmorecols = len(seen) - ncols
return nodeidx, edges, ncols, nmorecols
Steve Borho
graphlog: add filelog revision grapher...
r5938
Joel Rosdahl
Add graphlog extension
r4344 def fix_long_right_edges(edges):
for (i, (start, end)) in enumerate(edges):
if end > start:
edges[i] = (start, end + 1)
Dirkjan Ochtman
graphlog: move functions around, eliminate helper function...
r7326 def get_nodeline_edges_tail(
node_index, p_node_index, n_columns, n_columns_diff, p_diff, fix_tail):
if fix_tail and n_columns_diff == p_diff and n_columns_diff != 0:
# Still going in the same non-vertical direction.
if n_columns_diff == -1:
start = max(node_index + 1, p_node_index)
tail = ["|", " "] * (start - node_index - 1)
tail.extend(["/", " "] * (n_columns - start))
return tail
else:
return ["\\", " "] * (n_columns - node_index - 1)
else:
return ["|", " "] * (n_columns - node_index - 1)
Joel Rosdahl
Add graphlog extension
r4344 def draw_edges(edges, nodeline, interline):
for (start, end) in edges:
if start == end + 1:
interline[2 * end + 1] = "/"
elif start == end - 1:
interline[2 * start + 1] = "\\"
elif start == end:
interline[2 * start] = "|"
else:
nodeline[2 * end] = "+"
if start > end:
Martin Geisler
coding style: use a space after comma...
r9198 (start, end) = (end, start)
Joel Rosdahl
Add graphlog extension
r4344 for i in range(2 * start + 1, 2 * end):
if nodeline[i] != "+":
nodeline[i] = "-"
def get_padding_line(ni, n_columns, edges):
line = []
line.extend(["|", " "] * ni)
if (ni, ni - 1) in edges or (ni, ni) in edges:
# (ni, ni - 1) (ni, ni)
# | | | | | | | |
# +---o | | o---+
# | | c | | c | |
# | |/ / | |/ /
# | | | | | |
c = "|"
else:
c = " "
line.extend([c, " "])
line.extend(["|", " "] * (n_columns - ni - 1))
return line
Peter Arrenbrecht
graphlog: hide internal state of ascii() from users
r9631 def asciistate():
"""returns the initial value for the "state" argument to ascii()"""
return [0, 0]
def ascii(ui, state, type, char, text, coldata):
Peter Arrenbrecht
graphlog: rename grapher to asciiedges
r8839 """prints an ASCII graph of the DAG
Joel Rosdahl
Add graphlog extension
r4344
Dirkjan Ochtman
graphlog: simplify ascii drawing to process one cset at a time
r9371 takes the following arguments (one call per node in the graph):
Joel Rosdahl
Add graphlog extension
r4344
Dirkjan Ochtman
graphlog: simplify ascii drawing to process one cset at a time
r9371 - ui to write to
Peter Arrenbrecht
graphlog: hide internal state of ascii() from users
r9631 - Somewhere to keep the needed state in (init to asciistate())
Peter Arrenbrecht
graphlog: split the actual DAG grapher out into a separate method...
r7325 - Column of the current node in the set of ongoing edges.
Peter Arrenbrecht
graphmod/graphlog: make dag walks carry data as type, payload
r8840 - Type indicator of node data == ASCIIDATA.
- Payload: (char, lines):
- Character to use as node's symbol.
- List of lines to display as the node's text.
Peter Arrenbrecht
graphlog: split the actual DAG grapher out into a separate method...
r7325 - Edges; a list of (col, next_col) indicating the edges between
the current node and its parents.
- Number of columns (ongoing edges) in the current revision.
- The difference between the number of columns (ongoing edges)
in the next revision and the number of columns (ongoing edges)
in the current revision. That is: -1 means one column removed;
0 means no columns added or removed; 1 means one column added.
"""
Joel Rosdahl
Add graphlog extension
r4344
Dirkjan Ochtman
graphlog: simplify ascii drawing to process one cset at a time
r9371 idx, edges, ncols, coldiff = coldata
assert -2 < coldiff < 2
if coldiff == -1:
# Transform
Joel Rosdahl
Add graphlog extension
r4344 #
Dirkjan Ochtman
graphlog: simplify ascii drawing to process one cset at a time
r9371 # | | | | | |
# o | | into o---+
# |X / |/ /
# | | | |
fix_long_right_edges(edges)
# add_padding_line says whether to rewrite
#
# | | | | | | | |
# | o---+ into | o---+
# | / / | | | # <--- padding line
# o | | | / /
# o | |
add_padding_line = (len(text) > 2 and coldiff == -1 and
[x for (x, y) in edges if x + 1 < y])
Joel Rosdahl
Add graphlog extension
r4344
Dirkjan Ochtman
graphlog: simplify ascii drawing to process one cset at a time
r9371 # fix_nodeline_tail says whether to rewrite
#
# | | o | | | | o | |
# | | |/ / | | |/ /
# | o | | into | o / / # <--- fixed nodeline tail
# | |/ / | |/ /
# o | | o | |
fix_nodeline_tail = len(text) <= 2 and not add_padding_line
Joel Rosdahl
Add graphlog extension
r4344
Dirkjan Ochtman
graphlog: simplify ascii drawing to process one cset at a time
r9371 # nodeline is the line containing the node character (typically o)
nodeline = ["|", " "] * idx
nodeline.extend([char, " "])
Joel Rosdahl
Add graphlog extension
r4344
Dirkjan Ochtman
graphlog: simplify ascii drawing to process one cset at a time
r9371 nodeline.extend(
Peter Arrenbrecht
graphlog: hide internal state of ascii() from users
r9631 get_nodeline_edges_tail(idx, state[1], ncols, coldiff,
state[0], fix_nodeline_tail))
Joel Rosdahl
Add graphlog extension
r4344
Dirkjan Ochtman
graphlog: simplify ascii drawing to process one cset at a time
r9371 # shift_interline is the line containing the non-vertical
# edges between this entry and the next
shift_interline = ["|", " "] * idx
if coldiff == -1:
n_spaces = 1
edge_ch = "/"
elif coldiff == 0:
n_spaces = 2
edge_ch = "|"
else:
n_spaces = 3
edge_ch = "\\"
shift_interline.extend(n_spaces * [" "])
shift_interline.extend([edge_ch, " "] * (ncols - idx - 1))
Joel Rosdahl
Add graphlog extension
r4344
Dirkjan Ochtman
graphlog: simplify ascii drawing to process one cset at a time
r9371 # draw edges from the current node to its parents
draw_edges(edges, nodeline, shift_interline)
Joel Rosdahl
Add graphlog extension
r4344
Dirkjan Ochtman
graphlog: simplify ascii drawing to process one cset at a time
r9371 # lines is the list of all graph lines to print
lines = [nodeline]
if add_padding_line:
lines.append(get_padding_line(idx, ncols, edges))
lines.append(shift_interline)
Joel Rosdahl
Add graphlog extension
r4344
Dirkjan Ochtman
graphlog: simplify ascii drawing to process one cset at a time
r9371 # make sure that there are as many graph lines as there are
# log strings
while len(text) < len(lines):
text.append("")
if len(lines) < len(text):
extra_interline = ["|", " "] * (ncols + coldiff)
while len(lines) < len(text):
lines.append(extra_interline)
Joel Rosdahl
Add graphlog extension
r4344
Dirkjan Ochtman
graphlog: simplify ascii drawing to process one cset at a time
r9371 # print lines
indentation_level = max(ncols, ncols + coldiff)
for (line, logstr) in zip(lines, text):
ln = "%-*s %s" % (2 * indentation_level, "".join(line), logstr)
ui.write(ln.rstrip() + '\n')
Joel Rosdahl
Add graphlog extension
r4344
Dirkjan Ochtman
graphlog: simplify ascii drawing to process one cset at a time
r9371 # ... and start over
Peter Arrenbrecht
graphlog: hide internal state of ascii() from users
r9631 state[0] = coldiff
state[1] = idx
Joel Rosdahl
Add graphlog extension
r4344
Dirkjan Ochtman
graphlog: move functions around, eliminate helper function...
r7326 def get_revs(repo, rev_opt):
if rev_opt:
revs = revrange(repo, rev_opt)
Eric Eisner
glog: fix crash on empty revision range
r11448 if len(revs) == 0:
return (nullrev, nullrev)
Dirkjan Ochtman
graphlog: move functions around, eliminate helper function...
r7326 return (max(revs), min(revs))
else:
return (len(repo) - 1, 0)
Alpar Juttner
Graphlog extension adds a --graph option to log/in/out...
r7426 def check_unsupported_flags(opts):
for op in ["follow", "follow_first", "date", "copies", "keyword", "remove",
"only_merges", "user", "only_branch", "prune", "newest_first",
"no_merges", "include", "exclude"]:
if op in opts and opts[op]:
Greg Ward
glog: fix "incompatible option" error message....
r10097 raise util.Abort(_("--graph option is incompatible with --%s")
% op.replace("_", "-"))
Alpar Juttner
Graphlog extension adds a --graph option to log/in/out...
r7426
Dirkjan Ochtman
graphlog: simplify ascii drawing to process one cset at a time
r9371 def generate(ui, dag, displayer, showparents, edgefn):
Peter Arrenbrecht
graphlog: hide internal state of ascii() from users
r9631 seen, state = [], asciistate()
Dirkjan Ochtman
graphlog: move common code into function again, change function types
r9369 for rev, type, ctx, parents in dag:
char = ctx.node() in showparents and '@' or 'o'
displayer.show(ctx)
lines = displayer.hunk.pop(rev).split('\n')[:-1]
Peter Arrenbrecht
graphlog: hide internal state of ascii() from users
r9631 ascii(ui, state, type, char, lines, edgefn(seen, rev, parents))
Dirkjan Ochtman
graphlog: move common code into function again, change function types
r9369
Peter Arrenbrecht
graphlog: split the actual DAG grapher out into a separate method...
r7325 def graphlog(ui, repo, path=None, **opts):
"""show revision history alongside an ASCII revision graph
Martin Geisler
graphlog: wrap docstrings at 70 characters
r9259 Print a revision history alongside a revision graph drawn with
ASCII characters.
Peter Arrenbrecht
graphlog: split the actual DAG grapher out into a separate method...
r7325
Martin Geisler
graphlog: wrap docstrings at 70 characters
r9259 Nodes printed as an @ character are parents of the working
directory.
Peter Arrenbrecht
graphlog: split the actual DAG grapher out into a separate method...
r7325 """
Alpar Juttner
Graphlog extension adds a --graph option to log/in/out...
r7426 check_unsupported_flags(opts)
Dirkjan Ochtman
graphlog: reuse cmdutil.loglimit() instead of redefining
r7715 limit = cmdutil.loglimit(opts)
Peter Arrenbrecht
graphlog: refactor common grapher code...
r7370 start, stop = get_revs(repo, opts["rev"])
if start == nullrev:
Peter Arrenbrecht
graphlog: split the actual DAG grapher out into a separate method...
r7325 return
Peter Arrenbrecht
graphlog: refactor common grapher code...
r7370
Peter Arrenbrecht
graphlog: split the actual DAG grapher out into a separate method...
r7325 if path:
Dirkjan Ochtman
graphlog: import util module rather than selected functions
r7713 path = util.canonpath(repo.root, os.getcwd(), path)
Peter Arrenbrecht
graphlog: refactor common grapher code...
r7370 if path: # could be reset in canonpath
Nicolas Dumazet
graphlog: fix output when both a limit and a path are provided...
r10084 revdag = graphmod.filerevs(repo, path, start, stop, limit)
Peter Arrenbrecht
graphlog: split the actual DAG grapher out into a separate method...
r7325 else:
Nicolas Dumazet
cmdutil: replace sys.maxint with None as default value in loglimit...
r10111 if limit is not None:
stop = max(stop, start - limit + 1)
Peter Arrenbrecht
graphmod/graphlog: move log walks to graphmod
r8836 revdag = graphmod.revisions(repo, start, stop)
Peter Arrenbrecht
graphlog: split the actual DAG grapher out into a separate method...
r7325
Dirkjan Ochtman
graphlog: extract some setup code out of common functions
r9368 displayer = show_changeset(ui, repo, opts, buffered=True)
showparents = [ctx.node() for ctx in repo[None].parents()]
Dirkjan Ochtman
graphlog: simplify ascii drawing to process one cset at a time
r9371 generate(ui, revdag, displayer, showparents, asciiedges)
Dirkjan Ochtman
graphlog: extract large parts of repeated code from incoming/outgoing
r7716
def graphrevs(repo, nodes, opts):
limit = cmdutil.loglimit(opts)
Peter Arrenbrecht
graphmod/graphlog: extract nodelistwalk
r8837 nodes.reverse()
Nicolas Dumazet
cmdutil: replace sys.maxint with None as default value in loglimit...
r10111 if limit is not None:
Peter Arrenbrecht
graphmod/graphlog: extract nodelistwalk
r8837 nodes = nodes[:limit]
return graphmod.nodes(repo, nodes)
Dirkjan Ochtman
graphlog: extract large parts of repeated code from incoming/outgoing
r7716
def goutgoing(ui, repo, dest=None, **opts):
"""show the outgoing changesets alongside an ASCII revision graph
Peter Arrenbrecht
graphlog: split the actual DAG grapher out into a separate method...
r7325
Dirkjan Ochtman
graphlog: extract large parts of repeated code from incoming/outgoing
r7716 Print the outgoing changesets alongside a revision graph drawn with
ASCII characters.
Alpar Juttner
Graphlog extension adds a --graph option to log/in/out...
r7426
Dirkjan Ochtman
graphlog: extract large parts of repeated code from incoming/outgoing
r7716 Nodes printed as an @ character are parents of the working
directory.
Alpar Juttner
Graphlog extension adds a --graph option to log/in/out...
r7426 """
Dirkjan Ochtman
graphlog: extract large parts of repeated code from incoming/outgoing
r7716
check_unsupported_flags(opts)
Sune Foldager
interpret repo#name url syntax as branch instead of revision...
r10365 dest = ui.expandpath(dest or 'default-push', dest or 'default')
Sune Foldager
add -b/--branch option to clone, bundle, incoming, outgoing, pull, push
r10379 dest, branches = hg.parseurl(dest, opts.get('branch'))
Sune Foldager
interpret repo#name url syntax as branch instead of revision...
r10365 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
Matt Mackall
remoteui: move from cmdutil to hg
r11273 other = hg.repository(hg.remoteui(ui, opts), dest)
Alpar Juttner
Graphlog extension adds a --graph option to log/in/out...
r7426 if revs:
revs = [repo.lookup(rev) for rev in revs]
ui.status(_('comparing with %s\n') % url.hidepassword(dest))
Dirkjan Ochtman
move discovery methods from localrepo into new discovery module
r11301 o = discovery.findoutgoing(repo, other, force=opts.get('force'))
Alpar Juttner
Graphlog extension adds a --graph option to log/in/out...
r7426 if not o:
ui.status(_("no changes found\n"))
return
Dirkjan Ochtman
graphlog: extract large parts of repeated code from incoming/outgoing
r7716
Alpar Juttner
Graphlog extension adds a --graph option to log/in/out...
r7426 o = repo.changelog.nodesbetween(o, revs)[0]
Dirkjan Ochtman
graphlog: extract large parts of repeated code from incoming/outgoing
r7716 revdag = graphrevs(repo, o, opts)
Dirkjan Ochtman
graphlog: extract some setup code out of common functions
r9368 displayer = show_changeset(ui, repo, opts, buffered=True)
showparents = [ctx.node() for ctx in repo[None].parents()]
Dirkjan Ochtman
graphlog: simplify ascii drawing to process one cset at a time
r9371 generate(ui, revdag, displayer, showparents, asciiedges)
Alpar Juttner
Graphlog extension adds a --graph option to log/in/out...
r7426
def gincoming(ui, repo, source="default", **opts):
"""show the incoming changesets alongside an ASCII revision graph
Martin Geisler
graphlog: wrap docstrings at 70 characters
r9259 Print the incoming changesets alongside a revision graph drawn with
ASCII characters.
Alpar Juttner
Graphlog extension adds a --graph option to log/in/out...
r7426
Martin Geisler
graphlog: wrap docstrings at 70 characters
r9259 Nodes printed as an @ character are parents of the working
directory.
Alpar Juttner
Graphlog extension adds a --graph option to log/in/out...
r7426 """
check_unsupported_flags(opts)
Sune Foldager
add -b/--branch option to clone, bundle, incoming, outgoing, pull, push
r10379 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
Matt Mackall
remoteui: move from cmdutil to hg
r11273 other = hg.repository(hg.remoteui(repo, opts), source)
Sune Foldager
interpret repo#name url syntax as branch instead of revision...
r10365 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
Alpar Juttner
Graphlog extension adds a --graph option to log/in/out...
r7426 ui.status(_('comparing with %s\n') % url.hidepassword(source))
if revs:
revs = [other.lookup(rev) for rev in revs]
Dirkjan Ochtman
move discovery methods from localrepo into new discovery module
r11301 incoming = discovery.findincoming(repo, other, heads=revs,
force=opts["force"])
Alpar Juttner
Graphlog extension adds a --graph option to log/in/out...
r7426 if not incoming:
try:
os.unlink(opts["bundle"])
except:
pass
ui.status(_("no changes found\n"))
return
cleanup = None
try:
Dirkjan Ochtman
graphlog: extract large parts of repeated code from incoming/outgoing
r7716
Alpar Juttner
Graphlog extension adds a --graph option to log/in/out...
r7426 fname = opts["bundle"]
if fname or not other.local():
# create a bundle (uncompressed if other repo is not local)
if revs is None:
cg = other.changegroup(incoming, "incoming")
else:
cg = other.changegroupsubset(incoming, revs, 'incoming')
bundletype = other.local() and "HG10BZ" or "HG10UN"
fname = cleanup = changegroup.writebundle(cg, fname, bundletype)
# keep written bundle?
if opts["bundle"]:
cleanup = None
if not other.local():
# use the created uncompressed bundlerepo
other = bundlerepo.bundlerepository(ui, repo.root, fname)
chlist = other.changelog.nodesbetween(incoming, revs)[0]
Dirkjan Ochtman
graphlog: extract large parts of repeated code from incoming/outgoing
r7716 revdag = graphrevs(other, chlist, opts)
Dirkjan Ochtman
graphlog: extract some setup code out of common functions
r9368 displayer = show_changeset(ui, other, opts, buffered=True)
showparents = [ctx.node() for ctx in repo[None].parents()]
Dirkjan Ochtman
graphlog: simplify ascii drawing to process one cset at a time
r9371 generate(ui, revdag, displayer, showparents, asciiedges)
Alpar Juttner
Graphlog extension adds a --graph option to log/in/out...
r7426
finally:
if hasattr(other, 'close'):
other.close()
if cleanup:
os.unlink(cleanup)
def uisetup(ui):
'''Initialize the extension.'''
_wrapcmd(ui, 'log', commands.table, graphlog)
_wrapcmd(ui, 'incoming', commands.table, gincoming)
_wrapcmd(ui, 'outgoing', commands.table, goutgoing)
def _wrapcmd(ui, cmd, table, wrapfn):
'''wrap the command'''
def graph(orig, *args, **kwargs):
if kwargs['graph']:
return wrapfn(*args, **kwargs)
return orig(*args, **kwargs)
entry = extensions.wrapcommand(table, cmd, graph)
Jim Correia
log-like commands now use -G for --graph, -g for --git
r7763 entry[1].append(('G', 'graph', None, _("show the revision DAG")))
Alpar Juttner
Graphlog extension adds a --graph option to log/in/out...
r7426
Joel Rosdahl
Add graphlog extension
r4344 cmdtable = {
"glog":
Thomas Arendsen Hein
Updated command tables in commands.py and hgext extensions....
r4730 (graphlog,
FUJIWARA Katsunori
help: show value requirement and multiple occurrence of options...
r11321 [('l', 'limit', '',
_('limit number of changes displayed'), _('NUM')),
Thomas Arendsen Hein
Updated command tables in commands.py and hgext extensions....
r4730 ('p', 'patch', False, _('show patch')),
FUJIWARA Katsunori
help: show value requirement and multiple occurrence of options...
r11321 ('r', 'rev', [],
_('show the specified revision or range'), _('REV')),
Thomas Arendsen Hein
Introduce templateopts and logopts to reduce duplicate option definitions.
r6192 ] + templateopts,
Thomas Arendsen Hein
glog shows at most one file: correct synopsis
r5942 _('hg glog [OPTION]... [FILE]')),
Joel Rosdahl
Add graphlog extension
r4344 }