comparison mercurial/revset.py @ 18473:692cbda1eb50 stable

revset: evaluate sub expressions correctly (issue3775) Before this patch, sub expression may return unexpected result, if it is joined with another expression by "or": - "^"/parentspec(): "R or R^1" is not equal to "R^1 or R". the former returns only "R". - "~"/ancestorspec(): "R or R~1" is not equal to "R~1 or R". the former returns only "R". - ":"/rangeset(): "10 or (10 or 15):" is not equal to "(10 or 15): or 10". the former returns only 10 and 15 or grater (11 to 14 are not included). In "or"-ed expression "A or B", the "subset" passed to evaluation of "B" doesn't contain revisions gotten from evaluation of "A", for efficiency. In the other hand, "stringset()" fails to look corresponding revision for specified string/symbol up, if "subset" doesn't contain that revision. So, predicates looking revisions up indirectly should evaluate sub expressions of themselves not with passed "subset" but with "entire revisions in the repository", to prevent "stringset()" from unexpected failing to look symbols in them up. But predicates in above example don't so. For example, in the case of "R or R^1": 1. "R^1" is evaluated with "subset" containing revisions other than "R", because "R" is already gotten by the former of "or"-ed expressions 2. "parentspec()" evaluates "R" of "R^1" with such "subset" 3. "stringset()" fails to look "R" up, because "R" is not contained in "subset" 4. so, evaluation of "R^1" returns no revision This patch evaluates sub expressions for predicates above with "entire revisions in the repository".
author FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
date Wed, 23 Jan 2013 22:52:55 +0900
parents 8b0f0dd56cec
children 8260fa9f30b9
comparison
equal deleted inserted replaced
18472:37100f30590f 18473:692cbda1eb50
221 if x in symbols: 221 if x in symbols:
222 raise error.ParseError(_("can't use %s here") % x) 222 raise error.ParseError(_("can't use %s here") % x)
223 return stringset(repo, subset, x) 223 return stringset(repo, subset, x)
224 224
225 def rangeset(repo, subset, x, y): 225 def rangeset(repo, subset, x, y):
226 m = getset(repo, subset, x) 226 cl = repo.changelog
227 if not m: 227 m = getset(repo, cl, x)
228 m = getset(repo, list(repo), x) 228 n = getset(repo, cl, y)
229
230 n = getset(repo, subset, y)
231 if not n:
232 n = getset(repo, list(repo), y)
233 229
234 if not m or not n: 230 if not m or not n:
235 return [] 231 return []
236 m, n = m[0], n[-1] 232 m, n = m[0], n[-1]
237 233
324 n = int(n[1]) 320 n = int(n[1])
325 except (TypeError, ValueError): 321 except (TypeError, ValueError):
326 raise error.ParseError(_("~ expects a number")) 322 raise error.ParseError(_("~ expects a number"))
327 ps = set() 323 ps = set()
328 cl = repo.changelog 324 cl = repo.changelog
329 for r in getset(repo, subset, x): 325 for r in getset(repo, cl, x):
330 for i in range(n): 326 for i in range(n):
331 r = cl.parentrevs(r)[0] 327 r = cl.parentrevs(r)[0]
332 ps.add(r) 328 ps.add(r)
333 return [r for r in subset if r in ps] 329 return [r for r in subset if r in ps]
334 330
1137 raise ValueError 1133 raise ValueError
1138 except (TypeError, ValueError): 1134 except (TypeError, ValueError):
1139 raise error.ParseError(_("^ expects a number 0, 1, or 2")) 1135 raise error.ParseError(_("^ expects a number 0, 1, or 2"))
1140 ps = set() 1136 ps = set()
1141 cl = repo.changelog 1137 cl = repo.changelog
1142 for r in getset(repo, subset, x): 1138 for r in getset(repo, cl, x):
1143 if n == 0: 1139 if n == 0:
1144 ps.add(r) 1140 ps.add(r)
1145 elif n == 1: 1141 elif n == 1:
1146 ps.add(cl.parentrevs(r)[0]) 1142 ps.add(cl.parentrevs(r)[0])
1147 elif n == 2: 1143 elif n == 2: