diff hgext/graphlog.py @ 16316:0f1e621d3d3b

graphlog: handle old-style --rev values --rev options cannot be merged into a single revset because we do not know if they are valid revset or old-style revision specifications, like 'foo-bar' tags. Instead, a base revision set is generated with scmutil.revrange() then filtered with the revset built from log options. It also fixes incorrect or hostile expressions passed in --rev.
author Patrick Mezard <patrick@mezard.eu>
date Thu, 29 Mar 2012 22:42:03 +0200
parents 16ec050490fc
children 17deb6bbfbab
line wrap: on
line diff
--- a/hgext/graphlog.py	Thu Mar 29 17:13:23 2012 +0200
+++ b/hgext/graphlog.py	Thu Mar 29 22:42:03 2012 +0200
@@ -18,6 +18,7 @@
 from mercurial.node import nullrev
 from mercurial import cmdutil, commands, extensions, scmutil
 from mercurial import hg, util, graphmod, templatekw
+from mercurial import revset as revsetmod
 
 cmdtable = {}
 command = cmdutil.command(cmdtable)
@@ -272,16 +273,20 @@
 
 def revset(repo, pats, opts):
     """Return (expr, filematcher) where expr is a revset string built
-    of revisions, log options and file patterns. If --stat or --patch
-    are not passed filematcher is None. Otherwise it a a callable
-    taking a revision number and returning a match objects filtering
-    the files to be detailed when displaying the revision.
+    log options and file patterns, or None. Note that --rev options
+    are ignored when building expr because we do not know if they are
+    proper revsets or legacy expressions like a 'foo-bar' tags. If
+    --stat or --patch are not passed filematcher is None. Otherwise it
+    a a callable taking a revision number and returning a match
+    objects filtering the files to be detailed when displaying the
+    revision.
     """
     opt2revset = {
         'follow':           ('follow()', None),
         'follow_first':     ('_followfirst()', None),
         'no_merges':        ('not merge()', None),
         'only_merges':      ('merge()', None),
+        '_matchfiles':      ('_matchfiles(%(val)s)', None),
         'date':             ('date(%(val)r)', None),
         'branch':           ('branch(%(val)r)', ' or '),
         '_patslog':         ('filelog(%(val)r)', ' or '),
@@ -290,7 +295,6 @@
         'keyword':          ('keyword(%(val)r)', ' or '),
         'prune':            ('not (%(val)r or ancestors(%(val)r))', ' and '),
         'user':             ('user(%(val)r)', ' or '),
-        'rev':              ('%(val)s', ' or '),
         }
 
     opts = dict(opts)
@@ -343,7 +347,7 @@
         for p in opts.get('exclude', []):
             matchargs.append('x:' + p)
         matchargs = ','.join(('%r' % p) for p in matchargs)
-        opts['rev'] = opts.get('rev', []) + ['_matchfiles(%s)' % matchargs]
+        opts['_matchfiles'] = matchargs
     else:
         if follow:
             if followfirst:
@@ -385,7 +389,7 @@
     if revset:
         revset = '(' + ' and '.join(revset) + ')'
     else:
-        revset = 'all()'
+        revset = None
     return revset, filematcher
 
 def generate(ui, dag, displayer, showparents, edgefn, getrenamed=None,
@@ -431,7 +435,13 @@
     check_unsupported_flags(pats, opts)
 
     expr, filematcher = revset(repo, pats, opts)
-    revs = sorted(scmutil.revrange(repo, [expr]), reverse=1)
+    if opts.get('rev'):
+        revs = scmutil.revrange(repo, opts['rev'])
+    else:
+        revs = range(len(repo))
+    if expr:
+        revs = revsetmod.match(repo.ui, expr)(repo, revs)
+    revs = sorted(revs, reverse=1)
     limit = cmdutil.loglimit(opts)
     if limit is not None:
         revs = revs[:limit]