annotate mercurial/hook.py @ 26739:8429369eeb85

hook: for python hooks, also return whether an exception was raised The hook code treats python hooks raising an exception and returning True as the exact same. This is OK for hooks themselves, but other code that wants to invoke external code using the same underlying code is a bit more interested in making a distinction.
author Siddharth Agarwal <sid0@fb.com>
date Wed, 14 Oct 2015 16:27:10 -0700
parents 9abc2c921bbd
children 520defbc0335
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
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
25e572394f5c Update license to GPLv2+
Matt Mackall <mpm@selenic.com>
parents: 10103
diff changeset
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 = {}
b8d750daadde Introduce HG_PREPEND to solve pretxn races
Matt Mackall <mpm@selenic.com>
parents: 7644
diff changeset
121 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
122 if callable(v):
7787
b8d750daadde Introduce HG_PREPEND to solve pretxn races
Matt Mackall <mpm@selenic.com>
parents: 7644
diff changeset
123 v = v()
13207
1775382ff833 hooks: sort any dictionaries set in the environment
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 13119
diff changeset
124 if isinstance(v, dict):
1775382ff833 hooks: sort any dictionaries set in the environment
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 13119
diff changeset
125 # 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
126 # implementations
1775382ff833 hooks: sort any dictionaries set in the environment
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 13119
diff changeset
127 v = ('{' +
1775382ff833 hooks: sort any dictionaries set in the environment
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 13119
diff changeset
128 ', '.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
129 '}')
7787
b8d750daadde Introduce HG_PREPEND to solve pretxn races
Matt Mackall <mpm@selenic.com>
parents: 7644
diff changeset
130 env['HG_' + k.upper()] = v
b8d750daadde Introduce HG_PREPEND to solve pretxn races
Matt Mackall <mpm@selenic.com>
parents: 7644
diff changeset
131
5869
2c565b9598b8 hooks: fix pre- and post- hooks specified in .hg/hgrc
Matt Mackall <mpm@selenic.com>
parents: 5833
diff changeset
132 if repo:
2c565b9598b8 hooks: fix pre- and post- hooks specified in .hg/hgrc
Matt Mackall <mpm@selenic.com>
parents: 5833
diff changeset
133 cwd = repo.root
2c565b9598b8 hooks: fix pre- and post- hooks specified in .hg/hgrc
Matt Mackall <mpm@selenic.com>
parents: 5833
diff changeset
134 else:
2c565b9598b8 hooks: fix pre- and post- hooks specified in .hg/hgrc
Matt Mackall <mpm@selenic.com>
parents: 5833
diff changeset
135 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
136 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
137
1c305128e5b9 blackbox: logs python and extension hooks via ui.log()
Durham Goode <durham@fb.com>
parents: 18111
diff changeset
138 duration = time.time() - starttime
18691
4f485bd68f1d blackbox: do not translate the log messages
Durham Goode <durham@fb.com>
parents: 18671
diff changeset
139 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
140 name, cmd, duration)
4622
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
141 if r:
14234
600e64004eb5 rename explain_exit to explainexit
Adrian Buehlmann <adrian@cadifra.com>
parents: 13207
diff changeset
142 desc, r = util.explainexit(r)
4622
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
143 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
144 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
145 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
146 return r
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
147
15896
30c34fde40cc hooks: prioritize run order of hooks
Matt Zuba <matt.zuba@goodwillaz.org>
parents: 15512
diff changeset
148 def _allhooks(ui):
30c34fde40cc hooks: prioritize run order of hooks
Matt Zuba <matt.zuba@goodwillaz.org>
parents: 15512
diff changeset
149 hooks = []
30c34fde40cc hooks: prioritize run order of hooks
Matt Zuba <matt.zuba@goodwillaz.org>
parents: 15512
diff changeset
150 for name, cmd in ui.configitems('hooks'):
30c34fde40cc hooks: prioritize run order of hooks
Matt Zuba <matt.zuba@goodwillaz.org>
parents: 15512
diff changeset
151 if not name.startswith('priority'):
30c34fde40cc hooks: prioritize run order of hooks
Matt Zuba <matt.zuba@goodwillaz.org>
parents: 15512
diff changeset
152 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
153 hooks.append((-priority, len(hooks), name, cmd))
30c34fde40cc hooks: prioritize run order of hooks
Matt Zuba <matt.zuba@goodwillaz.org>
parents: 15512
diff changeset
154 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
155
5833
323b9c55b328 hook: redirect stdout to stderr for ssh and http servers
Matt Mackall <mpm@selenic.com>
parents: 4622
diff changeset
156 _redirect = False
323b9c55b328 hook: redirect stdout to stderr for ssh and http servers
Matt Mackall <mpm@selenic.com>
parents: 4622
diff changeset
157 def redirect(state):
6266
9f76df0edb7d hook.py: fix redirections introduced by 323b9c55b328
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5869
diff changeset
158 global _redirect
5833
323b9c55b328 hook: redirect stdout to stderr for ssh and http servers
Matt Mackall <mpm@selenic.com>
parents: 4622
diff changeset
159 _redirect = state
323b9c55b328 hook: redirect stdout to stderr for ssh and http servers
Matt Mackall <mpm@selenic.com>
parents: 4622
diff changeset
160
4622
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
161 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
162 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
163 return False
15d4d475de9e ui: add a variable to control whether hooks should be called
Idan Kamara <idankk86@gmail.com>
parents: 15896
diff changeset
164
26737
a930d66a04af hook: factor out determination of hooks from running them
Siddharth Agarwal <sid0@fb.com>
parents: 26692
diff changeset
165 hooks = []
a930d66a04af hook: factor out determination of hooks from running them
Siddharth Agarwal <sid0@fb.com>
parents: 26692
diff changeset
166 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
167 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
168 hooks.append((hname, cmd))
a930d66a04af hook: factor out determination of hooks from running them
Siddharth Agarwal <sid0@fb.com>
parents: 26692
diff changeset
169
26738
9abc2c921bbd hook.runhooks: return a dict of result values
Siddharth Agarwal <sid0@fb.com>
parents: 26737
diff changeset
170 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
171 r = False
9abc2c921bbd hook.runhooks: return a dict of result values
Siddharth Agarwal <sid0@fb.com>
parents: 26737
diff changeset
172 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
173 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
174 return r
26737
a930d66a04af hook: factor out determination of hooks from running them
Siddharth Agarwal <sid0@fb.com>
parents: 26692
diff changeset
175
a930d66a04af hook: factor out determination of hooks from running them
Siddharth Agarwal <sid0@fb.com>
parents: 26692
diff changeset
176 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
177 res = {}
9658
852b1f3032d2 hook: only redirect stdout if it and stderr are valid files
Sune Foldager <cryo@cyanite.org>
parents: 9332
diff changeset
178 oldstdout = -1
5833
323b9c55b328 hook: redirect stdout to stderr for ssh and http servers
Matt Mackall <mpm@selenic.com>
parents: 4622
diff changeset
179
7416
196b05a548d0 hooks: restore io correctly on exception
Jesse Long <jesse@virtualpostman.co.za>
parents: 7280
diff changeset
180 try:
26737
a930d66a04af hook: factor out determination of hooks from running them
Siddharth Agarwal <sid0@fb.com>
parents: 26692
diff changeset
181 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
182 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
183 try:
6180dcb29ec5 hooks: delay I/O redirection until we actually run a hook (issue3711)
Matt Mackall <mpm@selenic.com>
parents: 17428
diff changeset
184 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
185 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
186 # 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
187 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
188 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
189 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
190 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
191 except (OSError, AttributeError):
2c63896783e3 hooks: be even more forgiven of non-fd descriptors (issue3711)
Matt Mackall <mpm@selenic.com>
parents: 17963
diff changeset
192 # 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
193 pass
6180dcb29ec5 hooks: delay I/O redirection until we actually run a hook (issue3711)
Matt Mackall <mpm@selenic.com>
parents: 17428
diff changeset
194
21797
b009dd135aa0 hook: restore use of callable() since it was readded in Python 3.2
Augie Fackler <raf@durin42.com>
parents: 20548
diff changeset
195 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
196 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
197 elif cmd.startswith('python:'):
9332
872d49dd577a hook: fix full path imports on Windows (issue1779)
Steve Borho <steve@borho.org>
parents: 8366
diff changeset
198 if cmd.count(':') >= 2:
872d49dd577a hook: fix full path imports on Windows (issue1779)
Steve Borho <steve@borho.org>
parents: 8366
diff changeset
199 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
200 path = util.expandpath(path)
13119
ecf7d6e0eef0 hook: fix import path handling for repo=None
Matt Mackall <mpm@selenic.com>
parents: 13118
diff changeset
201 if repo:
ecf7d6e0eef0 hook: fix import path handling for repo=None
Matt Mackall <mpm@selenic.com>
parents: 13118
diff changeset
202 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
203 try:
1b2b727a885f hooks: print out more information when loading a python hook fails
Simon Heimberg <simohe@besonet.ch>
parents: 17048
diff changeset
204 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
205 except Exception:
1b2b727a885f hooks: print out more information when loading a python hook fails
Simon Heimberg <simohe@besonet.ch>
parents: 17048
diff changeset
206 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
207 raise
7916
f779e1996e23 ability to load hooks from arbitrary python module
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7787
diff changeset
208 hookfn = getattr(mod, cmd)
f779e1996e23 ability to load hooks from arbitrary python module
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7787
diff changeset
209 else:
f779e1996e23 ability to load hooks from arbitrary python module
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7787
diff changeset
210 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
211 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
212 throw)
7416
196b05a548d0 hooks: restore io correctly on exception
Jesse Long <jesse@virtualpostman.co.za>
parents: 7280
diff changeset
213 else:
26738
9abc2c921bbd hook.runhooks: return a dict of result values
Siddharth Agarwal <sid0@fb.com>
parents: 26737
diff changeset
214 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
215 raised = False
26738
9abc2c921bbd hook.runhooks: return a dict of result values
Siddharth Agarwal <sid0@fb.com>
parents: 26737
diff changeset
216
26739
8429369eeb85 hook: for python hooks, also return whether an exception was raised
Siddharth Agarwal <sid0@fb.com>
parents: 26738
diff changeset
217 res[hname] = r, raised
24716
2abbf4750915 hook: forcibly flush stderr for Windows test stability
Matt Harbison <matt_harbison@yahoo.com>
parents: 23426
diff changeset
218
2abbf4750915 hook: forcibly flush stderr for Windows test stability
Matt Harbison <matt_harbison@yahoo.com>
parents: 23426
diff changeset
219 # 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
220 # 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
221 # 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
222 sys.stderr.flush()
7416
196b05a548d0 hooks: restore io correctly on exception
Jesse Long <jesse@virtualpostman.co.za>
parents: 7280
diff changeset
223 finally:
9658
852b1f3032d2 hook: only redirect stdout if it and stderr are valid files
Sune Foldager <cryo@cyanite.org>
parents: 9332
diff changeset
224 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
225 os.dup2(oldstdout, stdoutno)
7416
196b05a548d0 hooks: restore io correctly on exception
Jesse Long <jesse@virtualpostman.co.za>
parents: 7280
diff changeset
226 os.close(oldstdout)
6266
9f76df0edb7d hook.py: fix redirections introduced by 323b9c55b328
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5869
diff changeset
227
26738
9abc2c921bbd hook.runhooks: return a dict of result values
Siddharth Agarwal <sid0@fb.com>
parents: 26737
diff changeset
228 return res