Mercurial > hg
changeset 19722:bf15935b68a3
hgweb: add revset syntax support to search
This mode 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
- the repo can be actually matched against this tree, i.e. it has only existent
function/operators and revisions/tags/bookmarks specified are correct
- no revset regexes are used in the query (strings which start with 're:')
- only functions explicitly marked as safe in revset.py are used in the query
Add several new tests for different parsing conditions and exception handling.
author | Alexander Plavin <alexander@plav.in> |
---|---|
date | Fri, 06 Sep 2013 13:30:56 +0400 |
parents | d8ca6d965230 |
children | 7999f4fa155a |
files | mercurial/hgweb/webcommands.py tests/test-hgweb-commands.t |
diffstat | 2 files changed, 186 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- a/mercurial/hgweb/webcommands.py Fri Sep 06 13:30:56 2013 +0400 +++ b/mercurial/hgweb/webcommands.py Fri Sep 06 13:30:56 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, RepoLookupError, Abort +from mercurial import 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. @@ -111,6 +113,7 @@ def _search(web, req, tmpl): MODE_REVISION = 'rev' MODE_KEYWORD = 'keyword' + MODE_REVSET = 'revset' def revsearch(ctx): yield ctx @@ -143,19 +146,56 @@ yield ctx + def revsetsearch(revs): + for r in revs: + yield web.repo[r] + searchfuncs = { MODE_REVISION: revsearch, MODE_KEYWORD: keywordsearch, + MODE_REVSET: revsetsearch, } def getsearchmode(query): try: ctx = web.repo[query] except (error.RepoError, error.LookupError): - return MODE_KEYWORD, query + # query is not an exact revision pointer, need to + # decide if it's a revset expession or keywords + pass else: return MODE_REVISION, ctx + revdef = 'reverse(%s)' % query + try: + tree, pos = revset.parse(revdef) + except ParseError: + # can't parse to a revset tree + return MODE_KEYWORD, query + + if revset.depth(tree) <= 2: + # no revset syntax used + return MODE_KEYWORD, query + + if util.any((token, (value or '')[:3]) == ('string', 're:') + for token, value, pos in revset.tokenize(revdef)): + return MODE_KEYWORD, query + + funcsused = revset.funcsused(tree) + if not funcsused.issubset(revset.safesymbols): + return MODE_KEYWORD, query + + mfunc = revset.match(web.repo.ui, revdef) + try: + revs = mfunc(web.repo, list(web.repo)) + return MODE_REVSET, revs + # ParseError: wrongly placed tokens, wrongs arguments, etc + # RepoLookupError: no such revision, e.g. in 'revision:' + # Abort: bookmark/tag not exists + # LookupError: ambiguous identifier, e.g. in '(bc)' on a large repo + except (ParseError, RepoLookupError, Abort, LookupError): + return MODE_KEYWORD, query + def changelist(**map): count = 0
--- a/tests/test-hgweb-commands.t Fri Sep 06 13:30:56 2013 +0400 +++ b/tests/test-hgweb-commands.t Fri Sep 06 13:30:56 2013 +0400 @@ -540,6 +540,151 @@ $ "$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' + 200 Script output follows + + + # HG changesets search + # Node ID cad8025a2e87f88c06259790adfa15acb4080123 + # Query "tip^" + + changeset: 1d22e65f027e5a0609357e7d8e7508cd2ba5d2fe + revision: 2 + user: test + date: Thu, 01 Jan 1970 00:00:00 +0000 + summary: branch + branch: stable + + + $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT 'log?rev=last(all(),2)^&style=raw' + 200 Script output follows + + + # HG changesets search + # Node ID cad8025a2e87f88c06259790adfa15acb4080123 + # Query "last(all(),2)^" + + changeset: 1d22e65f027e5a0609357e7d8e7508cd2ba5d2fe + revision: 2 + user: test + date: Thu, 01 Jan 1970 00:00:00 +0000 + summary: branch + branch: stable + + changeset: a4f92ed23982be056b9852de5dfe873eaac7f0de + revision: 1 + user: test + date: Thu, 01 Jan 1970 00:00:00 +0000 + summary: Added tag 1.0 for changeset 2ef0ac749a14 + branch: default + + + $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT 'log?rev=last(all(,2)^&style=raw' + 200 Script output follows + + + # HG changesets search + # Node ID cad8025a2e87f88c06259790adfa15acb4080123 + # Query "last(all(,2)^" + + + $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT 'log?rev=last(al(),2)^&style=raw' + 200 Script output follows + + + # HG changesets search + # Node ID cad8025a2e87f88c06259790adfa15acb4080123 + # Query "last(al(),2)^" + + + $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT 'log?rev=bookmark(anotherthing)&style=raw' + 200 Script output follows + + + # HG changesets search + # Node ID cad8025a2e87f88c06259790adfa15acb4080123 + # Query "bookmark(anotherthing)" + + changeset: 2ef0ac749a14e4f57a5a822464a0902c6f7f448f + revision: 0 + user: test + date: Thu, 01 Jan 1970 00:00:00 +0000 + summary: base + tag: 1.0 + bookmark: anotherthing + + + $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT 'log?rev=bookmark(abc)&style=raw' + 200 Script output follows + + + # HG changesets search + # Node ID cad8025a2e87f88c06259790adfa15acb4080123 + # Query "bookmark(abc)" + + + $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT 'log?rev=deadbeef:&style=raw' + 200 Script output follows + + + # HG changesets search + # Node ID cad8025a2e87f88c06259790adfa15acb4080123 + # Query "deadbeef:" + + + + $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT 'log?rev=user("test")&style=raw' + 200 Script output follows + + + # HG changesets search + # Node ID cad8025a2e87f88c06259790adfa15acb4080123 + # Query "user("test")" + + changeset: cad8025a2e87f88c06259790adfa15acb4080123 + revision: 3 + user: test + date: Thu, 01 Jan 1970 00:00:00 +0000 + summary: branch commit with null character: \x00 (esc) + branch: unstable + tag: tip + bookmark: something + + changeset: 1d22e65f027e5a0609357e7d8e7508cd2ba5d2fe + revision: 2 + user: test + date: Thu, 01 Jan 1970 00:00:00 +0000 + summary: branch + branch: stable + + changeset: a4f92ed23982be056b9852de5dfe873eaac7f0de + revision: 1 + user: test + date: Thu, 01 Jan 1970 00:00:00 +0000 + summary: Added tag 1.0 for changeset 2ef0ac749a14 + branch: default + + changeset: 2ef0ac749a14e4f57a5a822464a0902c6f7f448f + revision: 0 + user: test + date: Thu, 01 Jan 1970 00:00:00 +0000 + summary: base + tag: 1.0 + bookmark: anotherthing + + + $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT 'log?rev=user("re:test")&style=raw' + 200 Script output follows + + + # HG changesets search + # Node ID cad8025a2e87f88c06259790adfa15acb4080123 + # Query "user("re:test")" + + + File-related $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT 'file/1/foo/?style=raw'