16 ) |
16 ) |
17 |
17 |
18 |
18 |
19 def _sizep(x): |
19 def _sizep(x): |
20 # i18n: "size" is a keyword |
20 # i18n: "size" is a keyword |
21 expr = filesetlang.getstring(x, _("size requires an expression")) |
21 expr = filesetlang.getstring(x, _(b"size requires an expression")) |
22 return fileset.sizematcher(expr) |
22 return fileset.sizematcher(expr) |
23 |
23 |
24 |
24 |
25 def _compile(tree): |
25 def _compile(tree): |
26 if not tree: |
26 if not tree: |
27 raise error.ParseError(_("missing argument")) |
27 raise error.ParseError(_(b"missing argument")) |
28 op = tree[0] |
28 op = tree[0] |
29 if op == 'withstatus': |
29 if op == b'withstatus': |
30 return _compile(tree[1]) |
30 return _compile(tree[1]) |
31 elif op in {'symbol', 'string', 'kindpat'}: |
31 elif op in {b'symbol', b'string', b'kindpat'}: |
32 name = filesetlang.getpattern(tree, {'path'}, _('invalid file pattern')) |
32 name = filesetlang.getpattern( |
33 if name.startswith('**'): # file extension test, ex. "**.tar.gz" |
33 tree, {b'path'}, _(b'invalid file pattern') |
|
34 ) |
|
35 if name.startswith(b'**'): # file extension test, ex. "**.tar.gz" |
34 ext = name[2:] |
36 ext = name[2:] |
35 for c in pycompat.bytestr(ext): |
37 for c in pycompat.bytestr(ext): |
36 if c in '*{}[]?/\\': |
38 if c in b'*{}[]?/\\': |
37 raise error.ParseError(_('reserved character: %s') % c) |
39 raise error.ParseError(_(b'reserved character: %s') % c) |
38 return lambda n, s: n.endswith(ext) |
40 return lambda n, s: n.endswith(ext) |
39 elif name.startswith('path:'): # directory or full path test |
41 elif name.startswith(b'path:'): # directory or full path test |
40 p = name[5:] # prefix |
42 p = name[5:] # prefix |
41 pl = len(p) |
43 pl = len(p) |
42 f = lambda n, s: n.startswith(p) and ( |
44 f = lambda n, s: n.startswith(p) and ( |
43 len(n) == pl or n[pl : pl + 1] == '/' |
45 len(n) == pl or n[pl : pl + 1] == b'/' |
44 ) |
46 ) |
45 return f |
47 return f |
46 raise error.ParseError( |
48 raise error.ParseError( |
47 _("unsupported file pattern: %s") % name, |
49 _(b"unsupported file pattern: %s") % name, |
48 hint=_('paths must be prefixed with "path:"'), |
50 hint=_(b'paths must be prefixed with "path:"'), |
49 ) |
51 ) |
50 elif op in {'or', 'patterns'}: |
52 elif op in {b'or', b'patterns'}: |
51 funcs = [_compile(x) for x in tree[1:]] |
53 funcs = [_compile(x) for x in tree[1:]] |
52 return lambda n, s: any(f(n, s) for f in funcs) |
54 return lambda n, s: any(f(n, s) for f in funcs) |
53 elif op == 'and': |
55 elif op == b'and': |
54 func1 = _compile(tree[1]) |
56 func1 = _compile(tree[1]) |
55 func2 = _compile(tree[2]) |
57 func2 = _compile(tree[2]) |
56 return lambda n, s: func1(n, s) and func2(n, s) |
58 return lambda n, s: func1(n, s) and func2(n, s) |
57 elif op == 'not': |
59 elif op == b'not': |
58 return lambda n, s: not _compile(tree[1])(n, s) |
60 return lambda n, s: not _compile(tree[1])(n, s) |
59 elif op == 'func': |
61 elif op == b'func': |
60 symbols = { |
62 symbols = { |
61 'all': lambda n, s: True, |
63 b'all': lambda n, s: True, |
62 'none': lambda n, s: False, |
64 b'none': lambda n, s: False, |
63 'size': lambda n, s: _sizep(tree[2])(s), |
65 b'size': lambda n, s: _sizep(tree[2])(s), |
64 } |
66 } |
65 |
67 |
66 name = filesetlang.getsymbol(tree[1]) |
68 name = filesetlang.getsymbol(tree[1]) |
67 if name in symbols: |
69 if name in symbols: |
68 return symbols[name] |
70 return symbols[name] |
69 |
71 |
70 raise error.UnknownIdentifier(name, symbols.keys()) |
72 raise error.UnknownIdentifier(name, symbols.keys()) |
71 elif op == 'minus': # equivalent to 'x and not y' |
73 elif op == b'minus': # equivalent to 'x and not y' |
72 func1 = _compile(tree[1]) |
74 func1 = _compile(tree[1]) |
73 func2 = _compile(tree[2]) |
75 func2 = _compile(tree[2]) |
74 return lambda n, s: func1(n, s) and not func2(n, s) |
76 return lambda n, s: func1(n, s) and not func2(n, s) |
75 elif op == 'list': |
77 elif op == b'list': |
76 raise error.ParseError( |
78 raise error.ParseError( |
77 _("can't use a list in this context"), |
79 _(b"can't use a list in this context"), |
78 hint=_('see \'hg help "filesets.x or y"\''), |
80 hint=_(b'see \'hg help "filesets.x or y"\''), |
79 ) |
81 ) |
80 raise error.ProgrammingError('illegal tree: %r' % (tree,)) |
82 raise error.ProgrammingError(b'illegal tree: %r' % (tree,)) |
81 |
83 |
82 |
84 |
83 def compile(text): |
85 def compile(text): |
84 """generate a function (path, size) -> bool from filter specification. |
86 """generate a function (path, size) -> bool from filter specification. |
85 |
87 |