[PATCH] revset: fix crash if range set endpoint not in current subset
Matt Mackall
mpm at selenic.com
Mon Jun 28 11:09:52 CDT 2010
On Sun, 2010-06-27 at 22:36 -1000, Julian Cowley wrote:
> # HG changeset patch
> # User Julian Cowley <julian at lava.net>
> # Date 1277713087 36000
> # Branch stable
> # Node ID 8e13bae85245766e023097955e7a42f37894785f
> # Parent ed2bb0f9b27d165b3fc76605b5904c2b4da9a3b7
> revset: fix crash if range set endpoint not in current subset
>
> Currently, if either endpoint of a range set is not in the current
> subset of revisions, an index error is raised. For example, this
> crashes:
>
> hg log -r '1:2 and 0:2'
>
> This does not:
>
> hg log -r '0:2 and 1:2'
Also:
-r 'not 1 and 1:2'
> The fix is to generate the range set independently of the current
> subset, then return the intersection of the two. This potentially
> runs slowly and there are probably numerous ways this can be optimized,
> but for now this returns the right answer.
It's not sufficient. All you need to break it again is an empty set:
-r '(1 and 2):3'
And this also currently breaks:
-r '(1 and 2)::'
As that's "descendants of the empty set", it should give us an empty set
too, so:
-r '(1 and 2):' -> empty set
-r '(1 and 2):3' -> still empty?
I've queued up a different fix that looks like this, thanks:
# HG changeset patch
# User Matt Mackall <mpm at selenic.com>
# Date 1277741247 18000
# Branch stable
# Node ID 88abbb046e66d6b1c4e5458ffd74dc804af14e60
# Parent 3827728b54e20febd05a862663191293a431dc90
revset: deal with empty sets in range endpoints
(spotted by Julian Cowley <julian at lava.net>)
diff -r 3827728b54e2 -r 88abbb046e66 mercurial/revset.py
--- a/mercurial/revset.py Sun Jun 27 18:20:49 2010 -0500
+++ b/mercurial/revset.py Mon Jun 28 11:07:27 2010 -0500
@@ -129,11 +129,24 @@
return stringset(repo, subset, x)
def rangeset(repo, subset, x, y):
- m = getset(repo, subset, x)[0]
- n = getset(repo, subset, y)[-1]
+ m = getset(repo, subset, x)
+ if not m:
+ m = getset(repo, range(len(repo)), x)
+
+ n = getset(repo, subset, y)
+ if not n:
+ n = getset(repo, range(len(repo)), y)
+
+ if not m or not n:
+ return []
+ m, n = m[0], n[-1]
+
if m < n:
- return range(m, n + 1)
- return range(m, n - 1, -1)
+ r = range(m, n + 1)
+ else:
+ r = range(m, n - 1, -1)
+ s = set(subset)
+ return [x for x in r if x in s]
def andset(repo, subset, x, y):
return getset(repo, getset(repo, subset, x), y)
@@ -222,11 +235,15 @@
def ancestors(repo, subset, x):
args = getset(repo, range(len(repo)), x)
+ if not args:
+ return []
s = set(repo.changelog.ancestors(*args)) | set(args)
return [r for r in subset if r in s]
def descendants(repo, subset, x):
args = getset(repo, range(len(repo)), x)
+ if not args:
+ return []
s = set(repo.changelog.descendants(*args)) | set(args)
return [r for r in subset if r in s]
diff -r 3827728b54e2 -r 88abbb046e66 tests/test-revset
--- a/tests/test-revset Sun Jun 27 18:20:49 2010 -0500
+++ b/tests/test-revset Mon Jun 28 11:07:27 2010 -0500
@@ -126,3 +126,10 @@
log '4:8'
log 'sort(!merge() & (modifies(b) | user(bob) | keyword(bug) | keyword(issue) & 1::9), "-date")'
+
+log 'not 0 and 0:2'
+log 'not 1 and 0:2'
+log 'not 2 and 0:2'
+log '(1 and 2)::'
+log '(1 and 2):'
+log '(1 and 2):3'
diff -r 3827728b54e2 -r 88abbb046e66 tests/test-revset.out
--- a/tests/test-revset.out Sun Jun 27 18:20:49 2010 -0500
+++ b/tests/test-revset.out Mon Jun 28 11:07:27 2010 -0500
@@ -198,3 +198,15 @@
4
2
5
+% log 'not 0 and 0:2'
+1
+2
+% log 'not 1 and 0:2'
+0
+2
+% log 'not 2 and 0:2'
+0
+1
+% log '(1 and 2)::'
+% log '(1 and 2):'
+% log '(1 and 2):3'
--
Mathematics is the supreme nostalgia of our time.
More information about the Mercurial-devel
mailing list