comparison mercurial/scmutil.py @ 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 99ab7bc944d2
children 9700cb9df140
comparison
equal deleted inserted replaced
35034:02845f7441af 35035:96dcc78468e3
1231 1231
1232 categories = [] 1232 categories = []
1233 1233
1234 def reportsummary(func): 1234 def reportsummary(func):
1235 """decorator for report callbacks.""" 1235 """decorator for report callbacks."""
1236 reporef = weakref.ref(repo) 1236 # The repoview life cycle is shorter than the one of the actual
1237 # underlying repository. So the filtered object can die before the
1238 # weakref is used leading to troubles. We keep a reference to the
1239 # unfiltered object and restore the filtering when retrieving the
1240 # repository through the weakref.
1241 filtername = repo.filtername
1242 reporef = weakref.ref(repo.unfiltered())
1237 def wrapped(tr): 1243 def wrapped(tr):
1238 repo = reporef() 1244 repo = reporef()
1245 if filtername:
1246 repo = repo.filtered(filtername)
1239 func(repo, tr) 1247 func(repo, tr)
1240 newcat = '%2i-txnreport' % len(categories) 1248 newcat = '%2i-txnreport' % len(categories)
1241 otr.addpostclose(newcat, wrapped) 1249 otr.addpostclose(newcat, wrapped)
1242 categories.append(newcat) 1250 categories.append(newcat)
1243 return wrapped 1251 return wrapped