changeset 30227:5ee944b9c750 stable

revset: don't cache abstractsmartset min/max invocations infinitely There was a "leak", apparently introduced in ab66c1dee405. When running: hg = hglib.open('repo') while True: hg.log("max(branch('default'))") all filteredset instances from branch() would be cached indefinitely by the @util.cachefunc annotation on the max() implementation. util.cachefunc seems dangerous as method decorator and is barely used elsewhere in the code base. Instead, just open code caching by having the min/max methods replace themselves with a plain lambda returning the result.
author Mads Kiilerich <madski@unity3d.com>
date Tue, 25 Oct 2016 18:56:27 +0200
parents 264f00b3e5f0
children b9f7b0c10027
files mercurial/revset.py
diffstat 1 files changed, 19 insertions(+), 13 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/revset.py	Mon Oct 24 09:14:34 2016 -0500
+++ b/mercurial/revset.py	Tue Oct 25 18:56:27 2016 +0200
@@ -2924,23 +2924,29 @@
         """True if the set will iterate in topographical order"""
         raise NotImplementedError()
 
-    @util.cachefunc
     def min(self):
         """return the minimum element in the set"""
-        if self.fastasc is not None:
-            for r in self.fastasc():
-                return r
-            raise ValueError('arg is an empty sequence')
-        return min(self)
-
-    @util.cachefunc
+        if self.fastasc is None:
+            v = min(self)
+        else:
+            for v in self.fastasc():
+                break
+            else:
+                raise ValueError('arg is an empty sequence')
+        self.min = lambda: v
+        return v
+
     def max(self):
         """return the maximum element in the set"""
-        if self.fastdesc is not None:
-            for r in self.fastdesc():
-                return r
-            raise ValueError('arg is an empty sequence')
-        return max(self)
+        if self.fastdesc is None:
+            return max(self)
+        else:
+            for v in self.fastdesc():
+                break
+            else:
+                raise ValueError('arg is an empty sequence')
+        self.max = lambda: v
+        return v
 
     def first(self):
         """return the first element in the set (user iteration perspective)