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()