Mercurial > public > mercurial-scm > hg-stable
comparison mercurial/revset.py @ 45725:99b8b73eb622
revset: add diff(pattern) predicate for "grep --diff"
I find this is useful in GUI log viewer since the tool only needs to support
"log -rREV" command.
This is basic implementation. Windowed search is not implemented since it
wouldn't work pretty well with the smartset API. And filename matcher is
not supported because the syntax isn't determined. My idea is to add handling
of diff(pattern, file(..)) and diff(pattern, follow(..)), which will then be
evolved to a full revset+matcher combinator support:
x & diff(pattern, y & z)
=====
y & z builds (revs(y) & revs(z), matcher(y) & matcher(z))
pair, and narrows the search space of diff()
====================
diff() returns matched (revs, matcher) pair
========================
revs and matcher will be combined respectively by &-operator, and the matcher
will optionally be used to filter "hg log -p" output
The predicate name "diff()" wouldn't be great, but grep() is already used.
Another options I can think of are "grepdiff()" and "containsdiff()".
Naming suggestions are welcome.
author | Yuya Nishihara <yuya@tcha.org> |
---|---|
date | Tue, 08 Sep 2020 18:16:24 +0900 |
parents | b90d7e7f39db |
children | c00595736595 |
comparison
equal
deleted
inserted
replaced
45724:ac39a8a214b1 | 45725:99b8b73eb622 |
---|---|
15 dagop, | 15 dagop, |
16 destutil, | 16 destutil, |
17 diffutil, | 17 diffutil, |
18 encoding, | 18 encoding, |
19 error, | 19 error, |
20 grep as grepmod, | |
20 hbisect, | 21 hbisect, |
21 match as matchmod, | 22 match as matchmod, |
22 node, | 23 node, |
23 obsolete as obsmod, | 24 obsolete as obsmod, |
24 obsutil, | 25 obsutil, |
991 dests.__contains__, | 992 dests.__contains__, |
992 condrepr=lambda: b'<destination %r>' % _sortedb(dests), | 993 condrepr=lambda: b'<destination %r>' % _sortedb(dests), |
993 ) | 994 ) |
994 | 995 |
995 | 996 |
997 @predicate(b'diff(pattern)', weight=110) | |
998 def diff(repo, subset, x): | |
999 """Search revision differences for when the pattern was added or removed. | |
1000 | |
1001 The pattern may be a substring literal or a regular expression. See | |
1002 :hg:`help revisions.patterns`. | |
1003 """ | |
1004 args = getargsdict(x, b'diff', b'pattern') | |
1005 if b'pattern' not in args: | |
1006 # i18n: "diff" is a keyword | |
1007 raise error.ParseError(_(b'diff takes at least 1 argument')) | |
1008 | |
1009 pattern = getstring(args[b'pattern'], _(b'diff requires a string pattern')) | |
1010 regexp = stringutil.substringregexp(pattern, re.M) | |
1011 | |
1012 # TODO: add support for file pattern and --follow. For example, | |
1013 # diff(pattern[, set]) where set may be file(pattern) or follow(pattern), | |
1014 # and we'll eventually add a support for narrowing files by revset? | |
1015 fmatch = matchmod.always() | |
1016 | |
1017 def makefilematcher(ctx): | |
1018 return fmatch | |
1019 | |
1020 # TODO: search in a windowed way | |
1021 searcher = grepmod.grepsearcher(repo.ui, repo, regexp, diff=True) | |
1022 | |
1023 def testdiff(rev): | |
1024 # consume the generator to discard revfiles/matches cache | |
1025 found = False | |
1026 for fn, ctx, pstates, states in searcher.searchfiles( | |
1027 baseset([rev]), makefilematcher | |
1028 ): | |
1029 if next(grepmod.difflinestates(pstates, states), None): | |
1030 found = True | |
1031 return found | |
1032 | |
1033 return subset.filter(testdiff, condrepr=(b'<diff %r>', pattern)) | |
1034 | |
1035 | |
996 @predicate(b'contentdivergent()', safe=True) | 1036 @predicate(b'contentdivergent()', safe=True) |
997 def contentdivergent(repo, subset, x): | 1037 def contentdivergent(repo, subset, x): |
998 """ | 1038 """ |
999 Final successors of changesets with an alternative set of final | 1039 Final successors of changesets with an alternative set of final |
1000 successors. (EXPERIMENTAL) | 1040 successors. (EXPERIMENTAL) |