Patchwork [2,of,3,RFC] hgweb: add revsetsearch() function when query can be parsed as a revset

login
register
mail settings
Submitter Alexander Plavin
Date Aug. 6, 2013, 9:30 p.m.
Message ID <b4310435ce2ebeb2b658.1375824657@debian-alexander.dolgopa>
Download mbox | patch
Permalink /patch/2007/
State Superseded
Headers show

Comments

Alexander Plavin - Aug. 6, 2013, 9:30 p.m.
# HG changeset patch
# User Alexander Plavin <alexander@plav.in>
# Date 1375823774 -14400
#      Wed Aug 07 01:16:14 2013 +0400
# Node ID b4310435ce2ebeb2b65871a63060c97b8a04c608
# Parent  0afbd16e3fc2427180e91a0a5293f784b014d8f1
hgweb: add revsetsearch() function when query can be parsed as a revset

This function is used when all the conditions are met:
- 'reverse(%s)' % query string can be parsed to a revset tree
- this tree has depth more than two, i.e. the query has some part of
revset syntax used
- this tree can be actually run, i.e. contains only correctly-named functions
and operators

Otherwise keywordsearch() or revsearch() functions are used as before.

Add several new tests for different parsing conditions and exception handling.

Patch

diff -r 0afbd16e3fc2 -r b4310435ce2e mercurial/hgweb/webcommands.py
--- a/mercurial/hgweb/webcommands.py	Wed Aug 07 01:21:31 2013 +0400
+++ b/mercurial/hgweb/webcommands.py	Wed Aug 07 01:16:14 2013 +0400
@@ -16,6 +16,8 @@ 
 from mercurial import help as helpmod
 from mercurial import scmutil
 from mercurial.i18n import _
+from mercurial.error import ParseError, Abort
+from mercurial import parser, revset
 
 # __all__ is populated with the allowed commands. Be sure to add to it if
 # you're adding a new command, or the new command won't work.
@@ -141,9 +143,15 @@ 
 
             yield ctx
 
+    def revsetsearch():
+        revs = revset.match(web.repo.ui, revdef)(web.repo, list(web.repo))
+        for r in revs:
+            yield web.repo[r]
+
     searchfuncs = {
         'rev': revsearch,
         'kw': keywordsearch,
+        'revset': revsetsearch,
     }
 
     def changelist(**map):
@@ -193,7 +201,28 @@ 
         web.repo[query]
         modename = 'rev'
     except (error.RepoError, error.LookupError):
-        modename = 'kw'
+        # query is not an exact revision pointer, now decide if
+        # it's a revset expession or keywords
+        revdef = 'reverse(%s)' % query
+        try:
+            p = parser.parser(revset.tokenize, revset.elements)
+            tree, pos = p.parse(revdef)
+        except ParseError:
+            # can't parse to a tree
+            modename = 'kw'
+        else:
+            if revset.depth(tree) > 2:
+                mfunc = revset.match(None, revdef)
+                try:
+                    # try running against empty subset
+                    mfunc(web.repo, [])
+                    modename = 'revset'
+                except (ParseError, Abort):
+                    # can't run the revset query, e.g. some function misspelled
+                    modename = 'kw'
+            else:
+                # no revset syntax used
+                modename = 'kw'
 
     searchfunc = searchfuncs[modename]
 
diff -r 0afbd16e3fc2 -r b4310435ce2e tests/test-hgweb-commands.t
--- a/tests/test-hgweb-commands.t	Wed Aug 07 01:21:31 2013 +0400
+++ b/tests/test-hgweb-commands.t	Wed Aug 07 01:16:14 2013 +0400
@@ -537,6 +537,22 @@ 
   $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT 'log?rev=stable&style=raw' | grep 'revision:'
   revision:    2
 
+Search with revset syntax
+
+  $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT 'log?rev=tip^&style=raw' | grep 'revision:'
+  revision:    2
+  $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT 'log?rev=last(all(),2)^&style=raw' | grep 'revision:'
+  revision:    2
+  revision:    1
+  $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT 'log?rev=last(all(,2)^&style=raw' | grep 'revision:'
+  [1]
+  $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT 'log?rev=last(al(),2)^&style=raw' | grep 'revision:'
+  [1]
+  $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT 'log?rev=bookmark(anotherthing)&style=raw' | grep 'revision:'
+  revision:    0
+  $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT 'log?rev=bookmark(abc)&style=raw' | grep 'revision:'
+  [1]
+
 File-related
 
   $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT 'file/1/foo/?style=raw'