Mercurial > public > mercurial-scm > hg
comparison mercurial/revset.py @ 16161:5a627b49b4d9
graphlog: paths/-I/-X handling requires a new revset
The filtering logic of match objects cannot be reproduced with the existing
revsets as it operates at changeset files level. A changeset touching "a" and
"b" is matched by "-I a -X b" but not by "file(a) and not file(b)".
To solve this, a new internal "_matchfiles(...)" revset is introduced. It works
like "file(x)" but accepts more than one argument and its arguments are
prefixed with "p:", "i:" and "x:" to be used as patterns, include patterns or
exclude patterns respectively.
The _matchfiles revset is kept private for now:
- There are probably smarter ways to pass the arguments in a user-friendly way
- A "rev:" argument is likely appear at some point to emulate log command
behaviour with regard to filesets: they are evaluated for the parent revision
and applied everywhere instead of being reevaluated for each revision.
author | Patrick Mezard <patrick@mezard.eu> |
---|---|
date | Thu, 23 Feb 2012 18:05:20 +0100 |
parents | b8be450638f6 |
children | 0a73c4bd9f47 |
comparison
equal
deleted
inserted
replaced
16160:1bfc7ba8b404 | 16161:5a627b49b4d9 |
---|---|
110 return getlist(x[1]) + [x[2]] | 110 return getlist(x[1]) + [x[2]] |
111 return [x] | 111 return [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 |
119 def getset(repo, subset, x): | 119 def getset(repo, subset, x): |
120 if not x: | 120 if not x: |
491 if gr.search(e): | 491 if gr.search(e): |
492 l.append(r) | 492 l.append(r) |
493 break | 493 break |
494 return l | 494 return l |
495 | 495 |
496 def hasfile(repo, subset, x): | 496 def _matchfiles(repo, subset, x): |
497 """``file(pattern)`` | 497 # _matchfiles takes a revset list of prefixed arguments: |
498 Changesets affecting files matched by pattern. | 498 # |
499 """ | 499 # [p:foo, i:bar, x:baz] |
500 # i18n: "file" is a keyword | 500 # |
501 pat = getstring(x, _("file requires a pattern")) | 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 | |
502 m = None | 522 m = None |
503 s = [] | 523 s = [] |
504 for r in subset: | 524 for r in subset: |
505 c = repo[r] | 525 c = repo[r] |
506 if not m or matchmod.patkind(pat) == 'set': | 526 if not m or hasset: |
507 m = matchmod.match(repo.root, repo.getcwd(), [pat], ctx=c) | 527 m = matchmod.match(repo.root, repo.getcwd(), pats, include=inc, |
528 exclude=exc, ctx=c) | |
508 for f in c.files(): | 529 for f in c.files(): |
509 if m(f): | 530 if m(f): |
510 s.append(r) | 531 s.append(r) |
511 break | 532 break |
512 return s | 533 return s |
534 | |
535 def hasfile(repo, subset, x): | |
536 """``file(pattern)`` | |
537 Changesets affecting files matched by pattern. | |
538 """ | |
539 # i18n: "file" is a keyword | |
540 pat = getstring(x, _("file requires a pattern")) | |
541 return _matchfiles(repo, subset, ('string', 'p:' + pat)) | |
513 | 542 |
514 def head(repo, subset, x): | 543 def head(repo, subset, x): |
515 """``head()`` | 544 """``head()`` |
516 Changeset is a named branch head. | 545 Changeset is a named branch head. |
517 """ | 546 """ |
941 "heads": heads, | 970 "heads": heads, |
942 "id": node, | 971 "id": node, |
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, |
949 "modifies": modifies, | 979 "modifies": modifies, |
950 "outgoing": outgoing, | 980 "outgoing": outgoing, |