hgext/logtoprocess.py
changeset 40666 d2c997b8001f
parent 40664 b2e5a554bc7b
child 40716 2b859742ea15
equal deleted inserted replaced
40665:175b590b1f51 40666:d2c997b8001f
     7 """send ui.log() data to a subprocess (EXPERIMENTAL)
     7 """send ui.log() data to a subprocess (EXPERIMENTAL)
     8 
     8 
     9 This extension lets you specify a shell command per ui.log() event,
     9 This extension lets you specify a shell command per ui.log() event,
    10 sending all remaining arguments to as environment variables to that command.
    10 sending all remaining arguments to as environment variables to that command.
    11 
    11 
    12 Each positional argument to the method results in a `MSG[N]` key in the
    12 Positional arguments construct a log message, which is passed in the `MSG1`
    13 environment, starting at 1 (so `MSG1`, `MSG2`, etc.). Each keyword argument
    13 environment variables. Each keyword argument is set as a `OPT_UPPERCASE_KEY`
    14 is set as a `OPT_UPPERCASE_KEY` variable (so the key is uppercased, and
    14 variable (so the key is uppercased, and prefixed with `OPT_`). The original
    15 prefixed with `OPT_`). The original event name is passed in the `EVENT`
    15 event name is passed in the `EVENT` environment variable, and the process ID
    16 environment variable, and the process ID of mercurial is given in `HGPID`.
    16 of mercurial is given in `HGPID`.
    17 
    17 
    18 So given a call `ui.log('foo', 'bar', 'baz', spam='eggs'), a script configured
    18 So given a call `ui.log('foo', 'bar %s\n', 'baz', spam='eggs'), a script
    19 for the `foo` event can expect an environment with `MSG1=bar`, `MSG2=baz`, and
    19 configured for the `foo` event can expect an environment with `MSG1=bar baz`,
    20 `OPT_SPAM=eggs`.
    20 and `OPT_SPAM=eggs`.
    21 
    21 
    22 Scripts are configured in the `[logtoprocess]` section, each key an event name.
    22 Scripts are configured in the `[logtoprocess]` section, each key an event name.
    23 For example::
    23 For example::
    24 
    24 
    25   [logtoprocess]
    25   [logtoprocess]
    26   commandexception = echo "$MSG2$MSG3" > /var/log/mercurial_exceptions.log
    26   commandexception = echo "$MSG1" > /var/log/mercurial_exceptions.log
    27 
    27 
    28 would log the warning message and traceback of any failed command dispatch.
    28 would log the warning message and traceback of any failed command dispatch.
    29 
    29 
    30 Scripts are run asynchronously as detached daemon processes; mercurial will
    30 Scripts are run asynchronously as detached daemon processes; mercurial will
    31 not ensure that they exit cleanly.
    31 not ensure that they exit cleanly.
    58             Arguments are passed on as environment variables.
    58             Arguments are passed on as environment variables.
    59 
    59 
    60             """
    60             """
    61             script = self.config('logtoprocess', event)
    61             script = self.config('logtoprocess', event)
    62             if script:
    62             if script:
    63                 if msg:
       
    64                     # try to format the log message given the remaining
       
    65                     # arguments
       
    66                     try:
       
    67                         # Format the message as blackbox does
       
    68                         formatted = msg[0] % msg[1:]
       
    69                     except (TypeError, KeyError):
       
    70                         # Failed to apply the arguments, ignore
       
    71                         formatted = msg[0]
       
    72                     messages = (formatted,) + msg[1:]
       
    73                 else:
       
    74                     messages = msg
       
    75                 env = {
    63                 env = {
    76                     b'EVENT': event,
    64                     b'EVENT': event,
    77                     b'HGPID': os.getpid(),
    65                     b'HGPID': os.getpid(),
       
    66                     b'MSG1': msg[0] % msg[1:],
    78                 }
    67                 }
    79                 # positional arguments are listed as MSG[N] keys in the
       
    80                 # environment
       
    81                 env.update((b'MSG%d' % i, m) for i, m in enumerate(messages, 1))
       
    82                 # keyword arguments get prefixed with OPT_ and uppercased
    68                 # keyword arguments get prefixed with OPT_ and uppercased
    83                 env.update((b'OPT_%s' % key.upper(), value)
    69                 env.update((b'OPT_%s' % key.upper(), value)
    84                            for key, value in pycompat.byteskwargs(opts).items())
    70                            for key, value in pycompat.byteskwargs(opts).items())
    85                 fullenv = procutil.shellenviron(env)
    71                 fullenv = procutil.shellenviron(env)
    86                 procutil.runbgcommand(script, fullenv, shell=True)
    72                 procutil.runbgcommand(script, fullenv, shell=True)