Show More
@@ -255,9 +255,6 b' def revset(repo, pats, opts):' | |||||
255 | 'removed': ('removes("*")', None), |
|
255 | 'removed': ('removes("*")', None), | |
256 | 'date': ('date(%(val)r)', None), |
|
256 | 'date': ('date(%(val)r)', None), | |
257 | 'branch': ('branch(%(val)r)', ' or '), |
|
257 | 'branch': ('branch(%(val)r)', ' or '), | |
258 | 'exclude': ('not file(%(val)r)', ' and '), |
|
|||
259 | 'include': ('file(%(val)r)', ' and '), |
|
|||
260 | '_pats': ('file(%(val)r)', ' or '), |
|
|||
261 | '_patslog': ('filelog(%(val)r)', ' or '), |
|
258 | '_patslog': ('filelog(%(val)r)', ' or '), | |
262 | 'keyword': ('keyword(%(val)r)', ' or '), |
|
259 | 'keyword': ('keyword(%(val)r)', ' or '), | |
263 | 'prune': ('not (%(val)r or ancestors(%(val)r))', ' and '), |
|
260 | 'prune': ('not (%(val)r or ancestors(%(val)r))', ' and '), | |
@@ -281,8 +278,21 b' def revset(repo, pats, opts):' | |||||
281 | # try to find matching entries on the slow path. |
|
278 | # try to find matching entries on the slow path. | |
282 | slowpath = True |
|
279 | slowpath = True | |
283 | if slowpath: |
|
280 | if slowpath: | |
284 | # See cmdutil.walkchangerevs() slow path |
|
281 | # See cmdutil.walkchangerevs() slow path. | |
285 | opts['_pats'] = list(pats) |
|
282 | # | |
|
283 | # pats/include/exclude cannot be represented as separate | |||
|
284 | # revset expressions as their filtering logic applies at file | |||
|
285 | # level. For instance "-I a -X a" matches a revision touching | |||
|
286 | # "a" and "b" while "file(a) and not file(b)" does not. | |||
|
287 | matchargs = [] | |||
|
288 | for p in pats: | |||
|
289 | matchargs.append('p:' + p) | |||
|
290 | for p in opts.get('include', []): | |||
|
291 | matchargs.append('i:' + p) | |||
|
292 | for p in opts.get('exclude', []): | |||
|
293 | matchargs.append('x:' + p) | |||
|
294 | matchargs = ','.join(('%r' % p) for p in matchargs) | |||
|
295 | opts['rev'] = opts.get('rev', []) + ['_matchfiles(%s)' % matchargs] | |||
286 | else: |
|
296 | else: | |
287 | opts['_patslog'] = list(pats) |
|
297 | opts['_patslog'] = list(pats) | |
288 |
|
298 |
@@ -112,7 +112,7 b' def getlist(x):' | |||||
112 |
|
112 | |||
113 | def getargs(x, min, max, err): |
|
113 | def getargs(x, min, max, err): | |
114 | l = getlist(x) |
|
114 | l = getlist(x) | |
115 | if len(l) < min or len(l) > max: |
|
115 | if len(l) < min or (max >= 0 and len(l) > max): | |
116 | raise error.ParseError(err) |
|
116 | raise error.ParseError(err) | |
117 | return l |
|
117 | return l | |
118 |
|
118 | |||
@@ -493,23 +493,52 b' def grep(repo, subset, x):' | |||||
493 | break |
|
493 | break | |
494 | return l |
|
494 | return l | |
495 |
|
495 | |||
|
496 | def _matchfiles(repo, subset, x): | |||
|
497 | # _matchfiles takes a revset list of prefixed arguments: | |||
|
498 | # | |||
|
499 | # [p:foo, i:bar, x:baz] | |||
|
500 | # | |||
|
501 | # builds a match object from them and filters subset. Allowed | |||
|
502 | # prefixes are 'p:' for regular patterns, 'i:' for include | |||
|
503 | # patterns and 'x:' for exclude patterns. | |||
|
504 | ||||
|
505 | # i18n: "_matchfiles" is a keyword | |||
|
506 | l = getargs(x, 1, -1, _("_matchfiles requires at least one argument")) | |||
|
507 | pats, inc, exc = [], [], [] | |||
|
508 | hasset = False | |||
|
509 | for arg in l: | |||
|
510 | s = getstring(arg, _("_matchfiles requires string arguments")) | |||
|
511 | prefix, value = s[:2], s[2:] | |||
|
512 | if prefix == 'p:': | |||
|
513 | pats.append(value) | |||
|
514 | elif prefix == 'i:': | |||
|
515 | inc.append(value) | |||
|
516 | elif prefix == 'x:': | |||
|
517 | exc.append(value) | |||
|
518 | else: | |||
|
519 | raise error.ParseError(_('invalid _matchfiles prefix: %s') % prefix) | |||
|
520 | if not hasset and matchmod.patkind(value) == 'set': | |||
|
521 | hasset = True | |||
|
522 | m = None | |||
|
523 | s = [] | |||
|
524 | for r in subset: | |||
|
525 | c = repo[r] | |||
|
526 | if not m or hasset: | |||
|
527 | m = matchmod.match(repo.root, repo.getcwd(), pats, include=inc, | |||
|
528 | exclude=exc, ctx=c) | |||
|
529 | for f in c.files(): | |||
|
530 | if m(f): | |||
|
531 | s.append(r) | |||
|
532 | break | |||
|
533 | return s | |||
|
534 | ||||
496 | def hasfile(repo, subset, x): |
|
535 | def hasfile(repo, subset, x): | |
497 | """``file(pattern)`` |
|
536 | """``file(pattern)`` | |
498 | Changesets affecting files matched by pattern. |
|
537 | Changesets affecting files matched by pattern. | |
499 | """ |
|
538 | """ | |
500 | # i18n: "file" is a keyword |
|
539 | # i18n: "file" is a keyword | |
501 | pat = getstring(x, _("file requires a pattern")) |
|
540 | pat = getstring(x, _("file requires a pattern")) | |
502 | m = None |
|
541 | return _matchfiles(repo, subset, ('string', 'p:' + pat)) | |
503 | s = [] |
|
|||
504 | for r in subset: |
|
|||
505 | c = repo[r] |
|
|||
506 | if not m or matchmod.patkind(pat) == 'set': |
|
|||
507 | m = matchmod.match(repo.root, repo.getcwd(), [pat], ctx=c) |
|
|||
508 | for f in c.files(): |
|
|||
509 | if m(f): |
|
|||
510 | s.append(r) |
|
|||
511 | break |
|
|||
512 | return s |
|
|||
513 |
|
542 | |||
514 | def head(repo, subset, x): |
|
543 | def head(repo, subset, x): | |
515 | """``head()`` |
|
544 | """``head()`` | |
@@ -943,6 +972,7 b' symbols = {' | |||||
943 | "keyword": keyword, |
|
972 | "keyword": keyword, | |
944 | "last": last, |
|
973 | "last": last, | |
945 | "limit": limit, |
|
974 | "limit": limit, | |
|
975 | "_matchfiles": _matchfiles, | |||
946 | "max": maxrev, |
|
976 | "max": maxrev, | |
947 | "merge": merge, |
|
977 | "merge": merge, | |
948 | "min": minrev, |
|
978 | "min": minrev, |
@@ -1437,7 +1437,6 b' Test log -G options' | |||||
1437 | ('group', ('group', ('or', ('or', ('func', ('symbol', 'branch'), ('string', 'default')), ('func', ('symbol', 'branch'), ('string', 'branch'))), ('func', ('symbol', 'branch'), ('string', 'branch'))))) |
|
1437 | ('group', ('group', ('or', ('or', ('func', ('symbol', 'branch'), ('string', 'default')), ('func', ('symbol', 'branch'), ('string', 'branch'))), ('func', ('symbol', 'branch'), ('string', 'branch'))))) | |
1438 | $ testlog -k expand -k merge |
|
1438 | $ testlog -k expand -k merge | |
1439 | ('group', ('group', ('or', ('func', ('symbol', 'keyword'), ('string', 'expand')), ('func', ('symbol', 'keyword'), ('string', 'merge'))))) |
|
1439 | ('group', ('group', ('or', ('func', ('symbol', 'keyword'), ('string', 'expand')), ('func', ('symbol', 'keyword'), ('string', 'merge'))))) | |
1440 | $ hg log -G --include 'some file' --exclude 'another file' |
|
|||
1441 | $ hg log -G --follow --template 'nodetag {rev}\n' | grep nodetag | wc -l |
|
1440 | $ hg log -G --follow --template 'nodetag {rev}\n' | grep nodetag | wc -l | |
1442 | \s*36 (re) |
|
1441 | \s*36 (re) | |
1443 | $ hg log -G --removed --template 'nodetag {rev}\n' | grep nodetag | wc -l |
|
1442 | $ hg log -G --removed --template 'nodetag {rev}\n' | grep nodetag | wc -l | |
@@ -1527,4 +1526,9 b' Dedicated repo for --follow and paths fi' | |||||
1527 | Test falling back to slow path for non-existing files |
|
1526 | Test falling back to slow path for non-existing files | |
1528 |
|
1527 | |||
1529 | $ testlog a c |
|
1528 | $ testlog a c | |
1530 |
('group', ('group', (' |
|
1529 | ('group', ('group', ('func', ('symbol', '_matchfiles'), ('list', ('string', 'p:a'), ('string', 'p:c'))))) | |
|
1530 | ||||
|
1531 | Test multiple --include/--exclude/paths | |||
|
1532 | ||||
|
1533 | $ testlog --include a --include e --exclude b --exclude e a e | |||
|
1534 | ('group', ('group', ('func', ('symbol', '_matchfiles'), ('list', ('list', ('list', ('list', ('list', ('string', 'p:a'), ('string', 'p:e')), ('string', 'i:a')), ('string', 'i:e')), ('string', 'x:b')), ('string', 'x:e'))))) |
General Comments 0
You need to be logged in to leave comments.
Login now