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,