##// END OF EJS Templates
minifileset: fix on Python 3...
Augie Fackler -
r37893:9c98cb30 default
parent child Browse files
Show More
@@ -1,85 +1,87 b''
1 # minifileset.py - a simple language to select files
1 # minifileset.py - a simple language to select files
2 #
2 #
3 # Copyright 2017 Facebook, Inc.
3 # Copyright 2017 Facebook, Inc.
4 #
4 #
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 from __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 from .i18n import _
10 from .i18n import _
11 from . import (
11 from . import (
12 error,
12 error,
13 fileset,
13 fileset,
14 pycompat,
14 )
15 )
15
16
16 def _compile(tree):
17 def _compile(tree):
17 if not tree:
18 if not tree:
18 raise error.ParseError(_("missing argument"))
19 raise error.ParseError(_("missing argument"))
19 op = tree[0]
20 op = tree[0]
20 if op in {'symbol', 'string', 'kindpat'}:
21 if op in {'symbol', 'string', 'kindpat'}:
21 name = fileset.getpattern(tree, {'path'}, _('invalid file pattern'))
22 name = fileset.getpattern(tree, {'path'}, _('invalid file pattern'))
22 if name.startswith('**'): # file extension test, ex. "**.tar.gz"
23 if name.startswith('**'): # file extension test, ex. "**.tar.gz"
23 ext = name[2:]
24 ext = name[2:]
24 for c in ext:
25 for c in pycompat.bytestr(ext):
25 if c in '*{}[]?/\\':
26 if c in '*{}[]?/\\':
26 raise error.ParseError(_('reserved character: %s') % c)
27 raise error.ParseError(_('reserved character: %s') % c)
27 return lambda n, s: n.endswith(ext)
28 return lambda n, s: n.endswith(ext)
28 elif name.startswith('path:'): # directory or full path test
29 elif name.startswith('path:'): # directory or full path test
29 p = name[5:] # prefix
30 p = name[5:] # prefix
30 pl = len(p)
31 pl = len(p)
31 f = lambda n, s: n.startswith(p) and (len(n) == pl or n[pl] == '/')
32 f = lambda n, s: n.startswith(p) and (len(n) == pl
33 or n[pl:pl + 1] == '/')
32 return f
34 return f
33 raise error.ParseError(_("unsupported file pattern: %s") % name,
35 raise error.ParseError(_("unsupported file pattern: %s") % name,
34 hint=_('paths must be prefixed with "path:"'))
36 hint=_('paths must be prefixed with "path:"'))
35 elif op == 'or':
37 elif op == 'or':
36 func1 = _compile(tree[1])
38 func1 = _compile(tree[1])
37 func2 = _compile(tree[2])
39 func2 = _compile(tree[2])
38 return lambda n, s: func1(n, s) or func2(n, s)
40 return lambda n, s: func1(n, s) or func2(n, s)
39 elif op == 'and':
41 elif op == 'and':
40 func1 = _compile(tree[1])
42 func1 = _compile(tree[1])
41 func2 = _compile(tree[2])
43 func2 = _compile(tree[2])
42 return lambda n, s: func1(n, s) and func2(n, s)
44 return lambda n, s: func1(n, s) and func2(n, s)
43 elif op == 'not':
45 elif op == 'not':
44 return lambda n, s: not _compile(tree[1])(n, s)
46 return lambda n, s: not _compile(tree[1])(n, s)
45 elif op == 'group':
47 elif op == 'group':
46 return _compile(tree[1])
48 return _compile(tree[1])
47 elif op == 'func':
49 elif op == 'func':
48 symbols = {
50 symbols = {
49 'all': lambda n, s: True,
51 'all': lambda n, s: True,
50 'none': lambda n, s: False,
52 'none': lambda n, s: False,
51 'size': lambda n, s: fileset.sizematcher(tree[2])(s),
53 'size': lambda n, s: fileset.sizematcher(tree[2])(s),
52 }
54 }
53
55
54 name = fileset.getsymbol(tree[1])
56 name = fileset.getsymbol(tree[1])
55 if name in symbols:
57 if name in symbols:
56 return symbols[name]
58 return symbols[name]
57
59
58 raise error.UnknownIdentifier(name, symbols.keys())
60 raise error.UnknownIdentifier(name, symbols.keys())
59 elif op == 'minus': # equivalent to 'x and not y'
61 elif op == 'minus': # equivalent to 'x and not y'
60 func1 = _compile(tree[1])
62 func1 = _compile(tree[1])
61 func2 = _compile(tree[2])
63 func2 = _compile(tree[2])
62 return lambda n, s: func1(n, s) and not func2(n, s)
64 return lambda n, s: func1(n, s) and not func2(n, s)
63 elif op == 'negate':
65 elif op == 'negate':
64 raise error.ParseError(_("can't use negate operator in this context"))
66 raise error.ParseError(_("can't use negate operator in this context"))
65 elif op == 'list':
67 elif op == 'list':
66 raise error.ParseError(_("can't use a list in this context"),
68 raise error.ParseError(_("can't use a list in this context"),
67 hint=_('see hg help "filesets.x or y"'))
69 hint=_('see hg help "filesets.x or y"'))
68 raise error.ProgrammingError('illegal tree: %r' % (tree,))
70 raise error.ProgrammingError('illegal tree: %r' % (tree,))
69
71
70 def compile(text):
72 def compile(text):
71 """generate a function (path, size) -> bool from filter specification.
73 """generate a function (path, size) -> bool from filter specification.
72
74
73 "text" could contain the operators defined by the fileset language for
75 "text" could contain the operators defined by the fileset language for
74 common logic operations, and parenthesis for grouping. The supported path
76 common logic operations, and parenthesis for grouping. The supported path
75 tests are '**.extname' for file extension test, and '"path:dir/subdir"'
77 tests are '**.extname' for file extension test, and '"path:dir/subdir"'
76 for prefix test. The ``size()`` predicate is borrowed from filesets to test
78 for prefix test. The ``size()`` predicate is borrowed from filesets to test
77 file size. The predicates ``all()`` and ``none()`` are also supported.
79 file size. The predicates ``all()`` and ``none()`` are also supported.
78
80
79 '(**.php & size(">10MB")) | **.zip | (path:bin & !path:bin/README)' for
81 '(**.php & size(">10MB")) | **.zip | (path:bin & !path:bin/README)' for
80 example, will catch all php files whose size is greater than 10 MB, all
82 example, will catch all php files whose size is greater than 10 MB, all
81 files whose name ends with ".zip", and all files under "bin" in the repo
83 files whose name ends with ".zip", and all files under "bin" in the repo
82 root except for "bin/README".
84 root except for "bin/README".
83 """
85 """
84 tree = fileset.parse(text)
86 tree = fileset.parse(text)
85 return _compile(tree)
87 return _compile(tree)
General Comments 0
You need to be logged in to leave comments. Login now