##// END OF EJS Templates
fileset: basic pattern and boolean support...
Matt Mackall -
r14551:68d814a3 default
parent child Browse files
Show More
@@ -1603,6 +1603,10 b' def debugfileset(ui, repo, expr):'
1603 if ui.verbose:
1603 if ui.verbose:
1604 tree = fileset.parse(expr)[0]
1604 tree = fileset.parse(expr)[0]
1605 ui.note(tree, "\n")
1605 ui.note(tree, "\n")
1606 matcher = lambda x: scmutil.match(repo, x, default='glob')
1607
1608 for f in fileset.getfileset(repo[None], matcher, expr):
1609 ui.write("%s\n" % f)
1606
1610
1607 @command('debugfsinfo', [], _('[PATH]'))
1611 @command('debugfsinfo', [], _('[PATH]'))
1608 def debugfsinfo(ui, path = "."):
1612 def debugfsinfo(ui, path = "."):
@@ -5,7 +5,7 b''
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 import parser, error
8 import parser, error, match
9 from i18n import _
9 from i18n import _
10
10
11 elements = {
11 elements = {
@@ -27,6 +27,8 b' elements = {'
27
27
28 keywords = set(['and', 'or', 'not'])
28 keywords = set(['and', 'or', 'not'])
29
29
30 globchars = ".*{}[]?/\\"
31
30 def tokenize(program):
32 def tokenize(program):
31 pos, l = 0, len(program)
33 pos, l = 0, len(program)
32 while pos < l:
34 while pos < l:
@@ -56,13 +58,13 b' def tokenize(program):'
56 pos += 1
58 pos += 1
57 else:
59 else:
58 raise error.ParseError(_("unterminated string"), s)
60 raise error.ParseError(_("unterminated string"), s)
59 elif c.isalnum() or c in '.*{}[]?' or ord(c) > 127:
61 elif c.isalnum() or c in globchars or ord(c) > 127:
60 # gather up a symbol/keyword
62 # gather up a symbol/keyword
61 s = pos
63 s = pos
62 pos += 1
64 pos += 1
63 while pos < l: # find end of symbol
65 while pos < l: # find end of symbol
64 d = program[pos]
66 d = program[pos]
65 if not (d.isalnum() or d in ".*{}[]?," or ord(d) > 127):
67 if not (d.isalnum() or d in globchars or ord(d) > 127):
66 break
68 break
67 pos += 1
69 pos += 1
68 sym = program[s:pos]
70 sym = program[s:pos]
@@ -78,3 +80,63 b' def tokenize(program):'
78
80
79 parse = parser.parser(tokenize, elements).parse
81 parse = parser.parser(tokenize, elements).parse
80
82
83 def getstring(x, err):
84 if x and (x[0] == 'string' or x[0] == 'symbol'):
85 return x[1]
86 raise error.ParseError(err)
87
88 def getset(mctx, x):
89 if not x:
90 raise error.ParseError(_("missing argument"))
91 return methods[x[0]](mctx, *x[1:])
92
93 def stringset(mctx, x):
94 m = mctx.matcher([x])
95 return [f for f in mctx.subset if m(f)]
96
97 def andset(mctx, x, y):
98 return getset(mctx.narrow(getset(mctx, x)), y)
99
100 def orset(mctx, x, y):
101 # needs optimizing
102 xl = getset(mctx, x)
103 yl = getset(mctx, y)
104 return xl + [f for f in yl if f not in xl]
105
106 def notset(mctx, x):
107 s = set(getset(mctx, x))
108 return [r for r in mctx.subset if r not in s]
109
110 def listset(mctx, a, b):
111 raise error.ParseError(_("can't use a list in this context"))
112
113 methods = {
114 'string': stringset,
115 'symbol': stringset,
116 'and': andset,
117 'or': orset,
118 'list': listset,
119 'group': getset,
120 'not': notset
121 }
122
123 class matchctx(object):
124 def __init__(self, ctx, matchfn, subset=None):
125 self.ctx = ctx
126 self.matchfn = matchfn
127 self.subset = subset
128 if subset is None:
129 self.subset = ctx.walk(matchfn([])) # optimize this later
130 def matcher(self, pattern):
131 return self.matchfn(pattern)
132 def filter(self, files):
133 return [f for f in files if f in self.subset]
134 def narrow(self, files):
135 return matchctx(self.ctx, self.matchfn,
136 self.filter(files))
137
138 def getfileset(ctx, matchfn, expr):
139 tree, pos = parse(expr)
140 if (pos != len(expr)):
141 raise error.ParseError("invalid token", pos)
142 return getset(matchctx(ctx, matchfn), tree)
General Comments 0
You need to be logged in to leave comments. Login now