Mercurial > public > mercurial-scm > hg-stable
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: |