1 | # Copyright 2019 Wilke Schwiedop. All rights reserved.
|
2 | # Licensed under the Apache License, Version 2.0 (the "License");
|
3 | # you may not use this file except in compliance with the License.
|
4 | # You may obtain a copy of the License at
|
5 | #
|
6 | # http://www.apache.org/licenses/LICENSE-2.0
|
7 | """
|
8 | eval.py: evaluator for find.
|
9 | """
|
10 |
|
11 | from __future__ import print_function
|
12 |
|
13 | import fnmatch
|
14 | import os
|
15 | import stat
|
16 | import sys
|
17 |
|
18 | from _devbuild.gen import find_asdl as asdl
|
19 |
|
20 | def _path(v):
|
21 | return v.path
|
22 | def _basename(v):
|
23 | return os.path.basename(v.path)
|
24 |
|
25 | pathAccMap = {
|
26 | asdl.pathAccessor_e.FullPath.enum_id : _path,
|
27 | asdl.pathAccessor_e.Filename.enum_id : _basename,
|
28 | }
|
29 |
|
30 | def _accessTime(v):
|
31 | assert False
|
32 | return stat.ST_ATIME(v.stat.st_mode)
|
33 | def _creationTime(v):
|
34 | assert False
|
35 | return stat.ST_CTIME(v.stat.st_mode)
|
36 | def _modificationTime(v):
|
37 | assert False
|
38 | return stat.ST_MTIME(v.stat.st_mode)
|
39 | def _filesystem(v):
|
40 | assert False
|
41 | return stat.ST_DEV(v.stat.st_mode) # ???
|
42 | def _inode(v):
|
43 | return stat.ST_INO(v.stat.st_mode)
|
44 | def _linkCount(v):
|
45 | return stat.ST_NLINK(v.stat.st_mode)
|
46 | def _mode(v):
|
47 | return stat.S_IMODE(v.stat.st_mode)
|
48 | def _filetype(v):
|
49 | return stat.S_IFMT(v.stat.st_mode)
|
50 | def _uid(v):
|
51 | return stat.ST_UID(v.stat.st_mode)
|
52 | def _gid(v):
|
53 | return stat.ST_GID(v.stat.st_mode)
|
54 | def _username(v):
|
55 | assert False
|
56 | def _groupname(v):
|
57 | assert False
|
58 | def _size(v):
|
59 | return stat.ST_SIZE(v.stat.st_mode)
|
60 |
|
61 | statAccMap = {
|
62 | asdl.statAccessor_e.AccessTime.enum_id : _accessTime,
|
63 | asdl.statAccessor_e.CreationTime.enum_id : _creationTime,
|
64 | asdl.statAccessor_e.ModificationTime.enum_id : _modificationTime,
|
65 | asdl.statAccessor_e.Filesystem.enum_id : _filesystem,
|
66 | asdl.statAccessor_e.Inode.enum_id : _inode,
|
67 | # asdl.statAccessor_e.LinkCount.enum_id : _linkCount,
|
68 | asdl.statAccessor_e.Mode.enum_id : _mode,
|
69 | asdl.statAccessor_e.Filetype.enum_id : _filetype,
|
70 | asdl.statAccessor_e.Uid.enum_id : _uid,
|
71 | asdl.statAccessor_e.Gid.enum_id : _gid,
|
72 | asdl.statAccessor_e.Username.enum_id : _username,
|
73 | asdl.statAccessor_e.Groupname.enum_id : _groupname,
|
74 | asdl.statAccessor_e.Size.enum_id : _size,
|
75 | }
|
76 |
|
77 | def _stringMatch(acc, test):
|
78 | string = test.p.str
|
79 | return lambda x: acc(x) == string
|
80 | def _globMatch(acc, test):
|
81 | glob = test.p.glob
|
82 | return lambda x: fnmatch.fnmatch(acc(x), glob)
|
83 | def _regexMatch(acc, test):
|
84 | assert False
|
85 | def _eq(acc, test):
|
86 | n = test.p.n
|
87 | return lambda x: acc(x) == n
|
88 | def _ge(acc, test):
|
89 | n = test.p.n
|
90 | return lambda x: acc(x) >= n
|
91 | def _le(acc, test):
|
92 | n = test.p.n
|
93 | return lambda x: acc(x) <= n
|
94 | def _readable(acc, test):
|
95 | return lambda x: os.access(acc(x), os.R_OK)
|
96 | def _writable(acc, test):
|
97 | return lambda x: os.access(acc(x), os.W_OK)
|
98 | def _executable(acc, test):
|
99 | return lambda x: os.access(acc(x), os.X_OK)
|
100 |
|
101 | predicateMap = {
|
102 | asdl.predicate_e.StringMatch : _stringMatch,
|
103 | asdl.predicate_e.GlobMatch : _globMatch,
|
104 | asdl.predicate_e.RegexMatch : _regexMatch,
|
105 | asdl.predicate_e.EQ : _eq,
|
106 | asdl.predicate_e.GE : _ge,
|
107 | asdl.predicate_e.LE : _le,
|
108 | asdl.predicate_e.Readable : _readable,
|
109 | asdl.predicate_e.Writable : _writable,
|
110 | asdl.predicate_e.Executable : _executable,
|
111 | }
|
112 |
|
113 | def _true(_):
|
114 | return lambda _: True
|
115 | def _false(_):
|
116 | return lambda _: False
|
117 | def _concatenation(test):
|
118 | return lambda x: [EvalExpr(e)(x) for e in test.exprs][-1]
|
119 | def _disjunction(test):
|
120 | return lambda x: any(EvalExpr(e)(x) for e in test.exprs)
|
121 | def _conjunction(test):
|
122 | return lambda x: all(EvalExpr(e)(x) for e in test.exprs)
|
123 | def _negation(test):
|
124 | return lambda x: not EvalExpr(test.expr)(x)
|
125 | def _pathTest(test):
|
126 | pred = predicateMap[test.p.tag]
|
127 | acc = pathAccMap[test.a.enum_id]
|
128 | return pred(acc, test)
|
129 | def _statTest(test):
|
130 | pred = predicateMap[test.p.tag]
|
131 | acc = statAccMap[test.a.enum_id]
|
132 | return pred(acc, test)
|
133 | def _delete(_):
|
134 | def __delete(v):
|
135 | print("pretend delete", v, file=sys.stderr)
|
136 | return True
|
137 | return __delete
|
138 | def _prune(_):
|
139 | def __prune(v):
|
140 | v.prune = True
|
141 | return True
|
142 | return __prune
|
143 | def _quit(_):
|
144 | def __quit(v):
|
145 | v.quit = True
|
146 | return True
|
147 | return __quit
|
148 | def _print(action):
|
149 | # TODO handle output-file
|
150 | # TODO handle format
|
151 | def __print(v):
|
152 | print(v.path)
|
153 | return True
|
154 | return __print
|
155 | def _ls(action):
|
156 | return _true
|
157 | def _exec(action):
|
158 | # TODO return exit status
|
159 | return _true
|
160 |
|
161 | exprMap = {
|
162 | asdl.expr_e.True_ : _true,
|
163 | asdl.expr_e.False_ : _false,
|
164 | asdl.expr_e.Concatenation : _concatenation,
|
165 | asdl.expr_e.Disjunction : _disjunction,
|
166 | asdl.expr_e.Conjunction : _conjunction,
|
167 | asdl.expr_e.Negation : _negation,
|
168 | asdl.expr_e.PathTest : _pathTest,
|
169 | asdl.expr_e.StatTest : _statTest,
|
170 | asdl.expr_e.DeleteAction : _delete,
|
171 | asdl.expr_e.PruneAction : _prune,
|
172 | asdl.expr_e.QuitAction : _quit,
|
173 | asdl.expr_e.PrintAction : _print,
|
174 | asdl.expr_e.LsAction : _ls,
|
175 | asdl.expr_e.ExecAction : _exec,
|
176 | }
|
177 |
|
178 | def EvalExpr(ast):
|
179 | return exprMap[ast.tag](ast)
|
180 |
|
181 | class Thing:
|
182 | def __init__(self, path, stat=None):
|
183 | self.path = path
|
184 | self._stat = stat
|
185 | self.prune = False
|
186 | self.quit = False
|
187 | @property
|
188 | def stat(self):
|
189 | if self._stat is None:
|
190 | # TODO stat for tests that require it?
|
191 | self._stat = os.lstat(self.path)
|
192 | return self._stat
|
193 | def __repr__(self):
|
194 | return self.path
|