Mercurial > hg
comparison mercurial/fileset.py @ 43076:2372284d9457
formatting: blacken the codebase
This is using my patch to black
(https://github.com/psf/black/pull/826) so we don't un-wrap collection
literals.
Done with:
hg files 'set:**.py - mercurial/thirdparty/** - "contrib/python-zstandard/**"' | xargs black -S
# skip-blame mass-reformatting only
# no-check-commit reformats foo_bar functions
Differential Revision: https://phab.mercurial-scm.org/D6971
author | Augie Fackler <augie@google.com> |
---|---|
date | Sun, 06 Oct 2019 09:45:02 -0400 |
parents | 0531dff73d0b |
children | 687b865b95ad |
comparison
equal
deleted
inserted
replaced
43075:57875cf423c9 | 43076:2372284d9457 |
---|---|
19 pycompat, | 19 pycompat, |
20 registrar, | 20 registrar, |
21 scmutil, | 21 scmutil, |
22 util, | 22 util, |
23 ) | 23 ) |
24 from .utils import ( | 24 from .utils import stringutil |
25 stringutil, | |
26 ) | |
27 | 25 |
28 # common weight constants | 26 # common weight constants |
29 _WEIGHT_CHECK_FILENAME = filesetlang.WEIGHT_CHECK_FILENAME | 27 _WEIGHT_CHECK_FILENAME = filesetlang.WEIGHT_CHECK_FILENAME |
30 _WEIGHT_READ_CONTENTS = filesetlang.WEIGHT_READ_CONTENTS | 28 _WEIGHT_READ_CONTENTS = filesetlang.WEIGHT_READ_CONTENTS |
31 _WEIGHT_STATUS = filesetlang.WEIGHT_STATUS | 29 _WEIGHT_STATUS = filesetlang.WEIGHT_STATUS |
36 getstring = filesetlang.getstring | 34 getstring = filesetlang.getstring |
37 _getkindpat = filesetlang.getkindpat | 35 _getkindpat = filesetlang.getkindpat |
38 getpattern = filesetlang.getpattern | 36 getpattern = filesetlang.getpattern |
39 getargs = filesetlang.getargs | 37 getargs = filesetlang.getargs |
40 | 38 |
39 | |
41 def getmatch(mctx, x): | 40 def getmatch(mctx, x): |
42 if not x: | 41 if not x: |
43 raise error.ParseError(_("missing argument")) | 42 raise error.ParseError(_("missing argument")) |
44 return methods[x[0]](mctx, *x[1:]) | 43 return methods[x[0]](mctx, *x[1:]) |
45 | 44 |
45 | |
46 def getmatchwithstatus(mctx, x, hint): | 46 def getmatchwithstatus(mctx, x, hint): |
47 keys = set(getstring(hint, 'status hint must be a string').split()) | 47 keys = set(getstring(hint, 'status hint must be a string').split()) |
48 return getmatch(mctx.withstatus(keys), x) | 48 return getmatch(mctx.withstatus(keys), x) |
49 | 49 |
50 | |
50 def stringmatch(mctx, x): | 51 def stringmatch(mctx, x): |
51 return mctx.matcher([x]) | 52 return mctx.matcher([x]) |
52 | 53 |
54 | |
53 def kindpatmatch(mctx, x, y): | 55 def kindpatmatch(mctx, x, y): |
54 return stringmatch(mctx, _getkindpat(x, y, matchmod.allpatternkinds, | 56 return stringmatch( |
55 _("pattern must be a string"))) | 57 mctx, |
58 _getkindpat( | |
59 x, y, matchmod.allpatternkinds, _("pattern must be a string") | |
60 ), | |
61 ) | |
62 | |
56 | 63 |
57 def patternsmatch(mctx, *xs): | 64 def patternsmatch(mctx, *xs): |
58 allkinds = matchmod.allpatternkinds | 65 allkinds = matchmod.allpatternkinds |
59 patterns = [getpattern(x, allkinds, _("pattern must be a string")) | 66 patterns = [ |
60 for x in xs] | 67 getpattern(x, allkinds, _("pattern must be a string")) for x in xs |
68 ] | |
61 return mctx.matcher(patterns) | 69 return mctx.matcher(patterns) |
70 | |
62 | 71 |
63 def andmatch(mctx, x, y): | 72 def andmatch(mctx, x, y): |
64 xm = getmatch(mctx, x) | 73 xm = getmatch(mctx, x) |
65 ym = getmatch(mctx.narrowed(xm), y) | 74 ym = getmatch(mctx.narrowed(xm), y) |
66 return matchmod.intersectmatchers(xm, ym) | 75 return matchmod.intersectmatchers(xm, ym) |
67 | 76 |
77 | |
68 def ormatch(mctx, *xs): | 78 def ormatch(mctx, *xs): |
69 ms = [getmatch(mctx, x) for x in xs] | 79 ms = [getmatch(mctx, x) for x in xs] |
70 return matchmod.unionmatcher(ms) | 80 return matchmod.unionmatcher(ms) |
71 | 81 |
82 | |
72 def notmatch(mctx, x): | 83 def notmatch(mctx, x): |
73 m = getmatch(mctx, x) | 84 m = getmatch(mctx, x) |
74 return mctx.predicate(lambda f: not m(f), predrepr=('<not %r>', m)) | 85 return mctx.predicate(lambda f: not m(f), predrepr=('<not %r>', m)) |
86 | |
75 | 87 |
76 def minusmatch(mctx, x, y): | 88 def minusmatch(mctx, x, y): |
77 xm = getmatch(mctx, x) | 89 xm = getmatch(mctx, x) |
78 ym = getmatch(mctx.narrowed(xm), y) | 90 ym = getmatch(mctx.narrowed(xm), y) |
79 return matchmod.differencematcher(xm, ym) | 91 return matchmod.differencematcher(xm, ym) |
80 | 92 |
93 | |
81 def listmatch(mctx, *xs): | 94 def listmatch(mctx, *xs): |
82 raise error.ParseError(_("can't use a list in this context"), | 95 raise error.ParseError( |
83 hint=_('see \'hg help "filesets.x or y"\'')) | 96 _("can't use a list in this context"), |
97 hint=_('see \'hg help "filesets.x or y"\''), | |
98 ) | |
99 | |
84 | 100 |
85 def func(mctx, a, b): | 101 def func(mctx, a, b): |
86 funcname = getsymbol(a) | 102 funcname = getsymbol(a) |
87 if funcname in symbols: | 103 if funcname in symbols: |
88 return symbols[funcname](mctx, b) | 104 return symbols[funcname](mctx, b) |
89 | 105 |
90 keep = lambda fn: getattr(fn, '__doc__', None) is not None | 106 keep = lambda fn: getattr(fn, '__doc__', None) is not None |
91 | 107 |
92 syms = [s for (s, fn) in symbols.items() if keep(fn)] | 108 syms = [s for (s, fn) in symbols.items() if keep(fn)] |
93 raise error.UnknownIdentifier(funcname, syms) | 109 raise error.UnknownIdentifier(funcname, syms) |
110 | |
94 | 111 |
95 # symbols are callable like: | 112 # symbols are callable like: |
96 # fun(mctx, x) | 113 # fun(mctx, x) |
97 # with: | 114 # with: |
98 # mctx - current matchctx instance | 115 # mctx - current matchctx instance |
99 # x - argument in tree form | 116 # x - argument in tree form |
100 symbols = filesetlang.symbols | 117 symbols = filesetlang.symbols |
101 | 118 |
102 predicate = registrar.filesetpredicate(symbols) | 119 predicate = registrar.filesetpredicate(symbols) |
103 | 120 |
121 | |
104 @predicate('modified()', callstatus=True, weight=_WEIGHT_STATUS) | 122 @predicate('modified()', callstatus=True, weight=_WEIGHT_STATUS) |
105 def modified(mctx, x): | 123 def modified(mctx, x): |
106 """File that is modified according to :hg:`status`. | 124 """File that is modified according to :hg:`status`. |
107 """ | 125 """ |
108 # i18n: "modified" is a keyword | 126 # i18n: "modified" is a keyword |
109 getargs(x, 0, 0, _("modified takes no arguments")) | 127 getargs(x, 0, 0, _("modified takes no arguments")) |
110 s = set(mctx.status().modified) | 128 s = set(mctx.status().modified) |
111 return mctx.predicate(s.__contains__, predrepr='modified') | 129 return mctx.predicate(s.__contains__, predrepr='modified') |
112 | 130 |
131 | |
113 @predicate('added()', callstatus=True, weight=_WEIGHT_STATUS) | 132 @predicate('added()', callstatus=True, weight=_WEIGHT_STATUS) |
114 def added(mctx, x): | 133 def added(mctx, x): |
115 """File that is added according to :hg:`status`. | 134 """File that is added according to :hg:`status`. |
116 """ | 135 """ |
117 # i18n: "added" is a keyword | 136 # i18n: "added" is a keyword |
118 getargs(x, 0, 0, _("added takes no arguments")) | 137 getargs(x, 0, 0, _("added takes no arguments")) |
119 s = set(mctx.status().added) | 138 s = set(mctx.status().added) |
120 return mctx.predicate(s.__contains__, predrepr='added') | 139 return mctx.predicate(s.__contains__, predrepr='added') |
121 | 140 |
141 | |
122 @predicate('removed()', callstatus=True, weight=_WEIGHT_STATUS) | 142 @predicate('removed()', callstatus=True, weight=_WEIGHT_STATUS) |
123 def removed(mctx, x): | 143 def removed(mctx, x): |
124 """File that is removed according to :hg:`status`. | 144 """File that is removed according to :hg:`status`. |
125 """ | 145 """ |
126 # i18n: "removed" is a keyword | 146 # i18n: "removed" is a keyword |
127 getargs(x, 0, 0, _("removed takes no arguments")) | 147 getargs(x, 0, 0, _("removed takes no arguments")) |
128 s = set(mctx.status().removed) | 148 s = set(mctx.status().removed) |
129 return mctx.predicate(s.__contains__, predrepr='removed') | 149 return mctx.predicate(s.__contains__, predrepr='removed') |
130 | 150 |
151 | |
131 @predicate('deleted()', callstatus=True, weight=_WEIGHT_STATUS) | 152 @predicate('deleted()', callstatus=True, weight=_WEIGHT_STATUS) |
132 def deleted(mctx, x): | 153 def deleted(mctx, x): |
133 """Alias for ``missing()``. | 154 """Alias for ``missing()``. |
134 """ | 155 """ |
135 # i18n: "deleted" is a keyword | 156 # i18n: "deleted" is a keyword |
136 getargs(x, 0, 0, _("deleted takes no arguments")) | 157 getargs(x, 0, 0, _("deleted takes no arguments")) |
137 s = set(mctx.status().deleted) | 158 s = set(mctx.status().deleted) |
138 return mctx.predicate(s.__contains__, predrepr='deleted') | 159 return mctx.predicate(s.__contains__, predrepr='deleted') |
139 | 160 |
161 | |
140 @predicate('missing()', callstatus=True, weight=_WEIGHT_STATUS) | 162 @predicate('missing()', callstatus=True, weight=_WEIGHT_STATUS) |
141 def missing(mctx, x): | 163 def missing(mctx, x): |
142 """File that is missing according to :hg:`status`. | 164 """File that is missing according to :hg:`status`. |
143 """ | 165 """ |
144 # i18n: "missing" is a keyword | 166 # i18n: "missing" is a keyword |
145 getargs(x, 0, 0, _("missing takes no arguments")) | 167 getargs(x, 0, 0, _("missing takes no arguments")) |
146 s = set(mctx.status().deleted) | 168 s = set(mctx.status().deleted) |
147 return mctx.predicate(s.__contains__, predrepr='deleted') | 169 return mctx.predicate(s.__contains__, predrepr='deleted') |
170 | |
148 | 171 |
149 @predicate('unknown()', callstatus=True, weight=_WEIGHT_STATUS_THOROUGH) | 172 @predicate('unknown()', callstatus=True, weight=_WEIGHT_STATUS_THOROUGH) |
150 def unknown(mctx, x): | 173 def unknown(mctx, x): |
151 """File that is unknown according to :hg:`status`.""" | 174 """File that is unknown according to :hg:`status`.""" |
152 # i18n: "unknown" is a keyword | 175 # i18n: "unknown" is a keyword |
153 getargs(x, 0, 0, _("unknown takes no arguments")) | 176 getargs(x, 0, 0, _("unknown takes no arguments")) |
154 s = set(mctx.status().unknown) | 177 s = set(mctx.status().unknown) |
155 return mctx.predicate(s.__contains__, predrepr='unknown') | 178 return mctx.predicate(s.__contains__, predrepr='unknown') |
156 | 179 |
180 | |
157 @predicate('ignored()', callstatus=True, weight=_WEIGHT_STATUS_THOROUGH) | 181 @predicate('ignored()', callstatus=True, weight=_WEIGHT_STATUS_THOROUGH) |
158 def ignored(mctx, x): | 182 def ignored(mctx, x): |
159 """File that is ignored according to :hg:`status`.""" | 183 """File that is ignored according to :hg:`status`.""" |
160 # i18n: "ignored" is a keyword | 184 # i18n: "ignored" is a keyword |
161 getargs(x, 0, 0, _("ignored takes no arguments")) | 185 getargs(x, 0, 0, _("ignored takes no arguments")) |
162 s = set(mctx.status().ignored) | 186 s = set(mctx.status().ignored) |
163 return mctx.predicate(s.__contains__, predrepr='ignored') | 187 return mctx.predicate(s.__contains__, predrepr='ignored') |
164 | 188 |
189 | |
165 @predicate('clean()', callstatus=True, weight=_WEIGHT_STATUS) | 190 @predicate('clean()', callstatus=True, weight=_WEIGHT_STATUS) |
166 def clean(mctx, x): | 191 def clean(mctx, x): |
167 """File that is clean according to :hg:`status`. | 192 """File that is clean according to :hg:`status`. |
168 """ | 193 """ |
169 # i18n: "clean" is a keyword | 194 # i18n: "clean" is a keyword |
170 getargs(x, 0, 0, _("clean takes no arguments")) | 195 getargs(x, 0, 0, _("clean takes no arguments")) |
171 s = set(mctx.status().clean) | 196 s = set(mctx.status().clean) |
172 return mctx.predicate(s.__contains__, predrepr='clean') | 197 return mctx.predicate(s.__contains__, predrepr='clean') |
198 | |
173 | 199 |
174 @predicate('tracked()') | 200 @predicate('tracked()') |
175 def tracked(mctx, x): | 201 def tracked(mctx, x): |
176 """File that is under Mercurial control.""" | 202 """File that is under Mercurial control.""" |
177 # i18n: "tracked" is a keyword | 203 # i18n: "tracked" is a keyword |
178 getargs(x, 0, 0, _("tracked takes no arguments")) | 204 getargs(x, 0, 0, _("tracked takes no arguments")) |
179 return mctx.predicate(mctx.ctx.__contains__, predrepr='tracked') | 205 return mctx.predicate(mctx.ctx.__contains__, predrepr='tracked') |
180 | 206 |
207 | |
181 @predicate('binary()', weight=_WEIGHT_READ_CONTENTS) | 208 @predicate('binary()', weight=_WEIGHT_READ_CONTENTS) |
182 def binary(mctx, x): | 209 def binary(mctx, x): |
183 """File that appears to be binary (contains NUL bytes). | 210 """File that appears to be binary (contains NUL bytes). |
184 """ | 211 """ |
185 # i18n: "binary" is a keyword | 212 # i18n: "binary" is a keyword |
186 getargs(x, 0, 0, _("binary takes no arguments")) | 213 getargs(x, 0, 0, _("binary takes no arguments")) |
187 return mctx.fpredicate(lambda fctx: fctx.isbinary(), | 214 return mctx.fpredicate( |
188 predrepr='binary', cache=True) | 215 lambda fctx: fctx.isbinary(), predrepr='binary', cache=True |
216 ) | |
217 | |
189 | 218 |
190 @predicate('exec()') | 219 @predicate('exec()') |
191 def exec_(mctx, x): | 220 def exec_(mctx, x): |
192 """File that is marked as executable. | 221 """File that is marked as executable. |
193 """ | 222 """ |
194 # i18n: "exec" is a keyword | 223 # i18n: "exec" is a keyword |
195 getargs(x, 0, 0, _("exec takes no arguments")) | 224 getargs(x, 0, 0, _("exec takes no arguments")) |
196 ctx = mctx.ctx | 225 ctx = mctx.ctx |
197 return mctx.predicate(lambda f: ctx.flags(f) == 'x', predrepr='exec') | 226 return mctx.predicate(lambda f: ctx.flags(f) == 'x', predrepr='exec') |
198 | 227 |
228 | |
199 @predicate('symlink()') | 229 @predicate('symlink()') |
200 def symlink(mctx, x): | 230 def symlink(mctx, x): |
201 """File that is marked as a symlink. | 231 """File that is marked as a symlink. |
202 """ | 232 """ |
203 # i18n: "symlink" is a keyword | 233 # i18n: "symlink" is a keyword |
204 getargs(x, 0, 0, _("symlink takes no arguments")) | 234 getargs(x, 0, 0, _("symlink takes no arguments")) |
205 ctx = mctx.ctx | 235 ctx = mctx.ctx |
206 return mctx.predicate(lambda f: ctx.flags(f) == 'l', predrepr='symlink') | 236 return mctx.predicate(lambda f: ctx.flags(f) == 'l', predrepr='symlink') |
237 | |
207 | 238 |
208 @predicate('resolved()', weight=_WEIGHT_STATUS) | 239 @predicate('resolved()', weight=_WEIGHT_STATUS) |
209 def resolved(mctx, x): | 240 def resolved(mctx, x): |
210 """File that is marked resolved according to :hg:`resolve -l`. | 241 """File that is marked resolved according to :hg:`resolve -l`. |
211 """ | 242 """ |
212 # i18n: "resolved" is a keyword | 243 # i18n: "resolved" is a keyword |
213 getargs(x, 0, 0, _("resolved takes no arguments")) | 244 getargs(x, 0, 0, _("resolved takes no arguments")) |
214 if mctx.ctx.rev() is not None: | 245 if mctx.ctx.rev() is not None: |
215 return mctx.never() | 246 return mctx.never() |
216 ms = merge.mergestate.read(mctx.ctx.repo()) | 247 ms = merge.mergestate.read(mctx.ctx.repo()) |
217 return mctx.predicate(lambda f: f in ms and ms[f] == 'r', | 248 return mctx.predicate( |
218 predrepr='resolved') | 249 lambda f: f in ms and ms[f] == 'r', predrepr='resolved' |
250 ) | |
251 | |
219 | 252 |
220 @predicate('unresolved()', weight=_WEIGHT_STATUS) | 253 @predicate('unresolved()', weight=_WEIGHT_STATUS) |
221 def unresolved(mctx, x): | 254 def unresolved(mctx, x): |
222 """File that is marked unresolved according to :hg:`resolve -l`. | 255 """File that is marked unresolved according to :hg:`resolve -l`. |
223 """ | 256 """ |
224 # i18n: "unresolved" is a keyword | 257 # i18n: "unresolved" is a keyword |
225 getargs(x, 0, 0, _("unresolved takes no arguments")) | 258 getargs(x, 0, 0, _("unresolved takes no arguments")) |
226 if mctx.ctx.rev() is not None: | 259 if mctx.ctx.rev() is not None: |
227 return mctx.never() | 260 return mctx.never() |
228 ms = merge.mergestate.read(mctx.ctx.repo()) | 261 ms = merge.mergestate.read(mctx.ctx.repo()) |
229 return mctx.predicate(lambda f: f in ms and ms[f] == 'u', | 262 return mctx.predicate( |
230 predrepr='unresolved') | 263 lambda f: f in ms and ms[f] == 'u', predrepr='unresolved' |
264 ) | |
265 | |
231 | 266 |
232 @predicate('hgignore()', weight=_WEIGHT_STATUS) | 267 @predicate('hgignore()', weight=_WEIGHT_STATUS) |
233 def hgignore(mctx, x): | 268 def hgignore(mctx, x): |
234 """File that matches the active .hgignore pattern. | 269 """File that matches the active .hgignore pattern. |
235 """ | 270 """ |
236 # i18n: "hgignore" is a keyword | 271 # i18n: "hgignore" is a keyword |
237 getargs(x, 0, 0, _("hgignore takes no arguments")) | 272 getargs(x, 0, 0, _("hgignore takes no arguments")) |
238 return mctx.ctx.repo().dirstate._ignore | 273 return mctx.ctx.repo().dirstate._ignore |
274 | |
239 | 275 |
240 @predicate('portable()', weight=_WEIGHT_CHECK_FILENAME) | 276 @predicate('portable()', weight=_WEIGHT_CHECK_FILENAME) |
241 def portable(mctx, x): | 277 def portable(mctx, x): |
242 """File that has a portable name. (This doesn't include filenames with case | 278 """File that has a portable name. (This doesn't include filenames with case |
243 collisions.) | 279 collisions.) |
244 """ | 280 """ |
245 # i18n: "portable" is a keyword | 281 # i18n: "portable" is a keyword |
246 getargs(x, 0, 0, _("portable takes no arguments")) | 282 getargs(x, 0, 0, _("portable takes no arguments")) |
247 return mctx.predicate(lambda f: util.checkwinfilename(f) is None, | 283 return mctx.predicate( |
248 predrepr='portable') | 284 lambda f: util.checkwinfilename(f) is None, predrepr='portable' |
285 ) | |
286 | |
249 | 287 |
250 @predicate('grep(regex)', weight=_WEIGHT_READ_CONTENTS) | 288 @predicate('grep(regex)', weight=_WEIGHT_READ_CONTENTS) |
251 def grep(mctx, x): | 289 def grep(mctx, x): |
252 """File contains the given regular expression. | 290 """File contains the given regular expression. |
253 """ | 291 """ |
254 try: | 292 try: |
255 # i18n: "grep" is a keyword | 293 # i18n: "grep" is a keyword |
256 r = re.compile(getstring(x, _("grep requires a pattern"))) | 294 r = re.compile(getstring(x, _("grep requires a pattern"))) |
257 except re.error as e: | 295 except re.error as e: |
258 raise error.ParseError(_('invalid match pattern: %s') % | 296 raise error.ParseError( |
259 stringutil.forcebytestr(e)) | 297 _('invalid match pattern: %s') % stringutil.forcebytestr(e) |
260 return mctx.fpredicate(lambda fctx: r.search(fctx.data()), | 298 ) |
261 predrepr=('grep(%r)', r.pattern), cache=True) | 299 return mctx.fpredicate( |
300 lambda fctx: r.search(fctx.data()), | |
301 predrepr=('grep(%r)', r.pattern), | |
302 cache=True, | |
303 ) | |
304 | |
262 | 305 |
263 def _sizetomax(s): | 306 def _sizetomax(s): |
264 try: | 307 try: |
265 s = s.strip().lower() | 308 s = s.strip().lower() |
266 for k, v in util._sizeunits: | 309 for k, v in util._sizeunits: |
267 if s.endswith(k): | 310 if s.endswith(k): |
268 # max(4k) = 5k - 1, max(4.5k) = 4.6k - 1 | 311 # max(4k) = 5k - 1, max(4.5k) = 4.6k - 1 |
269 n = s[:-len(k)] | 312 n = s[: -len(k)] |
270 inc = 1.0 | 313 inc = 1.0 |
271 if "." in n: | 314 if "." in n: |
272 inc /= 10 ** len(n.split(".")[1]) | 315 inc /= 10 ** len(n.split(".")[1]) |
273 return int((float(n) + inc) * v) - 1 | 316 return int((float(n) + inc) * v) - 1 |
274 # no extension, this is a precise value | 317 # no extension, this is a precise value |
275 return int(s) | 318 return int(s) |
276 except ValueError: | 319 except ValueError: |
277 raise error.ParseError(_("couldn't parse size: %s") % s) | 320 raise error.ParseError(_("couldn't parse size: %s") % s) |
278 | 321 |
322 | |
279 def sizematcher(expr): | 323 def sizematcher(expr): |
280 """Return a function(size) -> bool from the ``size()`` expression""" | 324 """Return a function(size) -> bool from the ``size()`` expression""" |
281 expr = expr.strip() | 325 expr = expr.strip() |
282 if '-' in expr: # do we have a range? | 326 if '-' in expr: # do we have a range? |
283 a, b = expr.split('-', 1) | 327 a, b = expr.split('-', 1) |
284 a = util.sizetoint(a) | 328 a = util.sizetoint(a) |
285 b = util.sizetoint(b) | 329 b = util.sizetoint(b) |
286 return lambda x: x >= a and x <= b | 330 return lambda x: x >= a and x <= b |
287 elif expr.startswith("<="): | 331 elif expr.startswith("<="): |
299 else: | 343 else: |
300 a = util.sizetoint(expr) | 344 a = util.sizetoint(expr) |
301 b = _sizetomax(expr) | 345 b = _sizetomax(expr) |
302 return lambda x: x >= a and x <= b | 346 return lambda x: x >= a and x <= b |
303 | 347 |
348 | |
304 @predicate('size(expression)', weight=_WEIGHT_STATUS) | 349 @predicate('size(expression)', weight=_WEIGHT_STATUS) |
305 def size(mctx, x): | 350 def size(mctx, x): |
306 """File size matches the given expression. Examples: | 351 """File size matches the given expression. Examples: |
307 | 352 |
308 - size('1k') - files from 1024 to 2047 bytes | 353 - size('1k') - files from 1024 to 2047 bytes |
311 - size('4k - 1MB') - files from 4096 bytes to 1048576 bytes | 356 - size('4k - 1MB') - files from 4096 bytes to 1048576 bytes |
312 """ | 357 """ |
313 # i18n: "size" is a keyword | 358 # i18n: "size" is a keyword |
314 expr = getstring(x, _("size requires an expression")) | 359 expr = getstring(x, _("size requires an expression")) |
315 m = sizematcher(expr) | 360 m = sizematcher(expr) |
316 return mctx.fpredicate(lambda fctx: m(fctx.size()), | 361 return mctx.fpredicate( |
317 predrepr=('size(%r)', expr), cache=True) | 362 lambda fctx: m(fctx.size()), predrepr=('size(%r)', expr), cache=True |
363 ) | |
364 | |
318 | 365 |
319 @predicate('encoding(name)', weight=_WEIGHT_READ_CONTENTS) | 366 @predicate('encoding(name)', weight=_WEIGHT_READ_CONTENTS) |
320 def encoding(mctx, x): | 367 def encoding(mctx, x): |
321 """File can be successfully decoded with the given character | 368 """File can be successfully decoded with the given character |
322 encoding. May not be useful for encodings other than ASCII and | 369 encoding. May not be useful for encodings other than ASCII and |
335 raise error.Abort(_("unknown encoding '%s'") % enc) | 382 raise error.Abort(_("unknown encoding '%s'") % enc) |
336 except UnicodeDecodeError: | 383 except UnicodeDecodeError: |
337 return False | 384 return False |
338 | 385 |
339 return mctx.fpredicate(encp, predrepr=('encoding(%r)', enc), cache=True) | 386 return mctx.fpredicate(encp, predrepr=('encoding(%r)', enc), cache=True) |
387 | |
340 | 388 |
341 @predicate('eol(style)', weight=_WEIGHT_READ_CONTENTS) | 389 @predicate('eol(style)', weight=_WEIGHT_READ_CONTENTS) |
342 def eol(mctx, x): | 390 def eol(mctx, x): |
343 """File contains newlines of the given style (dos, unix, mac). Binary | 391 """File contains newlines of the given style (dos, unix, mac). Binary |
344 files are excluded, files with mixed line endings match multiple | 392 files are excluded, files with mixed line endings match multiple |
357 elif enc == 'unix' and re.search('(?<!\r)\n', d): | 405 elif enc == 'unix' and re.search('(?<!\r)\n', d): |
358 return True | 406 return True |
359 elif enc == 'mac' and re.search('\r(?!\n)', d): | 407 elif enc == 'mac' and re.search('\r(?!\n)', d): |
360 return True | 408 return True |
361 return False | 409 return False |
410 | |
362 return mctx.fpredicate(eolp, predrepr=('eol(%r)', enc), cache=True) | 411 return mctx.fpredicate(eolp, predrepr=('eol(%r)', enc), cache=True) |
412 | |
363 | 413 |
364 @predicate('copied()') | 414 @predicate('copied()') |
365 def copied(mctx, x): | 415 def copied(mctx, x): |
366 """File that is recorded as being copied. | 416 """File that is recorded as being copied. |
367 """ | 417 """ |
368 # i18n: "copied" is a keyword | 418 # i18n: "copied" is a keyword |
369 getargs(x, 0, 0, _("copied takes no arguments")) | 419 getargs(x, 0, 0, _("copied takes no arguments")) |
420 | |
370 def copiedp(fctx): | 421 def copiedp(fctx): |
371 p = fctx.parents() | 422 p = fctx.parents() |
372 return p and p[0].path() != fctx.path() | 423 return p and p[0].path() != fctx.path() |
424 | |
373 return mctx.fpredicate(copiedp, predrepr='copied', cache=True) | 425 return mctx.fpredicate(copiedp, predrepr='copied', cache=True) |
426 | |
374 | 427 |
375 @predicate('revs(revs, pattern)', weight=_WEIGHT_STATUS) | 428 @predicate('revs(revs, pattern)', weight=_WEIGHT_STATUS) |
376 def revs(mctx, x): | 429 def revs(mctx, x): |
377 """Evaluate set in the specified revisions. If the revset match multiple | 430 """Evaluate set in the specified revisions. If the revset match multiple |
378 revs, this will return file matching pattern in any of the revision. | 431 revs, this will return file matching pattern in any of the revision. |
392 if not matchers: | 445 if not matchers: |
393 return mctx.never() | 446 return mctx.never() |
394 if len(matchers) == 1: | 447 if len(matchers) == 1: |
395 return matchers[0] | 448 return matchers[0] |
396 return matchmod.unionmatcher(matchers) | 449 return matchmod.unionmatcher(matchers) |
450 | |
397 | 451 |
398 @predicate('status(base, rev, pattern)', weight=_WEIGHT_STATUS) | 452 @predicate('status(base, rev, pattern)', weight=_WEIGHT_STATUS) |
399 def status(mctx, x): | 453 def status(mctx, x): |
400 """Evaluate predicate using status change between ``base`` and | 454 """Evaluate predicate using status change between ``base`` and |
401 ``rev``. Examples: | 455 ``rev``. Examples: |
416 raise error.ParseError(reverr) | 470 raise error.ParseError(reverr) |
417 basectx, ctx = scmutil.revpair(repo, [baserevspec, revspec]) | 471 basectx, ctx = scmutil.revpair(repo, [baserevspec, revspec]) |
418 mc = mctx.switch(basectx, ctx) | 472 mc = mctx.switch(basectx, ctx) |
419 return getmatch(mc, x) | 473 return getmatch(mc, x) |
420 | 474 |
475 | |
421 @predicate('subrepo([pattern])') | 476 @predicate('subrepo([pattern])') |
422 def subrepo(mctx, x): | 477 def subrepo(mctx, x): |
423 """Subrepositories whose paths match the given pattern. | 478 """Subrepositories whose paths match the given pattern. |
424 """ | 479 """ |
425 # i18n: "subrepo" is a keyword | 480 # i18n: "subrepo" is a keyword |
426 getargs(x, 0, 1, _("subrepo takes at most one argument")) | 481 getargs(x, 0, 1, _("subrepo takes at most one argument")) |
427 ctx = mctx.ctx | 482 ctx = mctx.ctx |
428 sstate = ctx.substate | 483 sstate = ctx.substate |
429 if x: | 484 if x: |
430 pat = getpattern(x, matchmod.allpatternkinds, | 485 pat = getpattern( |
431 # i18n: "subrepo" is a keyword | 486 x, |
432 _("subrepo requires a pattern or no arguments")) | 487 matchmod.allpatternkinds, |
488 # i18n: "subrepo" is a keyword | |
489 _("subrepo requires a pattern or no arguments"), | |
490 ) | |
433 fast = not matchmod.patkind(pat) | 491 fast = not matchmod.patkind(pat) |
434 if fast: | 492 if fast: |
493 | |
435 def m(s): | 494 def m(s): |
436 return (s == pat) | 495 return s == pat |
496 | |
437 else: | 497 else: |
438 m = matchmod.match(ctx.repo().root, '', [pat], ctx=ctx) | 498 m = matchmod.match(ctx.repo().root, '', [pat], ctx=ctx) |
439 return mctx.predicate(lambda f: f in sstate and m(f), | 499 return mctx.predicate( |
440 predrepr=('subrepo(%r)', pat)) | 500 lambda f: f in sstate and m(f), predrepr=('subrepo(%r)', pat) |
501 ) | |
441 else: | 502 else: |
442 return mctx.predicate(sstate.__contains__, predrepr='subrepo') | 503 return mctx.predicate(sstate.__contains__, predrepr='subrepo') |
504 | |
443 | 505 |
444 methods = { | 506 methods = { |
445 'withstatus': getmatchwithstatus, | 507 'withstatus': getmatchwithstatus, |
446 'string': stringmatch, | 508 'string': stringmatch, |
447 'symbol': stringmatch, | 509 'symbol': stringmatch, |
453 'list': listmatch, | 515 'list': listmatch, |
454 'not': notmatch, | 516 'not': notmatch, |
455 'func': func, | 517 'func': func, |
456 } | 518 } |
457 | 519 |
520 | |
458 class matchctx(object): | 521 class matchctx(object): |
459 def __init__(self, basectx, ctx, badfn=None): | 522 def __init__(self, basectx, ctx, badfn=None): |
460 self._basectx = basectx | 523 self._basectx = basectx |
461 self.ctx = ctx | 524 self.ctx = ctx |
462 self._badfn = badfn | 525 self._badfn = badfn |
482 mctx._match = self._match | 545 mctx._match = self._match |
483 mctx._buildstatus(keys) | 546 mctx._buildstatus(keys) |
484 return mctx | 547 return mctx |
485 | 548 |
486 def _buildstatus(self, keys): | 549 def _buildstatus(self, keys): |
487 self._status = self._basectx.status(self.ctx, self._match, | 550 self._status = self._basectx.status( |
488 listignored='ignored' in keys, | 551 self.ctx, |
489 listclean='clean' in keys, | 552 self._match, |
490 listunknown='unknown' in keys) | 553 listignored='ignored' in keys, |
554 listclean='clean' in keys, | |
555 listunknown='unknown' in keys, | |
556 ) | |
491 | 557 |
492 def status(self): | 558 def status(self): |
493 return self._status | 559 return self._status |
494 | 560 |
495 def matcher(self, patterns): | 561 def matcher(self, patterns): |
497 | 563 |
498 def predicate(self, predfn, predrepr=None, cache=False): | 564 def predicate(self, predfn, predrepr=None, cache=False): |
499 """Create a matcher to select files by predfn(filename)""" | 565 """Create a matcher to select files by predfn(filename)""" |
500 if cache: | 566 if cache: |
501 predfn = util.cachefunc(predfn) | 567 predfn = util.cachefunc(predfn) |
502 return matchmod.predicatematcher(predfn, predrepr=predrepr, | 568 return matchmod.predicatematcher( |
503 badfn=self._badfn) | 569 predfn, predrepr=predrepr, badfn=self._badfn |
570 ) | |
504 | 571 |
505 def fpredicate(self, predfn, predrepr=None, cache=False): | 572 def fpredicate(self, predfn, predrepr=None, cache=False): |
506 """Create a matcher to select files by predfn(fctx) at the current | 573 """Create a matcher to select files by predfn(fctx) at the current |
507 revision | 574 revision |
508 | 575 |
509 Missing files are ignored. | 576 Missing files are ignored. |
510 """ | 577 """ |
511 ctx = self.ctx | 578 ctx = self.ctx |
512 if ctx.rev() is None: | 579 if ctx.rev() is None: |
580 | |
513 def fctxpredfn(f): | 581 def fctxpredfn(f): |
514 try: | 582 try: |
515 fctx = ctx[f] | 583 fctx = ctx[f] |
516 except error.LookupError: | 584 except error.LookupError: |
517 return False | 585 return False |
521 return False | 589 return False |
522 try: | 590 try: |
523 return predfn(fctx) | 591 return predfn(fctx) |
524 except (IOError, OSError) as e: | 592 except (IOError, OSError) as e: |
525 # open()-ing a directory fails with EACCES on Windows | 593 # open()-ing a directory fails with EACCES on Windows |
526 if e.errno in (errno.ENOENT, errno.EACCES, errno.ENOTDIR, | 594 if e.errno in ( |
527 errno.EISDIR): | 595 errno.ENOENT, |
596 errno.EACCES, | |
597 errno.ENOTDIR, | |
598 errno.EISDIR, | |
599 ): | |
528 return False | 600 return False |
529 raise | 601 raise |
602 | |
530 else: | 603 else: |
604 | |
531 def fctxpredfn(f): | 605 def fctxpredfn(f): |
532 try: | 606 try: |
533 fctx = ctx[f] | 607 fctx = ctx[f] |
534 except error.LookupError: | 608 except error.LookupError: |
535 return False | 609 return False |
536 return predfn(fctx) | 610 return predfn(fctx) |
611 | |
537 return self.predicate(fctxpredfn, predrepr=predrepr, cache=cache) | 612 return self.predicate(fctxpredfn, predrepr=predrepr, cache=cache) |
538 | 613 |
539 def never(self): | 614 def never(self): |
540 """Create a matcher to select nothing""" | 615 """Create a matcher to select nothing""" |
541 return matchmod.never(badfn=self._badfn) | 616 return matchmod.never(badfn=self._badfn) |
617 | |
542 | 618 |
543 def match(ctx, expr, badfn=None): | 619 def match(ctx, expr, badfn=None): |
544 """Create a matcher for a single fileset expression""" | 620 """Create a matcher for a single fileset expression""" |
545 tree = filesetlang.parse(expr) | 621 tree = filesetlang.parse(expr) |
546 tree = filesetlang.analyze(tree) | 622 tree = filesetlang.analyze(tree) |
553 """Load fileset predicates from specified registrarobj | 629 """Load fileset predicates from specified registrarobj |
554 """ | 630 """ |
555 for name, func in registrarobj._table.iteritems(): | 631 for name, func in registrarobj._table.iteritems(): |
556 symbols[name] = func | 632 symbols[name] = func |
557 | 633 |
634 | |
558 # tell hggettext to extract docstrings from these functions: | 635 # tell hggettext to extract docstrings from these functions: |
559 i18nfunctions = symbols.values() | 636 i18nfunctions = symbols.values() |