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) |