Mercurial > hg
annotate mercurial/hook.py @ 27015:341cb90ffd18
util: disable floating point stat times (issue4836)
Alternate fix for this issue which avoids putting extra function calls
and exception handling in the fast path.
For almost all purposes, integer timestamps are preferable to
Mercurial. It stores integer timestamps in the dirstate and would thus
like to avoid doing any float/int comparisons or conversions. We will
continue to have to deal with 1-second granularity on filesystems for
quite some time, so this won't significantly hinder our capabilities.
This has some impact on our file cache validation code in that it
lowers timestamp resolution. But as we still have to deal with
low-resolution filesystems, we're not relying on this anyway.
An alternate approach is to use stat[ST_MTIME], which is guaranteed to
be an integer. But since this support isn't already in our extension,
we can't depend on it being available without adding a hard Python->C
API dependency that's painful for people like yours truly who have
bisect regularly and people without compilers.
author | Matt Mackall <mpm@selenic.com> |
---|---|
date | Thu, 19 Nov 2015 13:21:24 -0600 |
parents | 10a1a4b3e775 |
children | 10695f8f3323 |
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 import time |
d15b279ddade
hook: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
13 |
d15b279ddade
hook: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
14 from .i18n import _ |
d15b279ddade
hook: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
15 from . import ( |
d15b279ddade
hook: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
16 demandimport, |
d15b279ddade
hook: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
17 error, |
d15b279ddade
hook: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
18 extensions, |
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 |
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
22 def _pythonhook(ui, repo, name, hname, funcname, args, throw): |
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( |
8d1cfd77b64f
hook: raise a separate exception for when loading a hook fails
Siddharth Agarwal <sid0@fb.com>
parents:
26587
diff
changeset
|
39 _('%s hook is invalid ("%s" not in a module)') |
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) |
4622
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
52 except ImportError: |
25328
2cfb0bbf83a1
hooks: replace if-try-finally with a "with" statement
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
25184
diff
changeset
|
53 e1 = sys.exc_type, sys.exc_value, sys.exc_traceback |
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) |
2cfb0bbf83a1
hooks: replace if-try-finally with a "with" statement
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
25184
diff
changeset
|
57 except ImportError: |
2cfb0bbf83a1
hooks: replace if-try-finally with a "with" statement
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
25184
diff
changeset
|
58 e2 = sys.exc_type, sys.exc_value, sys.exc_traceback |
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) |
26692
8d1cfd77b64f
hook: raise a separate exception for when loading a hook fails
Siddharth Agarwal <sid0@fb.com>
parents:
26587
diff
changeset
|
67 raise error.HookLoadError( |
8d1cfd77b64f
hook: raise a separate exception for when loading a hook fails
Siddharth Agarwal <sid0@fb.com>
parents:
26587
diff
changeset
|
68 _('%s hook is invalid (import of "%s" failed)') % |
8d1cfd77b64f
hook: raise a separate exception for when loading a hook fails
Siddharth Agarwal <sid0@fb.com>
parents:
26587
diff
changeset
|
69 (hname, modname)) |
9332
872d49dd577a
hook: fix full path imports on Windows (issue1779)
Steve Borho <steve@borho.org>
parents:
8366
diff
changeset
|
70 sys.path = oldpaths |
4622
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
71 try: |
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
72 for p in funcname.split('.')[1:]: |
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
73 obj = getattr(obj, p) |
7280
810ca383da9c
remove unused variables
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
6762
diff
changeset
|
74 except AttributeError: |
26692
8d1cfd77b64f
hook: raise a separate exception for when loading a hook fails
Siddharth Agarwal <sid0@fb.com>
parents:
26587
diff
changeset
|
75 raise error.HookLoadError( |
8d1cfd77b64f
hook: raise a separate exception for when loading a hook fails
Siddharth Agarwal <sid0@fb.com>
parents:
26587
diff
changeset
|
76 _('%s hook is invalid ("%s" is not defined)') |
8d1cfd77b64f
hook: raise a separate exception for when loading a hook fails
Siddharth Agarwal <sid0@fb.com>
parents:
26587
diff
changeset
|
77 % (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
|
78 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
|
79 raise error.HookLoadError( |
8d1cfd77b64f
hook: raise a separate exception for when loading a hook fails
Siddharth Agarwal <sid0@fb.com>
parents:
26587
diff
changeset
|
80 _('%s hook is invalid ("%s" is not callable)') |
8d1cfd77b64f
hook: raise a separate exception for when loading a hook fails
Siddharth Agarwal <sid0@fb.com>
parents:
26587
diff
changeset
|
81 % (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
|
82 |
9d9f8ccffead
hooks: move logging of hook name to after we have found the hook
Mads Kiilerich <madski@unity3d.com>
parents:
20422
diff
changeset
|
83 ui.note(_("calling hook %s: %s\n") % (hname, funcname)) |
9d9f8ccffead
hooks: move logging of hook name to after we have found the hook
Mads Kiilerich <madski@unity3d.com>
parents:
20422
diff
changeset
|
84 starttime = time.time() |
9d9f8ccffead
hooks: move logging of hook name to after we have found the hook
Mads Kiilerich <madski@unity3d.com>
parents:
20422
diff
changeset
|
85 |
4622
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
86 try: |
25084
7046c7e7fcb4
hooks: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
24716
diff
changeset
|
87 # redirect IO descriptors to the ui descriptors so hooks |
7046c7e7fcb4
hooks: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
24716
diff
changeset
|
88 # that write directly to these don't mess up the command |
7046c7e7fcb4
hooks: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
24716
diff
changeset
|
89 # protocol when running through the command server |
7046c7e7fcb4
hooks: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
24716
diff
changeset
|
90 old = sys.stdout, sys.stderr, sys.stdin |
7046c7e7fcb4
hooks: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
24716
diff
changeset
|
91 sys.stdout, sys.stderr, sys.stdin = ui.fout, ui.ferr, ui.fin |
14889
a59058fd074a
hooks: redirect stdout/err/in to the ui descriptors when calling python hooks
Idan Kamara <idankk86@gmail.com>
parents:
14711
diff
changeset
|
92 |
25084
7046c7e7fcb4
hooks: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
24716
diff
changeset
|
93 r = obj(ui=ui, repo=repo, hooktype=name, **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 |
25084
7046c7e7fcb4
hooks: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
24716
diff
changeset
|
103 ui.traceback() |
26739
8429369eeb85
hook: for python hooks, also return whether an exception was raised
Siddharth Agarwal <sid0@fb.com>
parents:
26738
diff
changeset
|
104 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
|
105 finally: |
a59058fd074a
hooks: redirect stdout/err/in to the ui descriptors when calling python hooks
Idan Kamara <idankk86@gmail.com>
parents:
14711
diff
changeset
|
106 sys.stdout, sys.stderr, sys.stdin = old |
18671
1c305128e5b9
blackbox: logs python and extension hooks via ui.log()
Durham Goode <durham@fb.com>
parents:
18111
diff
changeset
|
107 duration = time.time() - starttime |
18691
4f485bd68f1d
blackbox: do not translate the log messages
Durham Goode <durham@fb.com>
parents:
18671
diff
changeset
|
108 ui.log('pythonhook', 'pythonhook-%s: %s finished in %0.2f seconds\n', |
20548
5bd6a9fec103
hooks: for python hooks, consistently use __name__ etc as name, not the repr
Mads Kiilerich <madski@unity3d.com>
parents:
20547
diff
changeset
|
109 name, funcname, duration) |
4622
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
110 if r: |
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
111 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
|
112 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
|
113 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
|
114 return r, False |
4622
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
115 |
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
116 def _exthook(ui, repo, name, cmd, args, throw): |
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
117 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
|
118 |
18671
1c305128e5b9
blackbox: logs python and extension hooks via ui.log()
Durham Goode <durham@fb.com>
parents:
18111
diff
changeset
|
119 starttime = time.time() |
7787
b8d750daadde
Introduce HG_PREPEND to solve pretxn races
Matt Mackall <mpm@selenic.com>
parents:
7644
diff
changeset
|
120 env = {} |
26751
520defbc0335
hook: centralize passing HG_PENDING to external hook process
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
26739
diff
changeset
|
121 |
520defbc0335
hook: centralize passing HG_PENDING to external hook process
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
26739
diff
changeset
|
122 # make in-memory changes visible to external process |
520defbc0335
hook: centralize passing HG_PENDING to external hook process
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
26739
diff
changeset
|
123 tr = repo.currenttransaction() |
520defbc0335
hook: centralize passing HG_PENDING to external hook process
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
26739
diff
changeset
|
124 repo.dirstate.write(tr) |
26861
10a1a4b3e775
hooks: back 9f272bf3b342 out
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
26858
diff
changeset
|
125 if tr and tr.writepending(): |
26751
520defbc0335
hook: centralize passing HG_PENDING to external hook process
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
26739
diff
changeset
|
126 env['HG_PENDING'] = repo.root |
520defbc0335
hook: centralize passing HG_PENDING to external hook process
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
26739
diff
changeset
|
127 |
7787
b8d750daadde
Introduce HG_PREPEND to solve pretxn races
Matt Mackall <mpm@selenic.com>
parents:
7644
diff
changeset
|
128 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
|
129 if callable(v): |
7787
b8d750daadde
Introduce HG_PREPEND to solve pretxn races
Matt Mackall <mpm@selenic.com>
parents:
7644
diff
changeset
|
130 v = v() |
13207
1775382ff833
hooks: sort any dictionaries set in the environment
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
13119
diff
changeset
|
131 if isinstance(v, dict): |
1775382ff833
hooks: sort any dictionaries set in the environment
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
13119
diff
changeset
|
132 # 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
|
133 # implementations |
1775382ff833
hooks: sort any dictionaries set in the environment
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
13119
diff
changeset
|
134 v = ('{' + |
1775382ff833
hooks: sort any dictionaries set in the environment
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
13119
diff
changeset
|
135 ', '.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
|
136 '}') |
7787
b8d750daadde
Introduce HG_PREPEND to solve pretxn races
Matt Mackall <mpm@selenic.com>
parents:
7644
diff
changeset
|
137 env['HG_' + k.upper()] = v |
b8d750daadde
Introduce HG_PREPEND to solve pretxn races
Matt Mackall <mpm@selenic.com>
parents:
7644
diff
changeset
|
138 |
5869
2c565b9598b8
hooks: fix pre- and post- hooks specified in .hg/hgrc
Matt Mackall <mpm@selenic.com>
parents:
5833
diff
changeset
|
139 if repo: |
2c565b9598b8
hooks: fix pre- and post- hooks specified in .hg/hgrc
Matt Mackall <mpm@selenic.com>
parents:
5833
diff
changeset
|
140 cwd = repo.root |
2c565b9598b8
hooks: fix pre- and post- hooks specified in .hg/hgrc
Matt Mackall <mpm@selenic.com>
parents:
5833
diff
changeset
|
141 else: |
2c565b9598b8
hooks: fix pre- and post- hooks specified in .hg/hgrc
Matt Mackall <mpm@selenic.com>
parents:
5833
diff
changeset
|
142 cwd = os.getcwd() |
23270
41c03b7592ed
util.system: use ui.system() in place of optional ui.fout parameter
Yuya Nishihara <yuya@tcha.org>
parents:
23268
diff
changeset
|
143 r = ui.system(cmd, environ=env, cwd=cwd) |
18671
1c305128e5b9
blackbox: logs python and extension hooks via ui.log()
Durham Goode <durham@fb.com>
parents:
18111
diff
changeset
|
144 |
1c305128e5b9
blackbox: logs python and extension hooks via ui.log()
Durham Goode <durham@fb.com>
parents:
18111
diff
changeset
|
145 duration = time.time() - starttime |
18691
4f485bd68f1d
blackbox: do not translate the log messages
Durham Goode <durham@fb.com>
parents:
18671
diff
changeset
|
146 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
|
147 name, cmd, duration) |
4622
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
148 if r: |
14234
600e64004eb5
rename explain_exit to explainexit
Adrian Buehlmann <adrian@cadifra.com>
parents:
13207
diff
changeset
|
149 desc, r = util.explainexit(r) |
4622
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
150 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
|
151 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
|
152 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
|
153 return r |
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
154 |
15896
30c34fde40cc
hooks: prioritize run order of hooks
Matt Zuba <matt.zuba@goodwillaz.org>
parents:
15512
diff
changeset
|
155 def _allhooks(ui): |
30c34fde40cc
hooks: prioritize run order of hooks
Matt Zuba <matt.zuba@goodwillaz.org>
parents:
15512
diff
changeset
|
156 hooks = [] |
30c34fde40cc
hooks: prioritize run order of hooks
Matt Zuba <matt.zuba@goodwillaz.org>
parents:
15512
diff
changeset
|
157 for name, cmd in ui.configitems('hooks'): |
30c34fde40cc
hooks: prioritize run order of hooks
Matt Zuba <matt.zuba@goodwillaz.org>
parents:
15512
diff
changeset
|
158 if not name.startswith('priority'): |
30c34fde40cc
hooks: prioritize run order of hooks
Matt Zuba <matt.zuba@goodwillaz.org>
parents:
15512
diff
changeset
|
159 priority = ui.configint('hooks', 'priority.%s' % name, 0) |
30c34fde40cc
hooks: prioritize run order of hooks
Matt Zuba <matt.zuba@goodwillaz.org>
parents:
15512
diff
changeset
|
160 hooks.append((-priority, len(hooks), name, cmd)) |
30c34fde40cc
hooks: prioritize run order of hooks
Matt Zuba <matt.zuba@goodwillaz.org>
parents:
15512
diff
changeset
|
161 return [(k, v) for p, o, k, v in sorted(hooks)] |
30c34fde40cc
hooks: prioritize run order of hooks
Matt Zuba <matt.zuba@goodwillaz.org>
parents:
15512
diff
changeset
|
162 |
5833
323b9c55b328
hook: redirect stdout to stderr for ssh and http servers
Matt Mackall <mpm@selenic.com>
parents:
4622
diff
changeset
|
163 _redirect = False |
323b9c55b328
hook: redirect stdout to stderr for ssh and http servers
Matt Mackall <mpm@selenic.com>
parents:
4622
diff
changeset
|
164 def redirect(state): |
6266
9f76df0edb7d
hook.py: fix redirections introduced by 323b9c55b328
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents:
5869
diff
changeset
|
165 global _redirect |
5833
323b9c55b328
hook: redirect stdout to stderr for ssh and http servers
Matt Mackall <mpm@selenic.com>
parents:
4622
diff
changeset
|
166 _redirect = state |
323b9c55b328
hook: redirect stdout to stderr for ssh and http servers
Matt Mackall <mpm@selenic.com>
parents:
4622
diff
changeset
|
167 |
4622
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
168 def hook(ui, repo, name, 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
|
169 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
|
170 return False |
15d4d475de9e
ui: add a variable to control whether hooks should be called
Idan Kamara <idankk86@gmail.com>
parents:
15896
diff
changeset
|
171 |
26737
a930d66a04af
hook: factor out determination of hooks from running them
Siddharth Agarwal <sid0@fb.com>
parents:
26692
diff
changeset
|
172 hooks = [] |
a930d66a04af
hook: factor out determination of hooks from running them
Siddharth Agarwal <sid0@fb.com>
parents:
26692
diff
changeset
|
173 for hname, cmd in _allhooks(ui): |
a930d66a04af
hook: factor out determination of hooks from running them
Siddharth Agarwal <sid0@fb.com>
parents:
26692
diff
changeset
|
174 if hname.split('.')[0] == name and cmd: |
a930d66a04af
hook: factor out determination of hooks from running them
Siddharth Agarwal <sid0@fb.com>
parents:
26692
diff
changeset
|
175 hooks.append((hname, cmd)) |
a930d66a04af
hook: factor out determination of hooks from running them
Siddharth Agarwal <sid0@fb.com>
parents:
26692
diff
changeset
|
176 |
26738
9abc2c921bbd
hook.runhooks: return a dict of result values
Siddharth Agarwal <sid0@fb.com>
parents:
26737
diff
changeset
|
177 res = runhooks(ui, repo, name, hooks, throw=throw, **args) |
9abc2c921bbd
hook.runhooks: return a dict of result values
Siddharth Agarwal <sid0@fb.com>
parents:
26737
diff
changeset
|
178 r = False |
9abc2c921bbd
hook.runhooks: return a dict of result values
Siddharth Agarwal <sid0@fb.com>
parents:
26737
diff
changeset
|
179 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
|
180 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
|
181 return r |
26737
a930d66a04af
hook: factor out determination of hooks from running them
Siddharth Agarwal <sid0@fb.com>
parents:
26692
diff
changeset
|
182 |
a930d66a04af
hook: factor out determination of hooks from running them
Siddharth Agarwal <sid0@fb.com>
parents:
26692
diff
changeset
|
183 def runhooks(ui, repo, name, hooks, throw=False, **args): |
26738
9abc2c921bbd
hook.runhooks: return a dict of result values
Siddharth Agarwal <sid0@fb.com>
parents:
26737
diff
changeset
|
184 res = {} |
9658
852b1f3032d2
hook: only redirect stdout if it and stderr are valid files
Sune Foldager <cryo@cyanite.org>
parents:
9332
diff
changeset
|
185 oldstdout = -1 |
5833
323b9c55b328
hook: redirect stdout to stderr for ssh and http servers
Matt Mackall <mpm@selenic.com>
parents:
4622
diff
changeset
|
186 |
7416
196b05a548d0
hooks: restore io correctly on exception
Jesse Long <jesse@virtualpostman.co.za>
parents:
7280
diff
changeset
|
187 try: |
26737
a930d66a04af
hook: factor out determination of hooks from running them
Siddharth Agarwal <sid0@fb.com>
parents:
26692
diff
changeset
|
188 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
|
189 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
|
190 try: |
6180dcb29ec5
hooks: delay I/O redirection until we actually run a hook (issue3711)
Matt Mackall <mpm@selenic.com>
parents:
17428
diff
changeset
|
191 stdoutno = sys.__stdout__.fileno() |
6180dcb29ec5
hooks: delay I/O redirection until we actually run a hook (issue3711)
Matt Mackall <mpm@selenic.com>
parents:
17428
diff
changeset
|
192 stderrno = sys.__stderr__.fileno() |
6180dcb29ec5
hooks: delay I/O redirection until we actually run a hook (issue3711)
Matt Mackall <mpm@selenic.com>
parents:
17428
diff
changeset
|
193 # 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
|
194 if stdoutno >= 0 and stderrno >= 0: |
6180dcb29ec5
hooks: delay I/O redirection until we actually run a hook (issue3711)
Matt Mackall <mpm@selenic.com>
parents:
17428
diff
changeset
|
195 sys.__stdout__.flush() |
6180dcb29ec5
hooks: delay I/O redirection until we actually run a hook (issue3711)
Matt Mackall <mpm@selenic.com>
parents:
17428
diff
changeset
|
196 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
|
197 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
|
198 except (OSError, AttributeError): |
2c63896783e3
hooks: be even more forgiven of non-fd descriptors (issue3711)
Matt Mackall <mpm@selenic.com>
parents:
17963
diff
changeset
|
199 # 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
|
200 pass |
6180dcb29ec5
hooks: delay I/O redirection until we actually run a hook (issue3711)
Matt Mackall <mpm@selenic.com>
parents:
17428
diff
changeset
|
201 |
21797
b009dd135aa0
hook: restore use of callable() since it was readded in Python 3.2
Augie Fackler <raf@durin42.com>
parents:
20548
diff
changeset
|
202 if callable(cmd): |
26739
8429369eeb85
hook: for python hooks, also return whether an exception was raised
Siddharth Agarwal <sid0@fb.com>
parents:
26738
diff
changeset
|
203 r, raised = _pythonhook(ui, repo, name, hname, cmd, args, throw) |
7416
196b05a548d0
hooks: restore io correctly on exception
Jesse Long <jesse@virtualpostman.co.za>
parents:
7280
diff
changeset
|
204 elif cmd.startswith('python:'): |
9332
872d49dd577a
hook: fix full path imports on Windows (issue1779)
Steve Borho <steve@borho.org>
parents:
8366
diff
changeset
|
205 if cmd.count(':') >= 2: |
872d49dd577a
hook: fix full path imports on Windows (issue1779)
Steve Borho <steve@borho.org>
parents:
8366
diff
changeset
|
206 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
|
207 path = util.expandpath(path) |
13119
ecf7d6e0eef0
hook: fix import path handling for repo=None
Matt Mackall <mpm@selenic.com>
parents:
13118
diff
changeset
|
208 if repo: |
ecf7d6e0eef0
hook: fix import path handling for repo=None
Matt Mackall <mpm@selenic.com>
parents:
13118
diff
changeset
|
209 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
|
210 try: |
1b2b727a885f
hooks: print out more information when loading a python hook fails
Simon Heimberg <simohe@besonet.ch>
parents:
17048
diff
changeset
|
211 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
|
212 except Exception: |
1b2b727a885f
hooks: print out more information when loading a python hook fails
Simon Heimberg <simohe@besonet.ch>
parents:
17048
diff
changeset
|
213 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
|
214 raise |
7916
f779e1996e23
ability to load hooks from arbitrary python module
Alexander Solovyov <piranha@piranha.org.ua>
parents:
7787
diff
changeset
|
215 hookfn = getattr(mod, cmd) |
f779e1996e23
ability to load hooks from arbitrary python module
Alexander Solovyov <piranha@piranha.org.ua>
parents:
7787
diff
changeset
|
216 else: |
f779e1996e23
ability to load hooks from arbitrary python module
Alexander Solovyov <piranha@piranha.org.ua>
parents:
7787
diff
changeset
|
217 hookfn = cmd[7:].strip() |
26739
8429369eeb85
hook: for python hooks, also return whether an exception was raised
Siddharth Agarwal <sid0@fb.com>
parents:
26738
diff
changeset
|
218 r, raised = _pythonhook(ui, repo, name, hname, hookfn, args, |
8429369eeb85
hook: for python hooks, also return whether an exception was raised
Siddharth Agarwal <sid0@fb.com>
parents:
26738
diff
changeset
|
219 throw) |
7416
196b05a548d0
hooks: restore io correctly on exception
Jesse Long <jesse@virtualpostman.co.za>
parents:
7280
diff
changeset
|
220 else: |
26738
9abc2c921bbd
hook.runhooks: return a dict of result values
Siddharth Agarwal <sid0@fb.com>
parents:
26737
diff
changeset
|
221 r = _exthook(ui, repo, 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
|
222 raised = False |
26738
9abc2c921bbd
hook.runhooks: return a dict of result values
Siddharth Agarwal <sid0@fb.com>
parents:
26737
diff
changeset
|
223 |
26739
8429369eeb85
hook: for python hooks, also return whether an exception was raised
Siddharth Agarwal <sid0@fb.com>
parents:
26738
diff
changeset
|
224 res[hname] = r, raised |
24716
2abbf4750915
hook: forcibly flush stderr for Windows test stability
Matt Harbison <matt_harbison@yahoo.com>
parents:
23426
diff
changeset
|
225 |
2abbf4750915
hook: forcibly flush stderr for Windows test stability
Matt Harbison <matt_harbison@yahoo.com>
parents:
23426
diff
changeset
|
226 # 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
|
227 # 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
|
228 # remote side available to the client immediately. |
2abbf4750915
hook: forcibly flush stderr for Windows test stability
Matt Harbison <matt_harbison@yahoo.com>
parents:
23426
diff
changeset
|
229 sys.stderr.flush() |
7416
196b05a548d0
hooks: restore io correctly on exception
Jesse Long <jesse@virtualpostman.co.za>
parents:
7280
diff
changeset
|
230 finally: |
9658
852b1f3032d2
hook: only redirect stdout if it and stderr are valid files
Sune Foldager <cryo@cyanite.org>
parents:
9332
diff
changeset
|
231 if _redirect and oldstdout >= 0: |
852b1f3032d2
hook: only redirect stdout if it and stderr are valid files
Sune Foldager <cryo@cyanite.org>
parents:
9332
diff
changeset
|
232 os.dup2(oldstdout, stdoutno) |
7416
196b05a548d0
hooks: restore io correctly on exception
Jesse Long <jesse@virtualpostman.co.za>
parents:
7280
diff
changeset
|
233 os.close(oldstdout) |
6266
9f76df0edb7d
hook.py: fix redirections introduced by 323b9c55b328
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents:
5869
diff
changeset
|
234 |
26738
9abc2c921bbd
hook.runhooks: return a dict of result values
Siddharth Agarwal <sid0@fb.com>
parents:
26737
diff
changeset
|
235 return res |