Mercurial > hg
annotate mercurial/hook.py @ 31956:c13ff31818b0
ui: add special-purpose atexit functionality
In spite of its longstanding use, Python's built-in atexit code is
not suitable for Mercurial's purposes, for several reasons:
* Handlers run after application code has finished.
* Because of this, the code that runs handlers swallows exceptions
(since there's no possible stacktrace to associate errors with).
If we're lucky, we'll get something spat out to stderr (if stderr
still works), which of course isn't any use in a big deployment
where it's important that exceptions get logged and aggregated.
* Mercurial's current atexit handlers make unfortunate assumptions
about process state (specifically stdio) that, coupled with the
above problems, make it impossible to deal with certain categories
of error (try "hg status > /dev/full" on a Linux box).
* In Python 3, the atexit implementation is completely hidden, so
we can't hijack the platform's atexit code to run handlers at a
time of our choosing.
As a result, here's a perfectly cromulent atexit-like implementation
over which we have control. This lets us decide exactly when the
handlers run (after each request has completed), and control what
the process state is when that occurs (and afterwards).
author | Bryan O'Sullivan <bryano@fb.com> |
---|---|
date | Tue, 11 Apr 2017 14:54:12 -0700 |
parents | aff7b32b3c05 |
children | 4b426ae96ff2 |
rev | line source |
---|---|
4622
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1 # hook.py - hook support for mercurial |
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
2 # |
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
3 # Copyright 2007 Matt Mackall <mpm@selenic.com> |
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
4 # |
8225
46293a0c7e9f
updated license to be explicit about GPL version 2
Martin Geisler <mg@lazybytes.net>
parents:
8209
diff
changeset
|
5 # This software may be used and distributed according to the terms of the |
10263 | 6 # GNU General Public License version 2 or any later version. |
4622
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
7 |
25953
d15b279ddade
hook: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
8 from __future__ import absolute_import |
d15b279ddade
hook: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
9 |
d15b279ddade
hook: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
10 import os |
d15b279ddade
hook: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
11 import sys |
d15b279ddade
hook: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
12 |
d15b279ddade
hook: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
13 from .i18n import _ |
d15b279ddade
hook: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
14 from . import ( |
d15b279ddade
hook: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
15 demandimport, |
d15b279ddade
hook: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
16 error, |
d15b279ddade
hook: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
17 extensions, |
30519
20a42325fdef
py3: use pycompat.getcwd() instead of os.getcwd()
Pulkit Goyal <7895pulkit@gmail.com>
parents:
30473
diff
changeset
|
18 pycompat, |
25953
d15b279ddade
hook: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
19 util, |
d15b279ddade
hook: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
20 ) |
4622
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
21 |
31742
f243b7fbeba5
hook: use "htype" as variable name in _pythonhook
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
31205
diff
changeset
|
22 def _pythonhook(ui, repo, htype, hname, funcname, args, throw): |
4622
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
23 '''call python hook. hook is callable object, looked up as |
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
24 name in python module. if callable returns "true", hook |
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
25 fails, else passes. if hook raises exception, treated as |
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
26 hook failure. exception propagates if throw is "true". |
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
27 |
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
28 reason for "true" meaning "hook failed" is so that |
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
29 unmodified commands (e.g. mercurial.commands.update) can |
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
30 be run as hooks without wrappers to convert return values.''' |
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
31 |
21797
b009dd135aa0
hook: restore use of callable() since it was readded in Python 3.2
Augie Fackler <raf@durin42.com>
parents:
20548
diff
changeset
|
32 if callable(funcname): |
20548
5bd6a9fec103
hooks: for python hooks, consistently use __name__ etc as name, not the repr
Mads Kiilerich <madski@unity3d.com>
parents:
20547
diff
changeset
|
33 obj = funcname |
5bd6a9fec103
hooks: for python hooks, consistently use __name__ etc as name, not the repr
Mads Kiilerich <madski@unity3d.com>
parents:
20547
diff
changeset
|
34 funcname = obj.__module__ + "." + obj.__name__ |
5bd6a9fec103
hooks: for python hooks, consistently use __name__ etc as name, not the repr
Mads Kiilerich <madski@unity3d.com>
parents:
20547
diff
changeset
|
35 else: |
4622
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
36 d = funcname.rfind('.') |
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
37 if d == -1: |
26692
8d1cfd77b64f
hook: raise a separate exception for when loading a hook fails
Siddharth Agarwal <sid0@fb.com>
parents:
26587
diff
changeset
|
38 raise error.HookLoadError( |
28106
cedbe8723d99
hook: even fewer parentheses for load errors
Siddharth Agarwal <sid0@fb.com>
parents:
28080
diff
changeset
|
39 _('%s hook is invalid: "%s" not in a module') |
26692
8d1cfd77b64f
hook: raise a separate exception for when loading a hook fails
Siddharth Agarwal <sid0@fb.com>
parents:
26587
diff
changeset
|
40 % (hname, funcname)) |
4622
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
41 modname = funcname[:d] |
10103
37679dbf2ee3
hook: fix bug (reuse of variable) introduced in 872d49dd577a
Sune Foldager <cryo@cyanite.org>
parents:
9851
diff
changeset
|
42 oldpaths = sys.path |
14941
4a28cb4df1f8
windows: check util.mainfrozen() instead of ad-hoc checks everywhere
Augie Fackler <durin42@gmail.com>
parents:
14916
diff
changeset
|
43 if util.mainfrozen(): |
9332
872d49dd577a
hook: fix full path imports on Windows (issue1779)
Steve Borho <steve@borho.org>
parents:
8366
diff
changeset
|
44 # binary installs require sys.path manipulation |
10103
37679dbf2ee3
hook: fix bug (reuse of variable) introduced in 872d49dd577a
Sune Foldager <cryo@cyanite.org>
parents:
9851
diff
changeset
|
45 modpath, modfile = os.path.split(modname) |
37679dbf2ee3
hook: fix bug (reuse of variable) introduced in 872d49dd577a
Sune Foldager <cryo@cyanite.org>
parents:
9851
diff
changeset
|
46 if modpath and modfile: |
37679dbf2ee3
hook: fix bug (reuse of variable) introduced in 872d49dd577a
Sune Foldager <cryo@cyanite.org>
parents:
9851
diff
changeset
|
47 sys.path = sys.path[:] + [modpath] |
37679dbf2ee3
hook: fix bug (reuse of variable) introduced in 872d49dd577a
Sune Foldager <cryo@cyanite.org>
parents:
9851
diff
changeset
|
48 modname = modfile |
25328
2cfb0bbf83a1
hooks: replace if-try-finally with a "with" statement
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
25184
diff
changeset
|
49 with demandimport.deactivated(): |
4622
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
50 try: |
25328
2cfb0bbf83a1
hooks: replace if-try-finally with a "with" statement
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
25184
diff
changeset
|
51 obj = __import__(modname) |
28109
b892e424f88c
hook: don't crash on syntax errors in python hooks
Siddharth Agarwal <sid0@fb.com>
parents:
28108
diff
changeset
|
52 except (ImportError, SyntaxError): |
28078
2058e1a894f2
hook: use sys.exc_info rather than the deprecated equivalents
Siddharth Agarwal <sid0@fb.com>
parents:
27228
diff
changeset
|
53 e1 = sys.exc_info() |
25328
2cfb0bbf83a1
hooks: replace if-try-finally with a "with" statement
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
25184
diff
changeset
|
54 try: |
2cfb0bbf83a1
hooks: replace if-try-finally with a "with" statement
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
25184
diff
changeset
|
55 # extensions are loaded with hgext_ prefix |
2cfb0bbf83a1
hooks: replace if-try-finally with a "with" statement
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
25184
diff
changeset
|
56 obj = __import__("hgext_%s" % modname) |
28109
b892e424f88c
hook: don't crash on syntax errors in python hooks
Siddharth Agarwal <sid0@fb.com>
parents:
28108
diff
changeset
|
57 except (ImportError, SyntaxError): |
28078
2058e1a894f2
hook: use sys.exc_info rather than the deprecated equivalents
Siddharth Agarwal <sid0@fb.com>
parents:
27228
diff
changeset
|
58 e2 = sys.exc_info() |
25328
2cfb0bbf83a1
hooks: replace if-try-finally with a "with" statement
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
25184
diff
changeset
|
59 if ui.tracebackflag: |
2cfb0bbf83a1
hooks: replace if-try-finally with a "with" statement
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
25184
diff
changeset
|
60 ui.warn(_('exception from first failed import ' |
2cfb0bbf83a1
hooks: replace if-try-finally with a "with" statement
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
25184
diff
changeset
|
61 'attempt:\n')) |
2cfb0bbf83a1
hooks: replace if-try-finally with a "with" statement
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
25184
diff
changeset
|
62 ui.traceback(e1) |
2cfb0bbf83a1
hooks: replace if-try-finally with a "with" statement
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
25184
diff
changeset
|
63 if ui.tracebackflag: |
2cfb0bbf83a1
hooks: replace if-try-finally with a "with" statement
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
25184
diff
changeset
|
64 ui.warn(_('exception from second failed import ' |
2cfb0bbf83a1
hooks: replace if-try-finally with a "with" statement
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
25184
diff
changeset
|
65 'attempt:\n')) |
2cfb0bbf83a1
hooks: replace if-try-finally with a "with" statement
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
25184
diff
changeset
|
66 ui.traceback(e2) |
28080
37b818cad146
hook: for python hook ImportErrors, add note to run with --traceback
Siddharth Agarwal <sid0@fb.com>
parents:
28079
diff
changeset
|
67 |
37b818cad146
hook: for python hook ImportErrors, add note to run with --traceback
Siddharth Agarwal <sid0@fb.com>
parents:
28079
diff
changeset
|
68 if not ui.tracebackflag: |
37b818cad146
hook: for python hook ImportErrors, add note to run with --traceback
Siddharth Agarwal <sid0@fb.com>
parents:
28079
diff
changeset
|
69 tracebackhint = _( |
37b818cad146
hook: for python hook ImportErrors, add note to run with --traceback
Siddharth Agarwal <sid0@fb.com>
parents:
28079
diff
changeset
|
70 'run with --traceback for stack trace') |
37b818cad146
hook: for python hook ImportErrors, add note to run with --traceback
Siddharth Agarwal <sid0@fb.com>
parents:
28079
diff
changeset
|
71 else: |
37b818cad146
hook: for python hook ImportErrors, add note to run with --traceback
Siddharth Agarwal <sid0@fb.com>
parents:
28079
diff
changeset
|
72 tracebackhint = None |
26692
8d1cfd77b64f
hook: raise a separate exception for when loading a hook fails
Siddharth Agarwal <sid0@fb.com>
parents:
26587
diff
changeset
|
73 raise error.HookLoadError( |
28079
0c9e914029be
hook: fewer parentheses for hook load errors
Siddharth Agarwal <sid0@fb.com>
parents:
28078
diff
changeset
|
74 _('%s hook is invalid: import of "%s" failed') % |
28080
37b818cad146
hook: for python hook ImportErrors, add note to run with --traceback
Siddharth Agarwal <sid0@fb.com>
parents:
28079
diff
changeset
|
75 (hname, modname), hint=tracebackhint) |
9332
872d49dd577a
hook: fix full path imports on Windows (issue1779)
Steve Borho <steve@borho.org>
parents:
8366
diff
changeset
|
76 sys.path = oldpaths |
4622
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
77 try: |
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
78 for p in funcname.split('.')[1:]: |
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
79 obj = getattr(obj, p) |
7280
810ca383da9c
remove unused variables
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
6762
diff
changeset
|
80 except AttributeError: |
26692
8d1cfd77b64f
hook: raise a separate exception for when loading a hook fails
Siddharth Agarwal <sid0@fb.com>
parents:
26587
diff
changeset
|
81 raise error.HookLoadError( |
28079
0c9e914029be
hook: fewer parentheses for hook load errors
Siddharth Agarwal <sid0@fb.com>
parents:
28078
diff
changeset
|
82 _('%s hook is invalid: "%s" is not defined') |
26692
8d1cfd77b64f
hook: raise a separate exception for when loading a hook fails
Siddharth Agarwal <sid0@fb.com>
parents:
26587
diff
changeset
|
83 % (hname, funcname)) |
21797
b009dd135aa0
hook: restore use of callable() since it was readded in Python 3.2
Augie Fackler <raf@durin42.com>
parents:
20548
diff
changeset
|
84 if not callable(obj): |
26692
8d1cfd77b64f
hook: raise a separate exception for when loading a hook fails
Siddharth Agarwal <sid0@fb.com>
parents:
26587
diff
changeset
|
85 raise error.HookLoadError( |
28079
0c9e914029be
hook: fewer parentheses for hook load errors
Siddharth Agarwal <sid0@fb.com>
parents:
28078
diff
changeset
|
86 _('%s hook is invalid: "%s" is not callable') |
26692
8d1cfd77b64f
hook: raise a separate exception for when loading a hook fails
Siddharth Agarwal <sid0@fb.com>
parents:
26587
diff
changeset
|
87 % (hname, funcname)) |
20547
9d9f8ccffead
hooks: move logging of hook name to after we have found the hook
Mads Kiilerich <madski@unity3d.com>
parents:
20422
diff
changeset
|
88 |
9d9f8ccffead
hooks: move logging of hook name to after we have found the hook
Mads Kiilerich <madski@unity3d.com>
parents:
20422
diff
changeset
|
89 ui.note(_("calling hook %s: %s\n") % (hname, funcname)) |
30975
22fbca1d11ed
mercurial: switch to util.timer for all interval timings
Simon Farnsworth <simonfar@fb.com>
parents:
30519
diff
changeset
|
90 starttime = util.timer() |
20547
9d9f8ccffead
hooks: move logging of hook name to after we have found the hook
Mads Kiilerich <madski@unity3d.com>
parents:
20422
diff
changeset
|
91 |
4622
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
92 try: |
31742
f243b7fbeba5
hook: use "htype" as variable name in _pythonhook
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
31205
diff
changeset
|
93 r = obj(ui=ui, repo=repo, hooktype=htype, **args) |
25660
328739ea70c3
global: mass rewrite to use modern exception syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25328
diff
changeset
|
94 except Exception as exc: |
26587
56b2bcea2529
error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25953
diff
changeset
|
95 if isinstance(exc, error.Abort): |
25084
7046c7e7fcb4
hooks: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
24716
diff
changeset
|
96 ui.warn(_('error: %s hook failed: %s\n') % |
7046c7e7fcb4
hooks: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
24716
diff
changeset
|
97 (hname, exc.args[0])) |
7046c7e7fcb4
hooks: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
24716
diff
changeset
|
98 else: |
7046c7e7fcb4
hooks: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
24716
diff
changeset
|
99 ui.warn(_('error: %s hook raised an exception: ' |
7046c7e7fcb4
hooks: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
24716
diff
changeset
|
100 '%s\n') % (hname, exc)) |
7046c7e7fcb4
hooks: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
24716
diff
changeset
|
101 if throw: |
4622
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
102 raise |
28108
2a71d9483199
hook: for python hook exceptions, add note to run with --traceback
Siddharth Agarwal <sid0@fb.com>
parents:
28106
diff
changeset
|
103 if not ui.tracebackflag: |
2a71d9483199
hook: for python hook exceptions, add note to run with --traceback
Siddharth Agarwal <sid0@fb.com>
parents:
28106
diff
changeset
|
104 ui.warn(_('(run with --traceback for stack trace)\n')) |
25084
7046c7e7fcb4
hooks: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
24716
diff
changeset
|
105 ui.traceback() |
26739
8429369eeb85
hook: for python hooks, also return whether an exception was raised
Siddharth Agarwal <sid0@fb.com>
parents:
26738
diff
changeset
|
106 return True, True |
14889
a59058fd074a
hooks: redirect stdout/err/in to the ui descriptors when calling python hooks
Idan Kamara <idankk86@gmail.com>
parents:
14711
diff
changeset
|
107 finally: |
30975
22fbca1d11ed
mercurial: switch to util.timer for all interval timings
Simon Farnsworth <simonfar@fb.com>
parents:
30519
diff
changeset
|
108 duration = util.timer() - starttime |
18691
4f485bd68f1d
blackbox: do not translate the log messages
Durham Goode <durham@fb.com>
parents:
18671
diff
changeset
|
109 ui.log('pythonhook', 'pythonhook-%s: %s finished in %0.2f seconds\n', |
31742
f243b7fbeba5
hook: use "htype" as variable name in _pythonhook
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
31205
diff
changeset
|
110 htype, funcname, duration) |
4622
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
111 if r: |
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
112 if throw: |
23415
cdbb85489c41
hook: raise a more specialized HookAbort exception when a hook fails
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
21797
diff
changeset
|
113 raise error.HookAbort(_('%s hook failed') % hname) |
4622
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
114 ui.warn(_('warning: %s hook failed\n') % hname) |
26739
8429369eeb85
hook: for python hooks, also return whether an exception was raised
Siddharth Agarwal <sid0@fb.com>
parents:
26738
diff
changeset
|
115 return r, False |
4622
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
116 |
31746
0fa30fbccc34
hook: provide hook type information to external hook
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
31745
diff
changeset
|
117 def _exthook(ui, repo, htype, name, cmd, args, throw): |
4622
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
118 ui.note(_("running hook %s: %s\n") % (name, cmd)) |
7787
b8d750daadde
Introduce HG_PREPEND to solve pretxn races
Matt Mackall <mpm@selenic.com>
parents:
7644
diff
changeset
|
119 |
30975
22fbca1d11ed
mercurial: switch to util.timer for all interval timings
Simon Farnsworth <simonfar@fb.com>
parents:
30519
diff
changeset
|
120 starttime = util.timer() |
7787
b8d750daadde
Introduce HG_PREPEND to solve pretxn races
Matt Mackall <mpm@selenic.com>
parents:
7644
diff
changeset
|
121 env = {} |
26751
520defbc0335
hook: centralize passing HG_PENDING to external hook process
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
26739
diff
changeset
|
122 |
520defbc0335
hook: centralize passing HG_PENDING to external hook process
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
26739
diff
changeset
|
123 # make in-memory changes visible to external process |
27228
10695f8f3323
dirstate: don't write repo.currenttransaction to repo.dirstate if repo
Sietse Brouwer <sbbrouwer@gmail.com>
parents:
26861
diff
changeset
|
124 if repo is not None: |
10695f8f3323
dirstate: don't write repo.currenttransaction to repo.dirstate if repo
Sietse Brouwer <sbbrouwer@gmail.com>
parents:
26861
diff
changeset
|
125 tr = repo.currenttransaction() |
10695f8f3323
dirstate: don't write repo.currenttransaction to repo.dirstate if repo
Sietse Brouwer <sbbrouwer@gmail.com>
parents:
26861
diff
changeset
|
126 repo.dirstate.write(tr) |
10695f8f3323
dirstate: don't write repo.currenttransaction to repo.dirstate if repo
Sietse Brouwer <sbbrouwer@gmail.com>
parents:
26861
diff
changeset
|
127 if tr and tr.writepending(): |
10695f8f3323
dirstate: don't write repo.currenttransaction to repo.dirstate if repo
Sietse Brouwer <sbbrouwer@gmail.com>
parents:
26861
diff
changeset
|
128 env['HG_PENDING'] = repo.root |
31746
0fa30fbccc34
hook: provide hook type information to external hook
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
31745
diff
changeset
|
129 env['HG_HOOKTYPE'] = htype |
31747
aff7b32b3c05
hook: add hook name information to external hook
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
31746
diff
changeset
|
130 env['HG_HOOKNAME'] = name |
26751
520defbc0335
hook: centralize passing HG_PENDING to external hook process
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
26739
diff
changeset
|
131 |
7787
b8d750daadde
Introduce HG_PREPEND to solve pretxn races
Matt Mackall <mpm@selenic.com>
parents:
7644
diff
changeset
|
132 for k, v in args.iteritems(): |
21797
b009dd135aa0
hook: restore use of callable() since it was readded in Python 3.2
Augie Fackler <raf@durin42.com>
parents:
20548
diff
changeset
|
133 if callable(v): |
7787
b8d750daadde
Introduce HG_PREPEND to solve pretxn races
Matt Mackall <mpm@selenic.com>
parents:
7644
diff
changeset
|
134 v = v() |
13207
1775382ff833
hooks: sort any dictionaries set in the environment
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
13119
diff
changeset
|
135 if isinstance(v, dict): |
1775382ff833
hooks: sort any dictionaries set in the environment
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
13119
diff
changeset
|
136 # make the dictionary element order stable across Python |
1775382ff833
hooks: sort any dictionaries set in the environment
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
13119
diff
changeset
|
137 # implementations |
1775382ff833
hooks: sort any dictionaries set in the environment
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
13119
diff
changeset
|
138 v = ('{' + |
1775382ff833
hooks: sort any dictionaries set in the environment
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
13119
diff
changeset
|
139 ', '.join('%r: %r' % i for i in sorted(v.iteritems())) + |
1775382ff833
hooks: sort any dictionaries set in the environment
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
13119
diff
changeset
|
140 '}') |
7787
b8d750daadde
Introduce HG_PREPEND to solve pretxn races
Matt Mackall <mpm@selenic.com>
parents:
7644
diff
changeset
|
141 env['HG_' + k.upper()] = v |
b8d750daadde
Introduce HG_PREPEND to solve pretxn races
Matt Mackall <mpm@selenic.com>
parents:
7644
diff
changeset
|
142 |
5869
2c565b9598b8
hooks: fix pre- and post- hooks specified in .hg/hgrc
Matt Mackall <mpm@selenic.com>
parents:
5833
diff
changeset
|
143 if repo: |
2c565b9598b8
hooks: fix pre- and post- hooks specified in .hg/hgrc
Matt Mackall <mpm@selenic.com>
parents:
5833
diff
changeset
|
144 cwd = repo.root |
2c565b9598b8
hooks: fix pre- and post- hooks specified in .hg/hgrc
Matt Mackall <mpm@selenic.com>
parents:
5833
diff
changeset
|
145 else: |
30519
20a42325fdef
py3: use pycompat.getcwd() instead of os.getcwd()
Pulkit Goyal <7895pulkit@gmail.com>
parents:
30473
diff
changeset
|
146 cwd = pycompat.getcwd() |
31205
a48c6ac5c13a
hook: give exthooks tags for blocking time
Simon Farnsworth <simonfar@fb.com>
parents:
30975
diff
changeset
|
147 r = ui.system(cmd, environ=env, cwd=cwd, blockedtag='exthook-%s' % (name,)) |
18671
1c305128e5b9
blackbox: logs python and extension hooks via ui.log()
Durham Goode <durham@fb.com>
parents:
18111
diff
changeset
|
148 |
30975
22fbca1d11ed
mercurial: switch to util.timer for all interval timings
Simon Farnsworth <simonfar@fb.com>
parents:
30519
diff
changeset
|
149 duration = util.timer() - starttime |
18691
4f485bd68f1d
blackbox: do not translate the log messages
Durham Goode <durham@fb.com>
parents:
18671
diff
changeset
|
150 ui.log('exthook', 'exthook-%s: %s finished in %0.2f seconds\n', |
18671
1c305128e5b9
blackbox: logs python and extension hooks via ui.log()
Durham Goode <durham@fb.com>
parents:
18111
diff
changeset
|
151 name, cmd, duration) |
4622
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
152 if r: |
14234
600e64004eb5
rename explain_exit to explainexit
Adrian Buehlmann <adrian@cadifra.com>
parents:
13207
diff
changeset
|
153 desc, r = util.explainexit(r) |
4622
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
154 if throw: |
23415
cdbb85489c41
hook: raise a more specialized HookAbort exception when a hook fails
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
21797
diff
changeset
|
155 raise error.HookAbort(_('%s hook %s') % (name, desc)) |
4622
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
156 ui.warn(_('warning: %s hook %s\n') % (name, desc)) |
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
157 return r |
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
158 |
28938
ea1fec3e9aba
hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
28937
diff
changeset
|
159 # represent an untrusted hook command |
ea1fec3e9aba
hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
28937
diff
changeset
|
160 _fromuntrusted = object() |
ea1fec3e9aba
hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
28937
diff
changeset
|
161 |
15896
30c34fde40cc
hooks: prioritize run order of hooks
Matt Zuba <matt.zuba@goodwillaz.org>
parents:
15512
diff
changeset
|
162 def _allhooks(ui): |
28937
3112c5e18835
hook: split config reading further
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
28936
diff
changeset
|
163 """return a list of (hook-id, cmd) pairs sorted by priority""" |
3112c5e18835
hook: split config reading further
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
28936
diff
changeset
|
164 hooks = _hookitems(ui) |
28938
ea1fec3e9aba
hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
28937
diff
changeset
|
165 # Be careful in this section, propagating the real commands from untrusted |
ea1fec3e9aba
hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
28937
diff
changeset
|
166 # sources would create a security vulnerability, make sure anything altered |
ea1fec3e9aba
hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
28937
diff
changeset
|
167 # in that section uses "_fromuntrusted" as its command. |
ea1fec3e9aba
hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
28937
diff
changeset
|
168 untrustedhooks = _hookitems(ui, _untrusted=True) |
ea1fec3e9aba
hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
28937
diff
changeset
|
169 for name, value in untrustedhooks.items(): |
ea1fec3e9aba
hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
28937
diff
changeset
|
170 trustedvalue = hooks.get(name, (None, None, name, _fromuntrusted)) |
ea1fec3e9aba
hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
28937
diff
changeset
|
171 if value != trustedvalue: |
ea1fec3e9aba
hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
28937
diff
changeset
|
172 (lp, lo, lk, lv) = trustedvalue |
ea1fec3e9aba
hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
28937
diff
changeset
|
173 hooks[name] = (lp, lo, lk, _fromuntrusted) |
ea1fec3e9aba
hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
28937
diff
changeset
|
174 # (end of the security sensitive section) |
28937
3112c5e18835
hook: split config reading further
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
28936
diff
changeset
|
175 return [(k, v) for p, o, k, v in sorted(hooks.values())] |
3112c5e18835
hook: split config reading further
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
28936
diff
changeset
|
176 |
28938
ea1fec3e9aba
hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
28937
diff
changeset
|
177 def _hookitems(ui, _untrusted=False): |
28937
3112c5e18835
hook: split config reading further
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
28936
diff
changeset
|
178 """return all hooks items ready to be sorted""" |
28936
44bd37af54e5
hook: small refactor to store hooks as dict instead of list
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
28109
diff
changeset
|
179 hooks = {} |
28938
ea1fec3e9aba
hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
28937
diff
changeset
|
180 for name, cmd in ui.configitems('hooks', untrusted=_untrusted): |
15896
30c34fde40cc
hooks: prioritize run order of hooks
Matt Zuba <matt.zuba@goodwillaz.org>
parents:
15512
diff
changeset
|
181 if not name.startswith('priority'): |
30c34fde40cc
hooks: prioritize run order of hooks
Matt Zuba <matt.zuba@goodwillaz.org>
parents:
15512
diff
changeset
|
182 priority = ui.configint('hooks', 'priority.%s' % name, 0) |
28936
44bd37af54e5
hook: small refactor to store hooks as dict instead of list
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
28109
diff
changeset
|
183 hooks[name] = (-priority, len(hooks), name, cmd) |
28937
3112c5e18835
hook: split config reading further
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
28936
diff
changeset
|
184 return hooks |
15896
30c34fde40cc
hooks: prioritize run order of hooks
Matt Zuba <matt.zuba@goodwillaz.org>
parents:
15512
diff
changeset
|
185 |
5833
323b9c55b328
hook: redirect stdout to stderr for ssh and http servers
Matt Mackall <mpm@selenic.com>
parents:
4622
diff
changeset
|
186 _redirect = False |
323b9c55b328
hook: redirect stdout to stderr for ssh and http servers
Matt Mackall <mpm@selenic.com>
parents:
4622
diff
changeset
|
187 def redirect(state): |
6266
9f76df0edb7d
hook.py: fix redirections introduced by 323b9c55b328
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents:
5869
diff
changeset
|
188 global _redirect |
5833
323b9c55b328
hook: redirect stdout to stderr for ssh and http servers
Matt Mackall <mpm@selenic.com>
parents:
4622
diff
changeset
|
189 _redirect = state |
323b9c55b328
hook: redirect stdout to stderr for ssh and http servers
Matt Mackall <mpm@selenic.com>
parents:
4622
diff
changeset
|
190 |
31745
33504b54863e
hook: use 'htype' in 'hook'
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
31744
diff
changeset
|
191 def hook(ui, repo, htype, throw=False, **args): |
17048
15d4d475de9e
ui: add a variable to control whether hooks should be called
Idan Kamara <idankk86@gmail.com>
parents:
15896
diff
changeset
|
192 if not ui.callhooks: |
15d4d475de9e
ui: add a variable to control whether hooks should be called
Idan Kamara <idankk86@gmail.com>
parents:
15896
diff
changeset
|
193 return False |
15d4d475de9e
ui: add a variable to control whether hooks should be called
Idan Kamara <idankk86@gmail.com>
parents:
15896
diff
changeset
|
194 |
26737
a930d66a04af
hook: factor out determination of hooks from running them
Siddharth Agarwal <sid0@fb.com>
parents:
26692
diff
changeset
|
195 hooks = [] |
a930d66a04af
hook: factor out determination of hooks from running them
Siddharth Agarwal <sid0@fb.com>
parents:
26692
diff
changeset
|
196 for hname, cmd in _allhooks(ui): |
31745
33504b54863e
hook: use 'htype' in 'hook'
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
31744
diff
changeset
|
197 if hname.split('.')[0] == htype and cmd: |
26737
a930d66a04af
hook: factor out determination of hooks from running them
Siddharth Agarwal <sid0@fb.com>
parents:
26692
diff
changeset
|
198 hooks.append((hname, cmd)) |
a930d66a04af
hook: factor out determination of hooks from running them
Siddharth Agarwal <sid0@fb.com>
parents:
26692
diff
changeset
|
199 |
31745
33504b54863e
hook: use 'htype' in 'hook'
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
31744
diff
changeset
|
200 res = runhooks(ui, repo, htype, hooks, throw=throw, **args) |
26738
9abc2c921bbd
hook.runhooks: return a dict of result values
Siddharth Agarwal <sid0@fb.com>
parents:
26737
diff
changeset
|
201 r = False |
9abc2c921bbd
hook.runhooks: return a dict of result values
Siddharth Agarwal <sid0@fb.com>
parents:
26737
diff
changeset
|
202 for hname, cmd in hooks: |
26739
8429369eeb85
hook: for python hooks, also return whether an exception was raised
Siddharth Agarwal <sid0@fb.com>
parents:
26738
diff
changeset
|
203 r = res[hname][0] or r |
26738
9abc2c921bbd
hook.runhooks: return a dict of result values
Siddharth Agarwal <sid0@fb.com>
parents:
26737
diff
changeset
|
204 return r |
26737
a930d66a04af
hook: factor out determination of hooks from running them
Siddharth Agarwal <sid0@fb.com>
parents:
26692
diff
changeset
|
205 |
31744
5678496659e9
hook: use 'htype' in 'runhooks'
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
31743
diff
changeset
|
206 def runhooks(ui, repo, htype, hooks, throw=False, **args): |
26738
9abc2c921bbd
hook.runhooks: return a dict of result values
Siddharth Agarwal <sid0@fb.com>
parents:
26737
diff
changeset
|
207 res = {} |
9658
852b1f3032d2
hook: only redirect stdout if it and stderr are valid files
Sune Foldager <cryo@cyanite.org>
parents:
9332
diff
changeset
|
208 oldstdout = -1 |
5833
323b9c55b328
hook: redirect stdout to stderr for ssh and http servers
Matt Mackall <mpm@selenic.com>
parents:
4622
diff
changeset
|
209 |
7416
196b05a548d0
hooks: restore io correctly on exception
Jesse Long <jesse@virtualpostman.co.za>
parents:
7280
diff
changeset
|
210 try: |
26737
a930d66a04af
hook: factor out determination of hooks from running them
Siddharth Agarwal <sid0@fb.com>
parents:
26692
diff
changeset
|
211 for hname, cmd in hooks: |
17963
6180dcb29ec5
hooks: delay I/O redirection until we actually run a hook (issue3711)
Matt Mackall <mpm@selenic.com>
parents:
17428
diff
changeset
|
212 if oldstdout == -1 and _redirect: |
6180dcb29ec5
hooks: delay I/O redirection until we actually run a hook (issue3711)
Matt Mackall <mpm@selenic.com>
parents:
17428
diff
changeset
|
213 try: |
30473
39d13b8c101d
py3: bulk replace sys.stdin/out/err by util's
Yuya Nishihara <yuya@tcha.org>
parents:
30365
diff
changeset
|
214 stdoutno = util.stdout.fileno() |
39d13b8c101d
py3: bulk replace sys.stdin/out/err by util's
Yuya Nishihara <yuya@tcha.org>
parents:
30365
diff
changeset
|
215 stderrno = util.stderr.fileno() |
17963
6180dcb29ec5
hooks: delay I/O redirection until we actually run a hook (issue3711)
Matt Mackall <mpm@selenic.com>
parents:
17428
diff
changeset
|
216 # temporarily redirect stdout to stderr, if possible |
6180dcb29ec5
hooks: delay I/O redirection until we actually run a hook (issue3711)
Matt Mackall <mpm@selenic.com>
parents:
17428
diff
changeset
|
217 if stdoutno >= 0 and stderrno >= 0: |
30473
39d13b8c101d
py3: bulk replace sys.stdin/out/err by util's
Yuya Nishihara <yuya@tcha.org>
parents:
30365
diff
changeset
|
218 util.stdout.flush() |
17963
6180dcb29ec5
hooks: delay I/O redirection until we actually run a hook (issue3711)
Matt Mackall <mpm@selenic.com>
parents:
17428
diff
changeset
|
219 oldstdout = os.dup(stdoutno) |
6180dcb29ec5
hooks: delay I/O redirection until we actually run a hook (issue3711)
Matt Mackall <mpm@selenic.com>
parents:
17428
diff
changeset
|
220 os.dup2(stderrno, stdoutno) |
17964
2c63896783e3
hooks: be even more forgiven of non-fd descriptors (issue3711)
Matt Mackall <mpm@selenic.com>
parents:
17963
diff
changeset
|
221 except (OSError, AttributeError): |
2c63896783e3
hooks: be even more forgiven of non-fd descriptors (issue3711)
Matt Mackall <mpm@selenic.com>
parents:
17963
diff
changeset
|
222 # files seem to be bogus, give up on redirecting (WSGI, etc) |
17963
6180dcb29ec5
hooks: delay I/O redirection until we actually run a hook (issue3711)
Matt Mackall <mpm@selenic.com>
parents:
17428
diff
changeset
|
223 pass |
6180dcb29ec5
hooks: delay I/O redirection until we actually run a hook (issue3711)
Matt Mackall <mpm@selenic.com>
parents:
17428
diff
changeset
|
224 |
28938
ea1fec3e9aba
hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
28937
diff
changeset
|
225 if cmd is _fromuntrusted: |
ea1fec3e9aba
hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
28937
diff
changeset
|
226 if throw: |
ea1fec3e9aba
hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
28937
diff
changeset
|
227 raise error.HookAbort( |
31743
f610c3220eec
hook: fix name used in untrusted message
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
31742
diff
changeset
|
228 _('untrusted hook %s not executed') % hname, |
28938
ea1fec3e9aba
hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
28937
diff
changeset
|
229 hint = _("see 'hg help config.trusted'")) |
31743
f610c3220eec
hook: fix name used in untrusted message
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
31742
diff
changeset
|
230 ui.warn(_('warning: untrusted hook %s not executed\n') % hname) |
28938
ea1fec3e9aba
hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
28937
diff
changeset
|
231 r = 1 |
ea1fec3e9aba
hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
28937
diff
changeset
|
232 raised = False |
ea1fec3e9aba
hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
28937
diff
changeset
|
233 elif callable(cmd): |
31744
5678496659e9
hook: use 'htype' in 'runhooks'
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
31743
diff
changeset
|
234 r, raised = _pythonhook(ui, repo, htype, hname, cmd, args, |
5678496659e9
hook: use 'htype' in 'runhooks'
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
31743
diff
changeset
|
235 throw) |
7416
196b05a548d0
hooks: restore io correctly on exception
Jesse Long <jesse@virtualpostman.co.za>
parents:
7280
diff
changeset
|
236 elif cmd.startswith('python:'): |
9332
872d49dd577a
hook: fix full path imports on Windows (issue1779)
Steve Borho <steve@borho.org>
parents:
8366
diff
changeset
|
237 if cmd.count(':') >= 2: |
872d49dd577a
hook: fix full path imports on Windows (issue1779)
Steve Borho <steve@borho.org>
parents:
8366
diff
changeset
|
238 path, cmd = cmd[7:].rsplit(':', 1) |
13118
789e0fa2fcea
hook: assume relative path to hook is given from repo root
Alexander Solovyov <alexander@solovyov.net>
parents:
11469
diff
changeset
|
239 path = util.expandpath(path) |
13119
ecf7d6e0eef0
hook: fix import path handling for repo=None
Matt Mackall <mpm@selenic.com>
parents:
13118
diff
changeset
|
240 if repo: |
ecf7d6e0eef0
hook: fix import path handling for repo=None
Matt Mackall <mpm@selenic.com>
parents:
13118
diff
changeset
|
241 path = os.path.join(repo.root, path) |
17217
1b2b727a885f
hooks: print out more information when loading a python hook fails
Simon Heimberg <simohe@besonet.ch>
parents:
17048
diff
changeset
|
242 try: |
1b2b727a885f
hooks: print out more information when loading a python hook fails
Simon Heimberg <simohe@besonet.ch>
parents:
17048
diff
changeset
|
243 mod = extensions.loadpath(path, 'hghook.%s' % hname) |
1b2b727a885f
hooks: print out more information when loading a python hook fails
Simon Heimberg <simohe@besonet.ch>
parents:
17048
diff
changeset
|
244 except Exception: |
1b2b727a885f
hooks: print out more information when loading a python hook fails
Simon Heimberg <simohe@besonet.ch>
parents:
17048
diff
changeset
|
245 ui.write(_("loading %s hook failed:\n") % hname) |
1b2b727a885f
hooks: print out more information when loading a python hook fails
Simon Heimberg <simohe@besonet.ch>
parents:
17048
diff
changeset
|
246 raise |
7916
f779e1996e23
ability to load hooks from arbitrary python module
Alexander Solovyov <piranha@piranha.org.ua>
parents:
7787
diff
changeset
|
247 hookfn = getattr(mod, cmd) |
f779e1996e23
ability to load hooks from arbitrary python module
Alexander Solovyov <piranha@piranha.org.ua>
parents:
7787
diff
changeset
|
248 else: |
f779e1996e23
ability to load hooks from arbitrary python module
Alexander Solovyov <piranha@piranha.org.ua>
parents:
7787
diff
changeset
|
249 hookfn = cmd[7:].strip() |
31744
5678496659e9
hook: use 'htype' in 'runhooks'
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
31743
diff
changeset
|
250 r, raised = _pythonhook(ui, repo, htype, hname, hookfn, args, |
26739
8429369eeb85
hook: for python hooks, also return whether an exception was raised
Siddharth Agarwal <sid0@fb.com>
parents:
26738
diff
changeset
|
251 throw) |
7416
196b05a548d0
hooks: restore io correctly on exception
Jesse Long <jesse@virtualpostman.co.za>
parents:
7280
diff
changeset
|
252 else: |
31746
0fa30fbccc34
hook: provide hook type information to external hook
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
31745
diff
changeset
|
253 r = _exthook(ui, repo, htype, hname, cmd, args, throw) |
26739
8429369eeb85
hook: for python hooks, also return whether an exception was raised
Siddharth Agarwal <sid0@fb.com>
parents:
26738
diff
changeset
|
254 raised = False |
26738
9abc2c921bbd
hook.runhooks: return a dict of result values
Siddharth Agarwal <sid0@fb.com>
parents:
26737
diff
changeset
|
255 |
26739
8429369eeb85
hook: for python hooks, also return whether an exception was raised
Siddharth Agarwal <sid0@fb.com>
parents:
26738
diff
changeset
|
256 res[hname] = r, raised |
24716
2abbf4750915
hook: forcibly flush stderr for Windows test stability
Matt Harbison <matt_harbison@yahoo.com>
parents:
23426
diff
changeset
|
257 |
2abbf4750915
hook: forcibly flush stderr for Windows test stability
Matt Harbison <matt_harbison@yahoo.com>
parents:
23426
diff
changeset
|
258 # The stderr is fully buffered on Windows when connected to a pipe. |
2abbf4750915
hook: forcibly flush stderr for Windows test stability
Matt Harbison <matt_harbison@yahoo.com>
parents:
23426
diff
changeset
|
259 # A forcible flush is required to make small stderr data in the |
2abbf4750915
hook: forcibly flush stderr for Windows test stability
Matt Harbison <matt_harbison@yahoo.com>
parents:
23426
diff
changeset
|
260 # remote side available to the client immediately. |
30473
39d13b8c101d
py3: bulk replace sys.stdin/out/err by util's
Yuya Nishihara <yuya@tcha.org>
parents:
30365
diff
changeset
|
261 util.stderr.flush() |
7416
196b05a548d0
hooks: restore io correctly on exception
Jesse Long <jesse@virtualpostman.co.za>
parents:
7280
diff
changeset
|
262 finally: |
9658
852b1f3032d2
hook: only redirect stdout if it and stderr are valid files
Sune Foldager <cryo@cyanite.org>
parents:
9332
diff
changeset
|
263 if _redirect and oldstdout >= 0: |
30473
39d13b8c101d
py3: bulk replace sys.stdin/out/err by util's
Yuya Nishihara <yuya@tcha.org>
parents:
30365
diff
changeset
|
264 util.stdout.flush() # write hook output to stderr fd |
9658
852b1f3032d2
hook: only redirect stdout if it and stderr are valid files
Sune Foldager <cryo@cyanite.org>
parents:
9332
diff
changeset
|
265 os.dup2(oldstdout, stdoutno) |
7416
196b05a548d0
hooks: restore io correctly on exception
Jesse Long <jesse@virtualpostman.co.za>
parents:
7280
diff
changeset
|
266 os.close(oldstdout) |
6266
9f76df0edb7d
hook.py: fix redirections introduced by 323b9c55b328
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents:
5869
diff
changeset
|
267 |
26738
9abc2c921bbd
hook.runhooks: return a dict of result values
Siddharth Agarwal <sid0@fb.com>
parents:
26737
diff
changeset
|
268 return res |