comparison hgext/graphlog.py @ 14043:1c1e1232abdc

graphlog: make use of graphmod's revset support
author Alexander Solovyov <alexander@solovyov.net>
date Sat, 23 Apr 2011 15:04:15 +0200
parents 9966c95b8c4f
children 8670e3694b85
comparison
equal deleted inserted replaced
14042:9966c95b8c4f 14043:1c1e1232abdc
10 This extension adds a --graph option to the incoming, outgoing and log 10 This extension adds a --graph option to the incoming, outgoing and log
11 commands. When this options is given, an ASCII representation of the 11 commands. When this options is given, an ASCII representation of the
12 revision graph is also shown. 12 revision graph is also shown.
13 ''' 13 '''
14 14
15 import os
16 from mercurial.cmdutil import revrange, show_changeset 15 from mercurial.cmdutil import revrange, show_changeset
17 from mercurial.commands import templateopts 16 from mercurial.commands import templateopts
18 from mercurial.i18n import _ 17 from mercurial.i18n import _
19 from mercurial.node import nullrev 18 from mercurial.node import nullrev
20 from mercurial import cmdutil, commands, extensions 19 from mercurial import cmdutil, commands, extensions
214 return (max(revs), min(revs)) 213 return (max(revs), min(revs))
215 else: 214 else:
216 return (len(repo) - 1, 0) 215 return (len(repo) - 1, 0)
217 216
218 def check_unsupported_flags(opts): 217 def check_unsupported_flags(opts):
219 for op in ["follow", "follow_first", "date", "copies", "keyword", "remove", 218 for op in ["follow_first", "copies", "newest_first"]:
220 "only_merges", "user", "branch", "only_branch", "prune",
221 "newest_first", "no_merges", "include", "exclude"]:
222 if op in opts and opts[op]: 219 if op in opts and opts[op]:
223 raise util.Abort(_("--graph option is incompatible with --%s") 220 raise util.Abort(_("-G/--graph option is incompatible with --%s")
224 % op.replace("_", "-")) 221 % op.replace("_", "-"))
222
223 def revset(pats, opts):
224 """Return revset str built of revisions, log options and file patterns.
225 """
226 opt2revset = dict(only_merges='merge',
227 only_branch='branch',
228 no_merges='not merge',
229 include='file',
230 exclude='not file',
231 prune='not follow')
232 revset = []
233 for op, val in opts.iteritems():
234 if not val:
235 continue
236 revop = opt2revset.get(op, op)
237 if op in ('follow', 'only_merges', 'no_merges'):
238 revset.append('%s()' % revop)
239 elif op in ("date", "keyword", "remove", "user", "branch",
240 "only_branch", "prune"):
241 revset.append('%s(%s)' % (op, val))
242 elif op in ('include', 'exclude'):
243 for f in val:
244 revset.append('%s(%r)' % (op, f))
245 elif op == 'rev':
246 revset.extend(val)
247
248 for path in pats:
249 revset.append('file(%r)' % path)
250
251 revset = ' and '.join(revset) or 'all()'
252 # we want reverted revset to build graph
253 revset = 'reverse(%s)' % revset
254 if opts['limit']:
255 revset = 'limit(%s, %s)' % (revset, opts['limit'])
256 return revset
225 257
226 def generate(ui, dag, displayer, showparents, edgefn): 258 def generate(ui, dag, displayer, showparents, edgefn):
227 seen, state = [], asciistate() 259 seen, state = [], asciistate()
228 for rev, type, ctx, parents in dag: 260 for rev, type, ctx, parents in dag:
229 char = ctx.node() in showparents and '@' or 'o' 261 char = ctx.node() in showparents and '@' or 'o'
231 lines = displayer.hunk.pop(rev).split('\n')[:-1] 263 lines = displayer.hunk.pop(rev).split('\n')[:-1]
232 displayer.flush(rev) 264 displayer.flush(rev)
233 ascii(ui, state, type, char, lines, edgefn(seen, rev, parents)) 265 ascii(ui, state, type, char, lines, edgefn(seen, rev, parents))
234 displayer.close() 266 displayer.close()
235 267
236 def graphlog(ui, repo, path=None, **opts): 268 def graphlog(ui, repo, *pats, **opts):
237 """show revision history alongside an ASCII revision graph 269 """show revision history alongside an ASCII revision graph
238 270
239 Print a revision history alongside a revision graph drawn with 271 Print a revision history alongside a revision graph drawn with
240 ASCII characters. 272 ASCII characters.
241 273
242 Nodes printed as an @ character are parents of the working 274 Nodes printed as an @ character are parents of the working
243 directory. 275 directory.
244 """ 276 """
245 277
246 check_unsupported_flags(opts) 278 check_unsupported_flags(opts)
247 limit = cmdutil.loglimit(opts) 279
248 start, stop = get_revs(repo, opts["rev"]) 280 revs = revrange(repo, [revset(pats, opts)])
249 if start == nullrev: 281 revdag = graphmod.dagwalker(repo, revs)
250 return
251
252 if path: # could be reset in canonpath
253 revdag = graphmod.filerevs(repo, path, start, stop, limit)
254 else:
255 if limit is not None:
256 stop = max(stop, start - limit + 1)
257 revdag = graphmod.revisions(repo, start, stop)
258 282
259 displayer = show_changeset(ui, repo, opts, buffered=True) 283 displayer = show_changeset(ui, repo, opts, buffered=True)
260 showparents = [ctx.node() for ctx in repo[None].parents()] 284 showparents = [ctx.node() for ctx in repo[None].parents()]
261 generate(ui, revdag, displayer, showparents, asciiedges) 285 generate(ui, revdag, displayer, showparents, asciiedges)
262 286
315 339
316 def _wrapcmd(ui, cmd, table, wrapfn): 340 def _wrapcmd(ui, cmd, table, wrapfn):
317 '''wrap the command''' 341 '''wrap the command'''
318 def graph(orig, *args, **kwargs): 342 def graph(orig, *args, **kwargs):
319 if kwargs['graph']: 343 if kwargs['graph']:
320 try: 344 return wrapfn(*args, **kwargs)
321 return wrapfn(*args, **kwargs)
322 except TypeError, e:
323 if len(args) > wrapfn.func_code.co_argcount:
324 raise util.Abort(_('--graph option allows at most one file'))
325 raise
326 return orig(*args, **kwargs) 345 return orig(*args, **kwargs)
327 entry = extensions.wrapcommand(table, cmd, graph) 346 entry = extensions.wrapcommand(table, cmd, graph)
328 entry[1].append(('G', 'graph', None, _("show the revision DAG"))) 347 entry[1].append(('G', 'graph', None, _("show the revision DAG")))
329 348
330 cmdtable = { 349 cmdtable = {