##// END OF EJS Templates
extensions: add "uipopulate" hook, called per instance, not per process...
extensions: add "uipopulate" hook, called per instance, not per process In short, this is the "reposetup" function for ui. It allows us to modify ui attributes without extending ui.__class__. Before, the only way to do that was to abuse the config dictionary, which is copied across ui instances. See the next patch for usage example.

File last commit:

r40713:2b859742 default
r40760:c93d046d default
Show More
logtoprocess.py
100 lines | 3.4 KiB | text/x-python | PythonLexer
Martijn Pieters
logtoprocess: new experimental extension...
r28901 # logtoprocess.py - send ui.log() data to a subprocess
#
# Copyright 2016 Facebook, Inc.
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.
Jun Wu
logtoprocess: use lowercase for docstring title
r31601 """send ui.log() data to a subprocess (EXPERIMENTAL)
Martijn Pieters
logtoprocess: new experimental extension...
r28901
This extension lets you specify a shell command per ui.log() event,
sending all remaining arguments to as environment variables to that command.
Yuya Nishihara
logtoprocess: drop support for ui.log() call with invalid msg arguments (BC)...
r40656 Positional arguments construct a log message, which is passed in the `MSG1`
environment variables. Each keyword argument is set as a `OPT_UPPERCASE_KEY`
variable (so the key is uppercased, and prefixed with `OPT_`). The original
event name is passed in the `EVENT` environment variable, and the process ID
of mercurial is given in `HGPID`.
Martijn Pieters
logtoprocess: new experimental extension...
r28901
Yuya Nishihara
logtoprocess: drop support for ui.log() call with invalid msg arguments (BC)...
r40656 So given a call `ui.log('foo', 'bar %s\n', 'baz', spam='eggs'), a script
configured for the `foo` event can expect an environment with `MSG1=bar baz`,
and `OPT_SPAM=eggs`.
Martijn Pieters
logtoprocess: new experimental extension...
r28901
Scripts are configured in the `[logtoprocess]` section, each key an event name.
For example::
[logtoprocess]
Yuya Nishihara
logtoprocess: drop support for ui.log() call with invalid msg arguments (BC)...
r40656 commandexception = echo "$MSG1" > /var/log/mercurial_exceptions.log
Martijn Pieters
logtoprocess: new experimental extension...
r28901
would log the warning message and traceback of any failed command dispatch.
Mads Kiilerich
spelling: fixes of non-dictionary words
r30332 Scripts are run asynchronously as detached daemon processes; mercurial will
Martijn Pieters
logtoprocess: new experimental extension...
r28901 not ensure that they exit cleanly.
"""
from __future__ import absolute_import
import os
Pulkit Goyal
py3: replace os.environ with encoding.environ (part 5 of 5)
r30638
Yuya Nishihara
logtoprocess: rewrite dict building in py3-compatible way
r40654 from mercurial import (
pycompat,
Yuya Nishihara
logtoprocess: extract logger class from ui wrapper...
r40713 util,
Yuya Nishihara
logtoprocess: rewrite dict building in py3-compatible way
r40654 )
Matt Harbison
py3: convert arguments, cwd and env to native strings when spawning subprocess...
r39851 from mercurial.utils import (
procutil,
)
Augie Fackler
extensions: change magic "shipped with hg" string...
r29841 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
Martijn Pieters
logtoprocess: new experimental extension...
r28901 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
# be specifying the version(s) of Mercurial they are tested with, or
# leave the attribute unspecified.
Augie Fackler
extensions: change magic "shipped with hg" string...
r29841 testedwith = 'ships-with-hg-core'
Martijn Pieters
logtoprocess: new experimental extension...
r28901
Yuya Nishihara
logtoprocess: extract logger class from ui wrapper...
r40713 class processlogger(object):
"""Map log events to external commands
Arguments are passed on as environment variables.
"""
def __init__(self, ui):
self._scripts = dict(ui.configitems(b'logtoprocess'))
def tracked(self, event):
return bool(self._scripts.get(event))
def log(self, ui, event, msg, opts):
script = self._scripts.get(event)
if not script:
return
env = {
b'EVENT': event,
b'HGPID': os.getpid(),
b'MSG1': msg[0] % msg[1:],
}
# keyword arguments get prefixed with OPT_ and uppercased
env.update((b'OPT_%s' % key.upper(), value)
for key, value in pycompat.byteskwargs(opts).items())
fullenv = procutil.shellenviron(env)
procutil.runbgcommand(script, fullenv, shell=True)
Martijn Pieters
logtoprocess: new experimental extension...
r28901 def uisetup(ui):
class logtoprocessui(ui.__class__):
Yuya Nishihara
logtoprocess: extract logger class from ui wrapper...
r40713 def __init__(self, src=None):
super(logtoprocessui, self).__init__(src)
if src and r'_ltplogger' in src.__dict__:
self._ltplogger = src._ltplogger
Martijn Pieters
logtoprocess: new experimental extension...
r28901
Yuya Nishihara
logtoprocess: extract logger class from ui wrapper...
r40713 # 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)
Martijn Pieters
logtoprocess: new experimental extension...
r28901 return super(logtoprocessui, self).log(event, *msg, **opts)
# Replace the class for this instance and all clones created from it:
ui.__class__ = logtoprocessui