# HG changeset patch # User Yuya Nishihara # Date 1541927313 -32400 # Node ID 55b053af7196c2965592a485dfefe303c6fdb236 # Parent c93d046d43004b91ed9e4c3680956ae7e11963c6 ui: manage logger instances and event filtering by core ui The setup code in blackbox needs more tweaks since it has lots of black magics. I'll fix them by follow-up patches. To be clear, the goal of this series is to provide a proper way for command server to install its own logger. I need it to debug in-memory repository cache. diff -r c93d046d4300 -r 55b053af7196 hgext/blackbox.py --- a/hgext/blackbox.py Mon Nov 12 21:10:51 2018 +0900 +++ b/hgext/blackbox.py Sun Nov 11 18:08:33 2018 +0900 @@ -53,7 +53,6 @@ pycompat, registrar, ui as uimod, - util, ) from mercurial.utils import ( dateutil, @@ -147,9 +146,6 @@ def log(self, ui, event, msg, opts): global _lastlogger - if not self.tracked(event): - return - if self._bbvfs: _lastlogger = self elif _lastlogger and _lastlogger._bbvfs: @@ -201,33 +197,20 @@ def wrapui(ui): class blackboxui(ui.__class__): - def __init__(self, src=None): - super(blackboxui, self).__init__(src) - if src and r'_bblogger' in src.__dict__: - self._bblogger = src._bblogger - - # trick to initialize logger after configuration is loaded, which - # can be replaced later with blackboxlogger(ui) in uisetup(), where - # both user and repo configurations should be available. - @util.propertycache - def _bblogger(self): - return blackboxlogger(self) - def debug(self, *msg, **opts): super(blackboxui, self).debug(*msg, **opts) if self.debugflag: self.log('debug', '%s', ''.join(msg)) - def log(self, event, *msg, **opts): - super(blackboxui, self).log(event, *msg, **opts) - self._bblogger.log(self, event, msg, opts) - ui.__class__ = blackboxui uimod.ui = blackboxui def uisetup(ui): wrapui(ui) +def uipopulate(ui): + ui.setlogger(b'blackbox', blackboxlogger(ui)) + def reposetup(ui, repo): # During 'hg pull' a httppeer repo is created to represent the remote repo. # It doesn't have a .hg directory to put a blackbox in, so we don't do @@ -235,7 +218,10 @@ if not repo.local(): return - logger = getattr(ui, '_bblogger', None) + # Since blackbox.log is stored in the repo directory, the logger should be + # instantiated per repository. + logger = blackboxlogger(ui) + ui.setlogger(b'blackbox', logger) if logger: logger.setrepo(repo) diff -r c93d046d4300 -r 55b053af7196 hgext/logtoprocess.py --- a/hgext/logtoprocess.py Mon Nov 12 21:10:51 2018 +0900 +++ b/hgext/logtoprocess.py Sun Nov 11 18:08:33 2018 +0900 @@ -38,7 +38,6 @@ from mercurial import ( pycompat, - util, ) from mercurial.utils import ( procutil, @@ -63,9 +62,7 @@ return bool(self._scripts.get(event)) def log(self, ui, event, msg, opts): - script = self._scripts.get(event) - if not script: - return + script = self._scripts[event] env = { b'EVENT': event, b'HGPID': os.getpid(), @@ -77,24 +74,5 @@ fullenv = procutil.shellenviron(env) procutil.runbgcommand(script, fullenv, shell=True) -def uisetup(ui): - - class logtoprocessui(ui.__class__): - def __init__(self, src=None): - super(logtoprocessui, self).__init__(src) - if src and r'_ltplogger' in src.__dict__: - self._ltplogger = src._ltplogger - - # trick to initialize logger after configuration is loaded, which - # can be replaced later with processlogger(ui) in uisetup(), where - # both user and repo configurations should be available. - @util.propertycache - def _ltplogger(self): - return processlogger(self) - - def log(self, event, *msg, **opts): - self._ltplogger.log(self, event, msg, opts) - return super(logtoprocessui, self).log(event, *msg, **opts) - - # Replace the class for this instance and all clones created from it: - ui.__class__ = logtoprocessui +def uipopulate(ui): + ui.setlogger(b'logtoprocess', processlogger(ui)) diff -r c93d046d4300 -r 55b053af7196 mercurial/ui.py --- a/mercurial/ui.py Mon Nov 12 21:10:51 2018 +0900 +++ b/mercurial/ui.py Sun Nov 11 18:08:33 2018 +0900 @@ -235,6 +235,7 @@ self._fmsgout = src._fmsgout self._fmsgerr = src._fmsgerr self._finoutredirected = src._finoutredirected + self._loggers = src._loggers.copy() self.pageractive = src.pageractive self._disablepager = src._disablepager self._tweaked = src._tweaked @@ -263,6 +264,7 @@ self._fmsgout = self.fout # configurable self._fmsgerr = self.ferr # configurable self._finoutredirected = False + self._loggers = {} self.pageractive = False self._disablepager = False self._tweaked = False @@ -1709,6 +1711,18 @@ '''exists only so low-level modules won't need to import scmutil''' return scmutil.progress(self, topic, unit, total) + def getlogger(self, name): + """Returns a logger of the given name; or None if not registered""" + return self._loggers.get(name) + + def setlogger(self, name, logger): + """Install logger which can be identified later by the given name + + More than one loggers can be registered. Use extension or module + name to uniquely identify the logger instance. + """ + self._loggers[name] = logger + def log(self, event, *msg, **opts): '''hook for logging facility extensions @@ -1720,6 +1734,14 @@ **opts currently has no defined meanings. ''' + if not self._loggers: + return + activeloggers = [l for l in self._loggers.itervalues() + if l.tracked(event)] + if not activeloggers: + return + for logger in activeloggers: + logger.log(self, event, msg, opts) def label(self, msg, label): '''style msg based on supplied label