changeset 40993:49d48489a16b

blackbox: resurrect recursion guard If I added ui.log() to hg.repository() function, test-merge-subrepos.t exploded. The problem is that the blackbox may create new repository instance while logging is active, and the created repository owns its new ui derived from the baseui, not from the ui which is processing the active logging. I tried to work around the issue in ui.log(), but that turned out to be not easy. We shouldn't globally lock the ui.log() since there may be more than one active repo/ui instances in threaded environment. We could store the logging state in thread-local storage, but that seems unnecessarily complex. So this patch reintroduces the _inlog flag to per-repository logger instances.
author Yuya Nishihara <yuya@tcha.org>
date Sat, 15 Dec 2018 19:05:42 +0900
parents 1de3364320af
children ab92e2111408
files hgext/blackbox.py
diffstat 1 files changed, 13 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/hgext/blackbox.py	Sat Dec 15 17:52:14 2018 +0900
+++ b/hgext/blackbox.py	Sat Dec 15 19:05:42 2018 +0900
@@ -96,11 +96,24 @@
         self._trackedevents = set(ui.configlist('blackbox', 'track'))
         self._maxfiles = ui.configint('blackbox', 'maxfiles')
         self._maxsize = ui.configbytes('blackbox', 'maxsize')
+        self._inlog = False
 
     def tracked(self, event):
         return b'*' in self._trackedevents or event in self._trackedevents
 
     def log(self, ui, event, msg, opts):
+        # self._log() -> ctx.dirty() may create new subrepo instance, which
+        # ui is derived from baseui. So the recursion guard in ui.log()
+        # doesn't work as it's local to the ui instance.
+        if self._inlog:
+            return
+        self._inlog = True
+        try:
+            self._log(ui, event, msg, opts)
+        finally:
+            self._inlog = False
+
+    def _log(self, ui, event, msg, opts):
         default = ui.configdate('devel', 'default-date')
         date = dateutil.datestr(default, ui.config('blackbox', 'date-format'))
         user = procutil.getuser()