Mercurial > public > mercurial-scm > hg
comparison mercurial/revset.py @ 15898:6902e13ddd03
revset: optimize building large lists in formatrevspec
The large or-expressions we used to build required a substantial
amount of subset filtering in orset() which was inefficient. Instead we build a
single string which we process in one go with a special internal predicate.
author | Matt Mackall <mpm@selenic.com> |
---|---|
date | Mon, 16 Jan 2012 01:21:22 -0600 |
parents | cd956049fc14 |
children | 476a981fdf34 |
comparison
equal
deleted
inserted
replaced
15897:cc021114fc98 | 15898:6902e13ddd03 |
---|---|
861 """``user(string)`` | 861 """``user(string)`` |
862 User name contains string. The match is case-insensitive. | 862 User name contains string. The match is case-insensitive. |
863 """ | 863 """ |
864 return author(repo, subset, x) | 864 return author(repo, subset, x) |
865 | 865 |
866 # for internal use | |
867 def _list(repo, subset, x): | |
868 s = getstring(x, "internal error") | |
869 if not s: | |
870 return [] | |
871 if not isinstance(subset, set): | |
872 subset = set(subset) | |
873 ls = [repo[r].rev() for r in s.split('\0')] | |
874 return [r for r in ls if r in subset] | |
875 | |
866 symbols = { | 876 symbols = { |
867 "adds": adds, | 877 "adds": adds, |
868 "all": getall, | 878 "all": getall, |
869 "ancestor": ancestor, | 879 "ancestor": ancestor, |
870 "ancestors": ancestors, | 880 "ancestors": ancestors, |
908 "sort": sort, | 918 "sort": sort, |
909 "secret": secret, | 919 "secret": secret, |
910 "tag": tag, | 920 "tag": tag, |
911 "tagged": tagged, | 921 "tagged": tagged, |
912 "user": user, | 922 "user": user, |
923 "_list": _list, | |
913 } | 924 } |
914 | 925 |
915 methods = { | 926 methods = { |
916 "range": rangeset, | 927 "range": rangeset, |
917 "string": stringset, | 928 "string": stringset, |
1093 >>> formatspec('%r:: and %lr', '10 or 11', ("this()", "that()")) | 1104 >>> formatspec('%r:: and %lr', '10 or 11', ("this()", "that()")) |
1094 '(10 or 11):: and ((this()) or (that()))' | 1105 '(10 or 11):: and ((this()) or (that()))' |
1095 >>> formatspec('%d:: and not %d::', 10, 20) | 1106 >>> formatspec('%d:: and not %d::', 10, 20) |
1096 '10:: and not 20::' | 1107 '10:: and not 20::' |
1097 >>> formatspec('%ld or %ld', [], [1]) | 1108 >>> formatspec('%ld or %ld', [], [1]) |
1098 '(0-0) or 1' | 1109 "_list('') or 1" |
1099 >>> formatspec('keyword(%s)', 'foo\\xe9') | 1110 >>> formatspec('keyword(%s)', 'foo\\xe9') |
1100 "keyword('foo\\\\xe9')" | 1111 "keyword('foo\\\\xe9')" |
1101 >>> b = lambda: 'default' | 1112 >>> b = lambda: 'default' |
1102 >>> b.branch = b | 1113 >>> b.branch = b |
1103 >>> formatspec('branch(%b)', b) | 1114 >>> formatspec('branch(%b)', b) |
1104 "branch('default')" | 1115 "branch('default')" |
1105 >>> formatspec('root(%ls)', ['a', 'b', 'c', 'd']) | 1116 >>> formatspec('root(%ls)', ['a', 'b', 'c', 'd']) |
1106 "root((('a' or 'b') or ('c' or 'd')))" | 1117 "root(_list('a\\x00b\\x00c\\x00d'))" |
1107 ''' | 1118 ''' |
1108 | 1119 |
1109 def quote(s): | 1120 def quote(s): |
1110 return repr(str(s)) | 1121 return repr(str(s)) |
1111 | 1122 |
1121 return quote(nodemod.hex(arg)) | 1132 return quote(nodemod.hex(arg)) |
1122 elif c == 'b': | 1133 elif c == 'b': |
1123 return quote(arg.branch()) | 1134 return quote(arg.branch()) |
1124 | 1135 |
1125 def listexp(s, t): | 1136 def listexp(s, t): |
1126 "balance a list s of type t to limit parse tree depth" | |
1127 l = len(s) | 1137 l = len(s) |
1128 if l == 0: | 1138 if l == 0: |
1129 return '(0-0)' # a minimal way to represent an empty set | 1139 return "_list('')" |
1130 if l == 1: | 1140 elif l == 1: |
1131 return argtype(t, s[0]) | 1141 return argtype(t, s[0]) |
1142 elif t == 'd': | |
1143 return "_list('%s')" % "\0".join(str(int(a)) for a in s) | |
1144 elif t == 's': | |
1145 return "_list('%s')" % "\0".join(s) | |
1146 elif t == 'n': | |
1147 return "_list('%s')" % "\0".join(nodemod.hex(a) for a in s) | |
1148 elif t == 'b': | |
1149 return "_list('%s')" % "\0".join(a.branch() for a in s) | |
1150 | |
1132 m = l // 2 | 1151 m = l // 2 |
1133 return '(%s or %s)' % (listexp(s[:m], t), listexp(s[m:], t)) | 1152 return '(%s or %s)' % (listexp(s[:m], t), listexp(s[m:], t)) |
1134 | 1153 |
1135 ret = '' | 1154 ret = '' |
1136 pos = 0 | 1155 pos = 0 |