comparison mercurial/revset.py @ 28424:534f968d33e5

revset: add inspection data to all filter() calls This is useful for debugging revset construction.
author Yuya Nishihara <yuya@tcha.org>
date Sat, 13 Feb 2016 20:05:57 +0900
parents 0d79d91ba7e3
children 02d7faaf455c
comparison
equal deleted inserted replaced
28423:0d79d91ba7e3 28424:534f968d33e5
598 """Alias for ``user(string)``. 598 """Alias for ``user(string)``.
599 """ 599 """
600 # i18n: "author" is a keyword 600 # i18n: "author" is a keyword
601 n = encoding.lower(getstring(x, _("author requires a string"))) 601 n = encoding.lower(getstring(x, _("author requires a string")))
602 kind, pattern, matcher = _substringmatcher(n) 602 kind, pattern, matcher = _substringmatcher(n)
603 return subset.filter(lambda x: matcher(encoding.lower(repo[x].user()))) 603 return subset.filter(lambda x: matcher(encoding.lower(repo[x].user())),
604 condrepr=('<user %r>', n))
604 605
605 @predicate('bisect(string)', safe=True) 606 @predicate('bisect(string)', safe=True)
606 def bisect(repo, subset, x): 607 def bisect(repo, subset, x):
607 """Changesets marked in the specified bisect status: 608 """Changesets marked in the specified bisect status:
608 609
684 kind, pattern, matcher = util.stringmatcher(b) 685 kind, pattern, matcher = util.stringmatcher(b)
685 if kind == 'literal': 686 if kind == 'literal':
686 # note: falls through to the revspec case if no branch with 687 # note: falls through to the revspec case if no branch with
687 # this name exists and pattern kind is not specified explicitly 688 # this name exists and pattern kind is not specified explicitly
688 if pattern in repo.branchmap(): 689 if pattern in repo.branchmap():
689 return subset.filter(lambda r: matcher(getbi(r)[0])) 690 return subset.filter(lambda r: matcher(getbi(r)[0]),
691 condrepr=('<branch %r>', b))
690 if b.startswith('literal:'): 692 if b.startswith('literal:'):
691 raise error.RepoLookupError(_("branch '%s' does not exist") 693 raise error.RepoLookupError(_("branch '%s' does not exist")
692 % pattern) 694 % pattern)
693 else: 695 else:
694 return subset.filter(lambda r: matcher(getbi(r)[0])) 696 return subset.filter(lambda r: matcher(getbi(r)[0]),
697 condrepr=('<branch %r>', b))
695 698
696 s = getset(repo, fullreposet(repo), x) 699 s = getset(repo, fullreposet(repo), x)
697 b = set() 700 b = set()
698 for r in s: 701 for r in s:
699 b.add(getbi(r)[0]) 702 b.add(getbi(r)[0])
700 c = s.__contains__ 703 c = s.__contains__
701 return subset.filter(lambda r: c(r) or getbi(r)[0] in b) 704 return subset.filter(lambda r: c(r) or getbi(r)[0] in b,
705 condrepr=lambda: '<branch %r>' % sorted(b))
702 706
703 @predicate('bumped()', safe=True) 707 @predicate('bumped()', safe=True)
704 def bumped(repo, subset, x): 708 def bumped(repo, subset, x):
705 """Mutable changesets marked as successors of public changesets. 709 """Mutable changesets marked as successors of public changesets.
706 710
751 else: 755 else:
752 for f in files: 756 for f in files:
753 if m(f): 757 if m(f):
754 return True 758 return True
755 759
756 return subset.filter(matches) 760 return subset.filter(matches, condrepr=('<status[%r] %r>', field, pat))
757 761
758 def _children(repo, narrow, parentset): 762 def _children(repo, narrow, parentset):
759 if not parentset: 763 if not parentset:
760 return baseset() 764 return baseset()
761 cs = set() 765 cs = set()
783 def closed(repo, subset, x): 787 def closed(repo, subset, x):
784 """Changeset is closed. 788 """Changeset is closed.
785 """ 789 """
786 # i18n: "closed" is a keyword 790 # i18n: "closed" is a keyword
787 getargs(x, 0, 0, _("closed takes no arguments")) 791 getargs(x, 0, 0, _("closed takes no arguments"))
788 return subset.filter(lambda r: repo[r].closesbranch()) 792 return subset.filter(lambda r: repo[r].closesbranch(),
793 condrepr='<branch closed>')
789 794
790 @predicate('contains(pattern)') 795 @predicate('contains(pattern)')
791 def contains(repo, subset, x): 796 def contains(repo, subset, x):
792 """The revision's manifest contains a file matching pattern (but might not 797 """The revision's manifest contains a file matching pattern (but might not
793 modify it). See :hg:`help patterns` for information about file patterns. 798 modify it). See :hg:`help patterns` for information about file patterns.
810 for f in c.manifest(): 815 for f in c.manifest():
811 if m(f): 816 if m(f):
812 return True 817 return True
813 return False 818 return False
814 819
815 return subset.filter(matches) 820 return subset.filter(matches, condrepr=('<contains %r>', pat))
816 821
817 @predicate('converted([id])', safe=True) 822 @predicate('converted([id])', safe=True)
818 def converted(repo, subset, x): 823 def converted(repo, subset, x):
819 """Changesets converted from the given identifier in the old repository if 824 """Changesets converted from the given identifier in the old repository if
820 present, or all converted changesets if no identifier is specified. 825 present, or all converted changesets if no identifier is specified.
832 837
833 def _matchvalue(r): 838 def _matchvalue(r):
834 source = repo[r].extra().get('convert_revision', None) 839 source = repo[r].extra().get('convert_revision', None)
835 return source is not None and (rev is None or source.startswith(rev)) 840 return source is not None and (rev is None or source.startswith(rev))
836 841
837 return subset.filter(lambda r: _matchvalue(r)) 842 return subset.filter(lambda r: _matchvalue(r),
843 condrepr=('<converted %r>', rev))
838 844
839 @predicate('date(interval)', safe=True) 845 @predicate('date(interval)', safe=True)
840 def date(repo, subset, x): 846 def date(repo, subset, x):
841 """Changesets within the interval, see :hg:`help dates`. 847 """Changesets within the interval, see :hg:`help dates`.
842 """ 848 """
843 # i18n: "date" is a keyword 849 # i18n: "date" is a keyword
844 ds = getstring(x, _("date requires a string")) 850 ds = getstring(x, _("date requires a string"))
845 dm = util.matchdate(ds) 851 dm = util.matchdate(ds)
846 return subset.filter(lambda x: dm(repo[x].date()[0])) 852 return subset.filter(lambda x: dm(repo[x].date()[0]),
853 condrepr=('<date %r>', ds))
847 854
848 @predicate('desc(string)', safe=True) 855 @predicate('desc(string)', safe=True)
849 def desc(repo, subset, x): 856 def desc(repo, subset, x):
850 """Search commit message for string. The match is case-insensitive. 857 """Search commit message for string. The match is case-insensitive.
851 """ 858 """
854 861
855 def matches(x): 862 def matches(x):
856 c = repo[x] 863 c = repo[x]
857 return ds in encoding.lower(c.description()) 864 return ds in encoding.lower(c.description())
858 865
859 return subset.filter(matches) 866 return subset.filter(matches, condrepr=('<desc %r>', ds))
860 867
861 def _descendants(repo, subset, x, followfirst=False): 868 def _descendants(repo, subset, x, followfirst=False):
862 roots = getset(repo, fullreposet(repo), x) 869 roots = getset(repo, fullreposet(repo), x)
863 if not roots: 870 if not roots:
864 return baseset() 871 return baseset()
929 break 936 break
930 937
931 r = src 938 r = src
932 src = _getrevsource(repo, r) 939 src = _getrevsource(repo, r)
933 940
934 return subset.filter(dests.__contains__) 941 return subset.filter(dests.__contains__,
942 condrepr=lambda: '<destination %r>' % sorted(dests))
935 943
936 @predicate('divergent()', safe=True) 944 @predicate('divergent()', safe=True)
937 def divergent(repo, subset, x): 945 def divergent(repo, subset, x):
938 """ 946 """
939 Final successors of changesets with an alternative set of final successors. 947 Final successors of changesets with an alternative set of final successors.
978 986
979 def _matchvalue(r): 987 def _matchvalue(r):
980 extra = repo[r].extra() 988 extra = repo[r].extra()
981 return label in extra and (value is None or matcher(extra[label])) 989 return label in extra and (value is None or matcher(extra[label]))
982 990
983 return subset.filter(lambda r: _matchvalue(r)) 991 return subset.filter(lambda r: _matchvalue(r),
992 condrepr=('<extra[%r] %r>', label, value))
984 993
985 @predicate('filelog(pattern)', safe=True) 994 @predicate('filelog(pattern)', safe=True)
986 def filelog(repo, subset, x): 995 def filelog(repo, subset, x):
987 """Changesets connected to the specified filelog. 996 """Changesets connected to the specified filelog.
988 997
1116 for e in c.files() + [c.user(), c.description()]: 1125 for e in c.files() + [c.user(), c.description()]:
1117 if gr.search(e): 1126 if gr.search(e):
1118 return True 1127 return True
1119 return False 1128 return False
1120 1129
1121 return subset.filter(matches) 1130 return subset.filter(matches, condrepr=('<grep %r>', gr.pattern))
1122 1131
1123 @predicate('_matchfiles', safe=True) 1132 @predicate('_matchfiles', safe=True)
1124 def _matchfiles(repo, subset, x): 1133 def _matchfiles(repo, subset, x):
1125 # _matchfiles takes a revset list of prefixed arguments: 1134 # _matchfiles takes a revset list of prefixed arguments:
1126 # 1135 #
1177 for f in files: 1186 for f in files:
1178 if m(f): 1187 if m(f):
1179 return True 1188 return True
1180 return False 1189 return False
1181 1190
1182 return subset.filter(matches) 1191 return subset.filter(matches,
1192 condrepr=('<matchfiles patterns=%r, include=%r '
1193 'exclude=%r, default=%r, rev=%r>',
1194 pats, inc, exc, default, rev))
1183 1195
1184 @predicate('file(pattern)', safe=True) 1196 @predicate('file(pattern)', safe=True)
1185 def hasfile(repo, subset, x): 1197 def hasfile(repo, subset, x):
1186 """Changesets affecting files matched by pattern. 1198 """Changesets affecting files matched by pattern.
1187 1199
1238 def matches(r): 1250 def matches(r):
1239 c = repo[r] 1251 c = repo[r]
1240 return any(kw in encoding.lower(t) 1252 return any(kw in encoding.lower(t)
1241 for t in c.files() + [c.user(), c.description()]) 1253 for t in c.files() + [c.user(), c.description()])
1242 1254
1243 return subset.filter(matches) 1255 return subset.filter(matches, condrepr=('<keyword %r>', kw))
1244 1256
1245 @predicate('limit(set[, n[, offset]])', safe=True) 1257 @predicate('limit(set[, n[, offset]])', safe=True)
1246 def limit(repo, subset, x): 1258 def limit(repo, subset, x):
1247 """First n members of set, defaulting to 1, starting from offset. 1259 """First n members of set, defaulting to 1, starting from offset.
1248 """ 1260 """
1324 """Changeset is a merge changeset. 1336 """Changeset is a merge changeset.
1325 """ 1337 """
1326 # i18n: "merge" is a keyword 1338 # i18n: "merge" is a keyword
1327 getargs(x, 0, 0, _("merge takes no arguments")) 1339 getargs(x, 0, 0, _("merge takes no arguments"))
1328 cl = repo.changelog 1340 cl = repo.changelog
1329 return subset.filter(lambda r: cl.parentrevs(r)[1] != -1) 1341 return subset.filter(lambda r: cl.parentrevs(r)[1] != -1,
1342 condrepr='<merge>')
1330 1343
1331 @predicate('branchpoint()', safe=True) 1344 @predicate('branchpoint()', safe=True)
1332 def branchpoint(repo, subset, x): 1345 def branchpoint(repo, subset, x):
1333 """Changesets with more than one child. 1346 """Changesets with more than one child.
1334 """ 1347 """
1343 parentscount = [0]*(len(repo) - baserev) 1356 parentscount = [0]*(len(repo) - baserev)
1344 for r in cl.revs(start=baserev + 1): 1357 for r in cl.revs(start=baserev + 1):
1345 for p in cl.parentrevs(r): 1358 for p in cl.parentrevs(r):
1346 if p >= baserev: 1359 if p >= baserev:
1347 parentscount[p - baserev] += 1 1360 parentscount[p - baserev] += 1
1348 return subset.filter(lambda r: parentscount[r - baserev] > 1) 1361 return subset.filter(lambda r: parentscount[r - baserev] > 1,
1362 condrepr='<branchpoint>')
1349 1363
1350 @predicate('min(set)', safe=True) 1364 @predicate('min(set)', safe=True)
1351 def minrev(repo, subset, x): 1365 def minrev(repo, subset, x):
1352 """Changeset with lowest revision number in set. 1366 """Changeset with lowest revision number in set.
1353 """ 1367 """
1600 s.sort() # set are non ordered, so we enforce ascending 1614 s.sort() # set are non ordered, so we enforce ascending
1601 return subset & s 1615 return subset & s
1602 else: 1616 else:
1603 phase = repo._phasecache.phase 1617 phase = repo._phasecache.phase
1604 condition = lambda r: phase(repo, r) == target 1618 condition = lambda r: phase(repo, r) == target
1605 return subset.filter(condition, cache=False) 1619 return subset.filter(condition, condrepr=('<phase %r>', target),
1620 cache=False)
1606 1621
1607 @predicate('draft()', safe=True) 1622 @predicate('draft()', safe=True)
1608 def draft(repo, subset, x): 1623 def draft(repo, subset, x):
1609 """Changeset in draft phase.""" 1624 """Changeset in draft phase."""
1610 # i18n: "draft" is a keyword 1625 # i18n: "draft" is a keyword
1673 return subset & s 1688 return subset & s
1674 else: 1689 else:
1675 phase = repo._phasecache.phase 1690 phase = repo._phasecache.phase
1676 target = phases.public 1691 target = phases.public
1677 condition = lambda r: phase(repo, r) != target 1692 condition = lambda r: phase(repo, r) != target
1678 return subset.filter(condition, cache=False) 1693 return subset.filter(condition, condrepr=('<phase %r>', target),
1694 cache=False)
1679 1695
1680 @predicate('public()', safe=True) 1696 @predicate('public()', safe=True)
1681 def public(repo, subset, x): 1697 def public(repo, subset, x):
1682 """Changeset in public phase.""" 1698 """Changeset in public phase."""
1683 # i18n: "public" is a keyword 1699 # i18n: "public" is a keyword
1684 getargs(x, 0, 0, _("public takes no arguments")) 1700 getargs(x, 0, 0, _("public takes no arguments"))
1685 phase = repo._phasecache.phase 1701 phase = repo._phasecache.phase
1686 target = phases.public 1702 target = phases.public
1687 condition = lambda r: phase(repo, r) == target 1703 condition = lambda r: phase(repo, r) == target
1688 return subset.filter(condition, cache=False) 1704 return subset.filter(condition, condrepr=('<phase %r>', target),
1705 cache=False)
1689 1706
1690 @predicate('remote([id [,path]])', safe=True) 1707 @predicate('remote([id [,path]])', safe=True)
1691 def remote(repo, subset, x): 1708 def remote(repo, subset, x):
1692 """Local revision that corresponds to the given identifier in a 1709 """Local revision that corresponds to the given identifier in a
1693 remote repository, if present. Here, the '.' identifier is a 1710 remote repository, if present. Here, the '.' identifier is a
1858 match = False 1875 match = False
1859 if match: 1876 if match:
1860 return True 1877 return True
1861 return False 1878 return False
1862 1879
1863 return subset.filter(matches) 1880 return subset.filter(matches, condrepr=('<matching%r %r>', fields, revs))
1864 1881
1865 @predicate('reverse(set)', safe=True) 1882 @predicate('reverse(set)', safe=True)
1866 def reverse(repo, subset, x): 1883 def reverse(repo, subset, x):
1867 """Reverse order of set. 1884 """Reverse order of set.
1868 """ 1885 """
1879 def filter(r): 1896 def filter(r):
1880 for p in parents(r): 1897 for p in parents(r):
1881 if 0 <= p and p in s: 1898 if 0 <= p and p in s:
1882 return False 1899 return False
1883 return True 1900 return True
1884 return subset & s.filter(filter) 1901 return subset & s.filter(filter, condrepr='<roots>')
1885 1902
1886 @predicate('sort(set[, [-]key...])', safe=True) 1903 @predicate('sort(set[, [-]key...])', safe=True)
1887 def sort(repo, subset, x): 1904 def sort(repo, subset, x):
1888 """Sort set by keys. The default sort order is ascending, specify a key 1905 """Sort set by keys. The default sort order is ascending, specify a key
1889 as ``-key`` to sort in descending order. 1906 as ``-key`` to sort in descending order.
1986 if s.removed: 2003 if s.removed:
1987 return any(submatches(c.p1().substate.keys())) 2004 return any(submatches(c.p1().substate.keys()))
1988 2005
1989 return False 2006 return False
1990 2007
1991 return subset.filter(matches) 2008 return subset.filter(matches, condrepr=('<subrepo %r>', pat))
1992 2009
1993 def _substringmatcher(pattern): 2010 def _substringmatcher(pattern):
1994 kind, pattern, matcher = util.stringmatcher(pattern) 2011 kind, pattern, matcher = util.stringmatcher(pattern)
1995 if kind == 'literal': 2012 if kind == 'literal':
1996 matcher = lambda s: pattern in s 2013 matcher = lambda s: pattern in s