changeset 35035:96dcc78468e3 stable

tr-summary: keep a weakref to the unfiltered repository Repoview can have a different life cycle, causing issue in some corner cases. The particular instance that revealed this comes from localpeer. The localpeer hold a reference to the unfiltered repository, but calling 'local()' will create an on-demand 'visible' repoview. That repoview can be garbaged collected any time. Here is a simplified step by step reproduction:: 1) tr = peer.local().transaction('foo') 2) tr.close() After (1), the repoview object is garbage collected, so weakref used in (2) point to nothing. Thanks to Sean Farley for helping raising and debugging this issue.
author Boris Feld <boris.feld@octobus.net>
date Fri, 24 Nov 2017 21:51:41 -0500
parents 02845f7441af
children 281214150561
files mercurial/scmutil.py
diffstat 1 files changed, 9 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/scmutil.py	Sat Nov 11 12:40:13 2017 +0900
+++ b/mercurial/scmutil.py	Fri Nov 24 21:51:41 2017 -0500
@@ -1233,9 +1233,17 @@
 
     def reportsummary(func):
         """decorator for report callbacks."""
-        reporef = weakref.ref(repo)
+        # The repoview life cycle is shorter than the one of the actual
+        # underlying repository. So the filtered object can die before the
+        # weakref is used leading to troubles. We keep a reference to the
+        # unfiltered object and restore the filtering when retrieving the
+        # repository through the weakref.
+        filtername = repo.filtername
+        reporef = weakref.ref(repo.unfiltered())
         def wrapped(tr):
             repo = reporef()
+            if filtername:
+                repo = repo.filtered(filtername)
             func(repo, tr)
         newcat = '%2i-txnreport' % len(categories)
         otr.addpostclose(newcat, wrapped)