##// END OF EJS Templates
graphlog: paths/-I/-X handling requires a new revset...
Patrick Mezard -
r16161:5a627b49 default
parent child Browse files
Show More
@@ -255,9 +255,6 b' def revset(repo, pats, opts):'
255 255 'removed': ('removes("*")', None),
256 256 'date': ('date(%(val)r)', None),
257 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 258 '_patslog': ('filelog(%(val)r)', ' or '),
262 259 'keyword': ('keyword(%(val)r)', ' or '),
263 260 'prune': ('not (%(val)r or ancestors(%(val)r))', ' and '),
@@ -281,8 +278,21 b' def revset(repo, pats, opts):'
281 278 # try to find matching entries on the slow path.
282 279 slowpath = True
283 280 if slowpath:
284 # See cmdutil.walkchangerevs() slow path
285 opts['_pats'] = list(pats)
281 # See cmdutil.walkchangerevs() slow path.
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 296 else:
287 297 opts['_patslog'] = list(pats)
288 298
@@ -112,7 +112,7 b' def getlist(x):'
112 112
113 113 def getargs(x, min, max, err):
114 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 116 raise error.ParseError(err)
117 117 return l
118 118
@@ -493,23 +493,52 b' def grep(repo, subset, x):'
493 493 break
494 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 535 def hasfile(repo, subset, x):
497 536 """``file(pattern)``
498 537 Changesets affecting files matched by pattern.
499 538 """
500 539 # i18n: "file" is a keyword
501 540 pat = getstring(x, _("file requires a pattern"))
502 m = None
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
541 return _matchfiles(repo, subset, ('string', 'p:' + pat))
513 542
514 543 def head(repo, subset, x):
515 544 """``head()``
@@ -943,6 +972,7 b' symbols = {'
943 972 "keyword": keyword,
944 973 "last": last,
945 974 "limit": limit,
975 "_matchfiles": _matchfiles,
946 976 "max": maxrev,
947 977 "merge": merge,
948 978 "min": minrev,
@@ -1437,7 +1437,6 b' Test log -G options'
1437 1437 ('group', ('group', ('or', ('or', ('func', ('symbol', 'branch'), ('string', 'default')), ('func', ('symbol', 'branch'), ('string', 'branch'))), ('func', ('symbol', 'branch'), ('string', 'branch')))))
1438 1438 $ testlog -k expand -k merge
1439 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 1440 $ hg log -G --follow --template 'nodetag {rev}\n' | grep nodetag | wc -l
1442 1441 \s*36 (re)
1443 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 1526 Test falling back to slow path for non-existing files
1528 1527
1529 1528 $ testlog a c
1530 ('group', ('group', ('or', ('func', ('symbol', 'file'), ('string', 'a')), ('func', ('symbol', 'file'), ('string', 'c')))))
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