diff --git a/mercurial/chgserver.py b/mercurial/chgserver.py --- a/mercurial/chgserver.py +++ b/mercurial/chgserver.py @@ -219,7 +219,7 @@ def _newchgui(srcui, csystem, attachio): return chgui(srcui) -def _loadnewui(srcui, args): +def _loadnewui(srcui, args, cdebug): from . import dispatch # avoid cycle newui = srcui.__class__.load() @@ -247,8 +247,10 @@ def _loadnewui(srcui, args): path, newlui = dispatch._getlocal(newui, rpath, wd=cwd) extensions.populateui(newui) + commandserver.setuplogging(newui, fp=cdebug) if newui is not newlui: extensions.populateui(newlui) + commandserver.setuplogging(newlui, fp=cdebug) return (newui, newlui) @@ -423,7 +425,7 @@ class chgcmdserver(commandserver.server) args = self._readlist() try: - self.ui, lui = _loadnewui(self.ui, args) + self.ui, lui = _loadnewui(self.ui, args, self.cdebug) except error.ParseError as inst: dispatch._formatparse(self.ui.warn, inst) self.ui.flush() diff --git a/mercurial/commandserver.py b/mercurial/commandserver.py --- a/mercurial/commandserver.py +++ b/mercurial/commandserver.py @@ -26,8 +26,10 @@ from .i18n import _ from . import ( encoding, error, + loggingutil, pycompat, util, + vfs as vfsmod, ) from .utils import ( cborutil, @@ -223,11 +225,18 @@ class server(object): self.ui = ui self.repo = self.repoui = None + self.cdebug = logfile self.cerr = channeledoutput(fout, 'e') self.cout = channeledoutput(fout, 'o') self.cin = channeledinput(fin, fout, 'I') self.cresult = channeledoutput(fout, 'r') + if self.ui.config(b'cmdserver', b'log') == b'-': + # switch log stream of server's ui to the 'd' (debug) channel + # (don't touch repo.ui as its lifetime is longer than the server) + self.ui = self.ui.copy() + setuplogging(self.ui, repo=None, fp=self.cdebug) + # TODO: add this to help/config.txt when stabilized # ``channel`` # Use separate channel for structured output. (Command-server only) @@ -356,17 +365,18 @@ class server(object): return 0 -def setuplogging(ui): +def setuplogging(ui, repo=None, fp=None): """Set up server logging facility - If cmdserver.log is '-', log messages will be sent to the 'd' channel - while a client is connected. Otherwise, messages will be written to - the stderr of the server process. + If cmdserver.log is '-', log messages will be sent to the given fp. + It should be the 'd' channel while a client is connected, and otherwise + is the stderr of the server process. """ # developer config: cmdserver.log logpath = ui.config(b'cmdserver', b'log') if not logpath: return + tracked = {b'cmdserver'} global logfile if logpath == b'-': @@ -374,6 +384,22 @@ def setuplogging(ui): else: logfile = open(logpath, 'ab') + if logpath == b'-' and fp: + logger = loggingutil.fileobjectlogger(fp, tracked) + elif logpath == b'-': + logger = loggingutil.fileobjectlogger(ui.ferr, tracked) + else: + logpath = os.path.abspath(logpath) + vfs = vfsmod.vfs(os.path.dirname(logpath)) + logger = loggingutil.filelogger(vfs, os.path.basename(logpath), tracked) + + targetuis = {ui} + if repo: + targetuis.add(repo.baseui) + targetuis.add(repo.ui) + for u in targetuis: + u.setlogger(b'cmdserver', logger) + class pipeservice(object): def __init__(self, ui, repo, opts): self.ui = ui diff --git a/mercurial/server.py b/mercurial/server.py --- a/mercurial/server.py +++ b/mercurial/server.py @@ -158,7 +158,7 @@ def _createcmdservice(ui, repo, opts): servicefn = _cmdservicemap[mode] except KeyError: raise error.Abort(_('unknown mode %s') % mode) - commandserver.setuplogging(ui) + commandserver.setuplogging(ui, repo) return servicefn(ui, repo, opts) def _createhgwebservice(ui, repo, opts):