Mercurial > hg-stable
changeset 14511:30506b894359
filesets: introduce basic fileset expression parser
author | Matt Mackall <mpm@selenic.com> |
---|---|
date | Wed, 01 Jun 2011 19:12:18 -0500 |
parents | eccbb9980ada |
children | 8c8b55733cbd |
files | mercurial/commands.py mercurial/fileset.py tests/test-debugcomplete.t |
diffstat | 3 files changed, 89 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- a/mercurial/commands.py Thu Jun 02 00:43:34 2011 +0300 +++ b/mercurial/commands.py Wed Jun 01 19:12:18 2011 -0500 @@ -13,7 +13,7 @@ import patch, help, url, encoding, templatekw, discovery import archival, changegroup, cmdutil, sshserver, hbisect, hgweb, hgweb.server import merge as mergemod -import minirst, revset +import minirst, revset, fileset import dagparser, context, simplemerge import random, setdiscovery, treediscovery, dagutil @@ -1597,6 +1597,13 @@ localrevs = opts.get('local_head') doit(localrevs, remoterevs) +@command('debugfileset', [], ('REVSPEC')) +def debugfileset(ui, repo, expr): + '''parse and apply a fileset specification''' + if ui.verbose: + tree = fileset.parse(expr)[0] + ui.note(tree, "\n") + @command('debugfsinfo', [], _('[PATH]')) def debugfsinfo(ui, path = "."): """show information detected about current filesystem"""
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mercurial/fileset.py Wed Jun 01 19:12:18 2011 -0500 @@ -0,0 +1,79 @@ +# fileset.py - file set queries for mercurial +# +# Copyright 2010 Matt Mackall <mpm@selenic.com> +# +# This software may be used and distributed according to the terms of the +# GNU General Public License version 2 or any later version. + +import parser, error +from i18n import _ + +elements = { + "(": (20, ("group", 1, ")"), ("func", 1, ")")), + "-": (5, ("negate", 19), ("minus", 5)), + "not": (10, ("not", 10)), + "!": (10, ("not", 10)), + "and": (5, None, ("and", 5)), + "&": (5, None, ("and", 5)), + "or": (4, None, ("or", 4)), + "|": (4, None, ("or", 4)), + "+": (4, None, ("or", 4)), + ",": (2, None, ("list", 2)), + ")": (0, None, None), + "symbol": (0, ("symbol",), None), + "string": (0, ("string",), None), + "end": (0, None, None), +} + +keywords = set(['and', 'or', 'not']) + +def tokenize(program): + pos, l = 0, len(program) + while pos < l: + c = program[pos] + if c.isspace(): # skip inter-token whitespace + pass + elif c in "(),-|&+!": # handle simple operators + yield (c, None, pos) + elif (c in '"\'' or c == 'r' and + program[pos:pos + 2] in ("r'", 'r"')): # handle quoted strings + if c == 'r': + pos += 1 + c = program[pos] + decode = lambda x: x + else: + decode = lambda x: x.decode('string-escape') + pos += 1 + s = pos + while pos < l: # find closing quote + d = program[pos] + if d == '\\': # skip over escaped characters + pos += 2 + continue + if d == c: + yield ('string', decode(program[s:pos]), s) + break + pos += 1 + else: + raise error.ParseError(_("unterminated string"), s) + elif c.isalnum() or c in '.*{}[]?' or ord(c) > 127: # gather up a symbol/keyword + s = pos + pos += 1 + while pos < l: # find end of symbol + d = program[pos] + if not (d.isalnum() or d in ".*{}[]?," or ord(d) > 127): + break + pos += 1 + sym = program[s:pos] + if sym in keywords: # operator keywords + yield (sym, None, s) + else: + yield ('symbol', sym, s) + pos -= 1 + else: + raise error.ParseError(_("syntax error"), pos) + pos += 1 + yield ('end', None, pos) + +parse = parser.parser(tokenize, elements).parse +
--- a/tests/test-debugcomplete.t Thu Jun 02 00:43:34 2011 +0300 +++ b/tests/test-debugcomplete.t Wed Jun 01 19:12:18 2011 -0500 @@ -76,6 +76,7 @@ debugdata debugdate debugdiscovery + debugfileset debugfsinfo debuggetbundle debugignore @@ -222,6 +223,7 @@ debugdata: changelog, manifest debugdate: extended debugdiscovery: old, nonheads, ssh, remotecmd, insecure + debugfileset: debugfsinfo: debuggetbundle: head, common, type debugignore: