annotate mercurial/hook.py @ 50863:264072107105

rust-status: error on non-existent files in file_set file_set here consists of the files that were explicitly specified on the command line. Erroring on them matches the behavior of Python status.
author Spencer Baugh <sbaugh@janestreet.com>
date Wed, 02 Aug 2023 10:21:18 -0400
parents 2761ce777fc4
children c642c03969ff
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 #
46819
d4ba4d51f85f contributor: change mentions of mpm to olivia
Raphaël Gomès <rgomes@octobus.net>
parents: 46493
diff changeset
3 # Copyright 2007 Olivia Mackall <olivia@selenic.com>
4622
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
44652
3cbbfd0bfc17 hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43671
diff changeset
9 import contextlib
45737
b3e8d8e4a40d hook: ignore EPIPE when flushing stdout/stderr
Mitchell Plamann <mplamann@janestreet.com>
parents: 44852
diff changeset
10 import errno
25953
d15b279ddade hook: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
11 import os
d15b279ddade hook: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
12 import sys
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 _
43089
c59eb1560c44 py3: manually import getattr where it is needed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43077
diff changeset
15 from .pycompat import getattr
25953
d15b279ddade hook: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
16 from . import (
d15b279ddade hook: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
17 demandimport,
32642
c032e137e494 py3: convert exception to bytes to pass into ui.warn()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 32614
diff changeset
18 encoding,
25953
d15b279ddade hook: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
19 error,
d15b279ddade hook: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
20 extensions,
30519
20a42325fdef py3: use pycompat.getcwd() instead of os.getcwd()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30473
diff changeset
21 pycompat,
25953
d15b279ddade hook: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
22 util,
d15b279ddade hook: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
23 )
37119
d4a2e0d5d042 procutil: bulk-replace util.std* to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36841
diff changeset
24 from .utils import (
d4a2e0d5d042 procutil: bulk-replace util.std* to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36841
diff changeset
25 procutil,
43671
664e24207728 procutil: move mainfrozen() to new resourceutil.py
Martin von Zweigbergk <martinvonz@google.com>
parents: 43503
diff changeset
26 resourceutil,
37751
483de34f23b1 hook: use stringutil.pprint instead of reinventing it
Augie Fackler <augie@google.com>
parents: 37463
diff changeset
27 stringutil,
37119
d4a2e0d5d042 procutil: bulk-replace util.std* to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36841
diff changeset
28 )
4622
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
29
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
30
38041
242eb5132203 filemerge: support specifying a python function to custom merge-tools
hindlemail <tom_hindle@sil.org>
parents: 37942
diff changeset
31 def pythonhook(ui, repo, htype, hname, funcname, args, throw):
45942
89a2afe31e82 formating: upgrade to black 20.8b1
Augie Fackler <raf@durin42.com>
parents: 45737
diff changeset
32 """call python hook. hook is callable object, looked up as
4622
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
33 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
34 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
35 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
36
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
37 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
38 unmodified commands (e.g. mercurial.commands.update) can
45942
89a2afe31e82 formating: upgrade to black 20.8b1
Augie Fackler <raf@durin42.com>
parents: 45737
diff changeset
39 be run as hooks without wrappers to convert return values."""
4622
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
40
21797
b009dd135aa0 hook: restore use of callable() since it was readded in Python 3.2
Augie Fackler <raf@durin42.com>
parents: 20548
diff changeset
41 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
42 obj = funcname
43503
313e3a279828 cleanup: remove pointless r-prefixes on double-quoted strings
Augie Fackler <augie@google.com>
parents: 43117
diff changeset
43 funcname = pycompat.sysbytes(obj.__module__ + "." + obj.__name__)
20548
5bd6a9fec103 hooks: for python hooks, consistently use __name__ etc as name, not the repr
Mads Kiilerich <madski@unity3d.com>
parents: 20547
diff changeset
44 else:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
45 d = funcname.rfind(b'.')
4622
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
46 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
47 raise error.HookLoadError(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
48 _(b'%s hook is invalid: "%s" not in a module')
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
49 % (hname, funcname)
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
50 )
4622
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
51 modname = funcname[:d]
10103
37679dbf2ee3 hook: fix bug (reuse of variable) introduced in 872d49dd577a
Sune Foldager <cryo@cyanite.org>
parents: 9851
diff changeset
52 oldpaths = sys.path
43671
664e24207728 procutil: move mainfrozen() to new resourceutil.py
Martin von Zweigbergk <martinvonz@google.com>
parents: 43503
diff changeset
53 if resourceutil.mainfrozen():
9332
872d49dd577a hook: fix full path imports on Windows (issue1779)
Steve Borho <steve@borho.org>
parents: 8366
diff changeset
54 # 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
55 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
56 if modpath and modfile:
37679dbf2ee3 hook: fix bug (reuse of variable) introduced in 872d49dd577a
Sune Foldager <cryo@cyanite.org>
parents: 9851
diff changeset
57 sys.path = sys.path[:] + [modpath]
37679dbf2ee3 hook: fix bug (reuse of variable) introduced in 872d49dd577a
Sune Foldager <cryo@cyanite.org>
parents: 9851
diff changeset
58 modname = modfile
25328
2cfb0bbf83a1 hooks: replace if-try-finally with a "with" statement
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 25184
diff changeset
59 with demandimport.deactivated():
4622
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
60 try:
36108
c4146cf4dd20 py3: use system strings when calling __import__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35357
diff changeset
61 obj = __import__(pycompat.sysstr(modname))
28109
b892e424f88c hook: don't crash on syntax errors in python hooks
Siddharth Agarwal <sid0@fb.com>
parents: 28108
diff changeset
62 except (ImportError, SyntaxError):
28078
2058e1a894f2 hook: use sys.exc_info rather than the deprecated equivalents
Siddharth Agarwal <sid0@fb.com>
parents: 27228
diff changeset
63 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
64 try:
2cfb0bbf83a1 hooks: replace if-try-finally with a "with" statement
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 25184
diff changeset
65 # extensions are loaded with hgext_ prefix
43503
313e3a279828 cleanup: remove pointless r-prefixes on double-quoted strings
Augie Fackler <augie@google.com>
parents: 43117
diff changeset
66 obj = __import__("hgext_%s" % pycompat.sysstr(modname))
28109
b892e424f88c hook: don't crash on syntax errors in python hooks
Siddharth Agarwal <sid0@fb.com>
parents: 28108
diff changeset
67 except (ImportError, SyntaxError):
28078
2058e1a894f2 hook: use sys.exc_info rather than the deprecated equivalents
Siddharth Agarwal <sid0@fb.com>
parents: 27228
diff changeset
68 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
69 if ui.tracebackflag:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
70 ui.warn(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
71 _(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
72 b'exception from first failed import '
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
73 b'attempt:\n'
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
74 )
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
75 )
25328
2cfb0bbf83a1 hooks: replace if-try-finally with a "with" statement
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 25184
diff changeset
76 ui.traceback(e1)
2cfb0bbf83a1 hooks: replace if-try-finally with a "with" statement
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 25184
diff changeset
77 if ui.tracebackflag:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
78 ui.warn(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
79 _(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
80 b'exception from second failed import '
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
81 b'attempt:\n'
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
82 )
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
83 )
25328
2cfb0bbf83a1 hooks: replace if-try-finally with a "with" statement
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 25184
diff changeset
84 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
85
37b818cad146 hook: for python hook ImportErrors, add note to run with --traceback
Siddharth Agarwal <sid0@fb.com>
parents: 28079
diff changeset
86 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
87 tracebackhint = _(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
88 b'run with --traceback for stack trace'
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
89 )
28080
37b818cad146 hook: for python hook ImportErrors, add note to run with --traceback
Siddharth Agarwal <sid0@fb.com>
parents: 28079
diff changeset
90 else:
37b818cad146 hook: for python hook ImportErrors, add note to run with --traceback
Siddharth Agarwal <sid0@fb.com>
parents: 28079
diff changeset
91 tracebackhint = None
26692
8d1cfd77b64f hook: raise a separate exception for when loading a hook fails
Siddharth Agarwal <sid0@fb.com>
parents: 26587
diff changeset
92 raise error.HookLoadError(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
93 _(b'%s hook is invalid: import of "%s" failed')
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
94 % (hname, modname),
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
95 hint=tracebackhint,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
96 )
9332
872d49dd577a hook: fix full path imports on Windows (issue1779)
Steve Borho <steve@borho.org>
parents: 8366
diff changeset
97 sys.path = oldpaths
4622
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
98 try:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
99 for p in funcname.split(b'.')[1:]:
4622
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
100 obj = getattr(obj, p)
7280
810ca383da9c remove unused variables
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 6762
diff changeset
101 except AttributeError:
26692
8d1cfd77b64f hook: raise a separate exception for when loading a hook fails
Siddharth Agarwal <sid0@fb.com>
parents: 26587
diff changeset
102 raise error.HookLoadError(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
103 _(b'%s hook is invalid: "%s" is not defined')
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
104 % (hname, funcname)
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
105 )
21797
b009dd135aa0 hook: restore use of callable() since it was readded in Python 3.2
Augie Fackler <raf@durin42.com>
parents: 20548
diff changeset
106 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
107 raise error.HookLoadError(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
108 _(b'%s hook is invalid: "%s" is not callable')
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
109 % (hname, funcname)
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
110 )
20547
9d9f8ccffead hooks: move logging of hook name to after we have found the hook
Mads Kiilerich <madski@unity3d.com>
parents: 20422
diff changeset
111
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
112 ui.note(_(b"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
113 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
114
4622
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
115 try:
35357
056a9c8813aa py3: handle keyword arguments correctly in hook.py
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34687
diff changeset
116 r = obj(ui=ui, repo=repo, hooktype=htype, **pycompat.strkwargs(args))
25660
328739ea70c3 global: mass rewrite to use modern exception syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25328
diff changeset
117 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
118 if isinstance(exc, error.Abort):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
119 ui.warn(_(b'error: %s hook failed: %s\n') % (hname, exc.args[0]))
25084
7046c7e7fcb4 hooks: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents: 24716
diff changeset
120 else:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
121 ui.warn(
43117
8ff1ecfadcd1 cleanup: join string literals that are already on one line
Martin von Zweigbergk <martinvonz@google.com>
parents: 43106
diff changeset
122 _(b'error: %s hook raised an exception: %s\n')
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
123 % (hname, stringutil.forcebytestr(exc))
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
124 )
25084
7046c7e7fcb4 hooks: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents: 24716
diff changeset
125 if throw:
4622
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
126 raise
28108
2a71d9483199 hook: for python hook exceptions, add note to run with --traceback
Siddharth Agarwal <sid0@fb.com>
parents: 28106
diff changeset
127 if not ui.tracebackflag:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
128 ui.warn(_(b'(run with --traceback for stack trace)\n'))
25084
7046c7e7fcb4 hooks: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents: 24716
diff changeset
129 ui.traceback()
26739
8429369eeb85 hook: for python hooks, also return whether an exception was raised
Siddharth Agarwal <sid0@fb.com>
parents: 26738
diff changeset
130 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
131 finally:
30975
22fbca1d11ed mercurial: switch to util.timer for all interval timings
Simon Farnsworth <simonfar@fb.com>
parents: 30519
diff changeset
132 duration = util.timer() - starttime
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
133 ui.log(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
134 b'pythonhook',
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
135 b'pythonhook-%s: %s finished in %0.2f seconds\n',
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
136 htype,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
137 funcname,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
138 duration,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
139 )
4622
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
140 if r:
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
141 if throw:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
142 raise error.HookAbort(_(b'%s hook failed') % hname)
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
143 ui.warn(_(b'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
144 return r, False
4622
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
145
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
146
31746
0fa30fbccc34 hook: provide hook type information to external hook
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 31745
diff changeset
147 def _exthook(ui, repo, htype, name, cmd, args, throw):
30975
22fbca1d11ed mercurial: switch to util.timer for all interval timings
Simon Farnsworth <simonfar@fb.com>
parents: 30519
diff changeset
148 starttime = util.timer()
7787
b8d750daadde Introduce HG_PREPEND to solve pretxn races
Matt Mackall <mpm@selenic.com>
parents: 7644
diff changeset
149 env = {}
26751
520defbc0335 hook: centralize passing HG_PENDING to external hook process
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 26739
diff changeset
150
520defbc0335 hook: centralize passing HG_PENDING to external hook process
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 26739
diff changeset
151 # 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
152 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
153 tr = repo.currenttransaction()
10695f8f3323 dirstate: don't write repo.currenttransaction to repo.dirstate if repo
Sietse Brouwer <sbbrouwer@gmail.com>
parents: 26861
diff changeset
154 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
155 if tr and tr.writepending():
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
156 env[b'HG_PENDING'] = repo.root
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
157 env[b'HG_HOOKTYPE'] = htype
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
158 env[b'HG_HOOKNAME'] = name
46492
7289eac777ec hooks: introduce a `:run-with-plain` option for hooks
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46490
diff changeset
159
46493
b910be772eb9 hooks: add a `auto` value for `hooks.*run-with-plain`
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46492
diff changeset
160 if ui.config(b'hooks', b'%s:run-with-plain' % name) == b'auto':
b910be772eb9 hooks: add a `auto` value for `hooks.*run-with-plain`
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46492
diff changeset
161 plain = ui.plain()
b910be772eb9 hooks: add a `auto` value for `hooks.*run-with-plain`
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46492
diff changeset
162 else:
b910be772eb9 hooks: add a `auto` value for `hooks.*run-with-plain`
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46492
diff changeset
163 plain = ui.configbool(b'hooks', b'%s:run-with-plain' % name)
46492
7289eac777ec hooks: introduce a `:run-with-plain` option for hooks
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46490
diff changeset
164 if plain:
7289eac777ec hooks: introduce a `:run-with-plain` option for hooks
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46490
diff changeset
165 env[b'HGPLAIN'] = b'1'
7289eac777ec hooks: introduce a `:run-with-plain` option for hooks
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46490
diff changeset
166 else:
7289eac777ec hooks: introduce a `:run-with-plain` option for hooks
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46490
diff changeset
167 env[b'HGPLAIN'] = b''
26751
520defbc0335 hook: centralize passing HG_PENDING to external hook process
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 26739
diff changeset
168
48913
f254fc73d956 global: bulk replace simple pycompat.iteritems(x) with x.items()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48875
diff changeset
169 for k, v in args.items():
44835
09da5cf44772 hooks: provide access to transaction changes for internal hooks
Joerg Sonnenberger <joerg@bec.de>
parents: 44652
diff changeset
170 # transaction changes can accumulate MBs of data, so skip it
09da5cf44772 hooks: provide access to transaction changes for internal hooks
Joerg Sonnenberger <joerg@bec.de>
parents: 44652
diff changeset
171 # for external hooks
09da5cf44772 hooks: provide access to transaction changes for internal hooks
Joerg Sonnenberger <joerg@bec.de>
parents: 44652
diff changeset
172 if k == b'changes':
09da5cf44772 hooks: provide access to transaction changes for internal hooks
Joerg Sonnenberger <joerg@bec.de>
parents: 44652
diff changeset
173 continue
21797
b009dd135aa0 hook: restore use of callable() since it was readded in Python 3.2
Augie Fackler <raf@durin42.com>
parents: 20548
diff changeset
174 if callable(v):
7787
b8d750daadde Introduce HG_PREPEND to solve pretxn races
Matt Mackall <mpm@selenic.com>
parents: 7644
diff changeset
175 v = v()
37752
63b7415e37a5 hook: also use pprint on lists for stable output on py2/3
Augie Fackler <augie@google.com>
parents: 37751
diff changeset
176 if isinstance(v, (dict, list)):
37942
32bc3815efae stringutil: flip the default of pprint() to bprefix=False
Yuya Nishihara <yuya@tcha.org>
parents: 37752
diff changeset
177 v = stringutil.pprint(v)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
178 env[b'HG_' + k.upper()] = v
7787
b8d750daadde Introduce HG_PREPEND to solve pretxn races
Matt Mackall <mpm@selenic.com>
parents: 7644
diff changeset
179
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
180 if ui.configbool(b'hooks', b'tonative.%s' % name, False):
38723
f9b2d996ffa5 hook: only print the note about native cmd translation if it actually changes
Matt Harbison <matt_harbison@yahoo.com>
parents: 38722
diff changeset
181 oldcmd = cmd
38629
38dfd308fe9d hook: add support for disabling the shell to native command translation
Matt Harbison <matt_harbison@yahoo.com>
parents: 38628
diff changeset
182 cmd = procutil.shelltonative(cmd, env)
38723
f9b2d996ffa5 hook: only print the note about native cmd translation if it actually changes
Matt Harbison <matt_harbison@yahoo.com>
parents: 38722
diff changeset
183 if cmd != oldcmd:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
184 ui.note(_(b'converting hook "%s" to native\n') % name)
38484
e9e61fbac787 hooks: allow Unix style environment variables on external Windows hooks
Matt Harbison <matt_harbison@yahoo.com>
parents: 38041
diff changeset
185
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
186 ui.note(_(b"running hook %s: %s\n") % (name, cmd))
38484
e9e61fbac787 hooks: allow Unix style environment variables on external Windows hooks
Matt Harbison <matt_harbison@yahoo.com>
parents: 38041
diff changeset
187
5869
2c565b9598b8 hooks: fix pre- and post- hooks specified in .hg/hgrc
Matt Mackall <mpm@selenic.com>
parents: 5833
diff changeset
188 if repo:
2c565b9598b8 hooks: fix pre- and post- hooks specified in .hg/hgrc
Matt Mackall <mpm@selenic.com>
parents: 5833
diff changeset
189 cwd = repo.root
2c565b9598b8 hooks: fix pre- and post- hooks specified in .hg/hgrc
Matt Mackall <mpm@selenic.com>
parents: 5833
diff changeset
190 else:
39818
24e493ec2229 py3: rename pycompat.getcwd() to encoding.getcwd() (API)
Matt Harbison <matt_harbison@yahoo.com>
parents: 38723
diff changeset
191 cwd = encoding.getcwd()
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
192 r = ui.system(cmd, environ=env, cwd=cwd, blockedtag=b'exthook-%s' % (name,))
18671
1c305128e5b9 blackbox: logs python and extension hooks via ui.log()
Durham Goode <durham@fb.com>
parents: 18111
diff changeset
193
50325
2761ce777fc4 hooks: invalidate the repo after the hooks
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48913
diff changeset
194 if repo is not None and repo.currentwlock() is None:
2761ce777fc4 hooks: invalidate the repo after the hooks
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48913
diff changeset
195 repo.invalidatedirstate()
2761ce777fc4 hooks: invalidate the repo after the hooks
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48913
diff changeset
196 if repo is not None and repo.currentlock() is None:
2761ce777fc4 hooks: invalidate the repo after the hooks
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48913
diff changeset
197 repo.invalidate()
2761ce777fc4 hooks: invalidate the repo after the hooks
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48913
diff changeset
198
30975
22fbca1d11ed mercurial: switch to util.timer for all interval timings
Simon Farnsworth <simonfar@fb.com>
parents: 30519
diff changeset
199 duration = util.timer() - starttime
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
200 ui.log(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
201 b'exthook',
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
202 b'exthook-%s: %s finished in %0.2f seconds\n',
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
203 name,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
204 cmd,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
205 duration,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
206 )
4622
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
207 if r:
37463
bbd240f81ac5 procutil: make explainexit() simply return a message (API)
Yuya Nishihara <yuya@tcha.org>
parents: 37120
diff changeset
208 desc = procutil.explainexit(r)
4622
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
209 if throw:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
210 raise error.HookAbort(_(b'%s hook %s') % (name, desc))
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
211 ui.warn(_(b'warning: %s hook %s\n') % (name, desc))
4622
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
212 return r
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
213
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
214
28938
ea1fec3e9aba hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 28937
diff changeset
215 # 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
216 _fromuntrusted = object()
ea1fec3e9aba hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 28937
diff changeset
217
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
218
15896
30c34fde40cc hooks: prioritize run order of hooks
Matt Zuba <matt.zuba@goodwillaz.org>
parents: 15512
diff changeset
219 def _allhooks(ui):
28937
3112c5e18835 hook: split config reading further
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 28936
diff changeset
220 """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
221 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
222 # 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
223 # 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
224 # 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
225 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
226 for name, value in untrustedhooks.items():
44828
50416d3d4b65 py3: change default priority and length used for sorting hooks to be compatible with python 3
Charles Chamberlain <cchamberlain@janestreet.com>
parents: 44652
diff changeset
227 trustedvalue = hooks.get(name, ((), (), name, _fromuntrusted))
28938
ea1fec3e9aba hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 28937
diff changeset
228 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
229 (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
230 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
231 # (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
232 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
233
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
234
28938
ea1fec3e9aba hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 28937
diff changeset
235 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
236 """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
237 hooks = {}
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
238 for name, cmd in ui.configitems(b'hooks', untrusted=_untrusted):
46490
86b019899737 hooks: forbid ':' in hook name
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46137
diff changeset
239 if (
86b019899737 hooks: forbid ':' in hook name
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46137
diff changeset
240 name.startswith(b'priority.')
86b019899737 hooks: forbid ':' in hook name
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46137
diff changeset
241 or name.startswith(b'tonative.')
86b019899737 hooks: forbid ':' in hook name
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46137
diff changeset
242 or b':' in name
86b019899737 hooks: forbid ':' in hook name
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46137
diff changeset
243 ):
38629
38dfd308fe9d hook: add support for disabling the shell to native command translation
Matt Harbison <matt_harbison@yahoo.com>
parents: 38628
diff changeset
244 continue
38dfd308fe9d hook: add support for disabling the shell to native command translation
Matt Harbison <matt_harbison@yahoo.com>
parents: 38628
diff changeset
245
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
246 priority = ui.configint(b'hooks', b'priority.%s' % name, 0)
44828
50416d3d4b65 py3: change default priority and length used for sorting hooks to be compatible with python 3
Charles Chamberlain <cchamberlain@janestreet.com>
parents: 44652
diff changeset
247 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
248 return hooks
15896
30c34fde40cc hooks: prioritize run order of hooks
Matt Zuba <matt.zuba@goodwillaz.org>
parents: 15512
diff changeset
249
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
250
5833
323b9c55b328 hook: redirect stdout to stderr for ssh and http servers
Matt Mackall <mpm@selenic.com>
parents: 4622
diff changeset
251 _redirect = False
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
252
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
253
5833
323b9c55b328 hook: redirect stdout to stderr for ssh and http servers
Matt Mackall <mpm@selenic.com>
parents: 4622
diff changeset
254 def redirect(state):
6266
9f76df0edb7d hook.py: fix redirections introduced by 323b9c55b328
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5869
diff changeset
255 global _redirect
5833
323b9c55b328 hook: redirect stdout to stderr for ssh and http servers
Matt Mackall <mpm@selenic.com>
parents: 4622
diff changeset
256 _redirect = state
323b9c55b328 hook: redirect stdout to stderr for ssh and http servers
Matt Mackall <mpm@selenic.com>
parents: 4622
diff changeset
257
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
258
34687
e79b6300d97c hook: add a 'hashook' function to test for hook existence
Boris Feld <boris.feld@octobus.net>
parents: 32897
diff changeset
259 def hashook(ui, htype):
e79b6300d97c hook: add a 'hashook' function to test for hook existence
Boris Feld <boris.feld@octobus.net>
parents: 32897
diff changeset
260 """return True if a hook is configured for 'htype'"""
e79b6300d97c hook: add a 'hashook' function to test for hook existence
Boris Feld <boris.feld@octobus.net>
parents: 32897
diff changeset
261 if not ui.callhooks:
e79b6300d97c hook: add a 'hashook' function to test for hook existence
Boris Feld <boris.feld@octobus.net>
parents: 32897
diff changeset
262 return False
e79b6300d97c hook: add a 'hashook' function to test for hook existence
Boris Feld <boris.feld@octobus.net>
parents: 32897
diff changeset
263 for hname, cmd in _allhooks(ui):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
264 if hname.split(b'.')[0] == htype and cmd:
34687
e79b6300d97c hook: add a 'hashook' function to test for hook existence
Boris Feld <boris.feld@octobus.net>
parents: 32897
diff changeset
265 return True
e79b6300d97c hook: add a 'hashook' function to test for hook existence
Boris Feld <boris.feld@octobus.net>
parents: 32897
diff changeset
266 return False
e79b6300d97c hook: add a 'hashook' function to test for hook existence
Boris Feld <boris.feld@octobus.net>
parents: 32897
diff changeset
267
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
268
31745
33504b54863e hook: use 'htype' in 'hook'
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 31744
diff changeset
269 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
270 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
271 return False
15d4d475de9e ui: add a variable to control whether hooks should be called
Idan Kamara <idankk86@gmail.com>
parents: 15896
diff changeset
272
26737
a930d66a04af hook: factor out determination of hooks from running them
Siddharth Agarwal <sid0@fb.com>
parents: 26692
diff changeset
273 hooks = []
a930d66a04af hook: factor out determination of hooks from running them
Siddharth Agarwal <sid0@fb.com>
parents: 26692
diff changeset
274 for hname, cmd in _allhooks(ui):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
275 if hname.split(b'.')[0] == htype and cmd:
26737
a930d66a04af hook: factor out determination of hooks from running them
Siddharth Agarwal <sid0@fb.com>
parents: 26692
diff changeset
276 hooks.append((hname, cmd))
a930d66a04af hook: factor out determination of hooks from running them
Siddharth Agarwal <sid0@fb.com>
parents: 26692
diff changeset
277
31745
33504b54863e hook: use 'htype' in 'hook'
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 31744
diff changeset
278 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
279 r = False
9abc2c921bbd hook.runhooks: return a dict of result values
Siddharth Agarwal <sid0@fb.com>
parents: 26737
diff changeset
280 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
281 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
282 return r
26737
a930d66a04af hook: factor out determination of hooks from running them
Siddharth Agarwal <sid0@fb.com>
parents: 26692
diff changeset
283
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
284
44652
3cbbfd0bfc17 hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43671
diff changeset
285 @contextlib.contextmanager
3cbbfd0bfc17 hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43671
diff changeset
286 def redirect_stdio():
3cbbfd0bfc17 hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43671
diff changeset
287 """Redirects stdout to stderr, if possible."""
3cbbfd0bfc17 hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43671
diff changeset
288
3cbbfd0bfc17 hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43671
diff changeset
289 oldstdout = -1
3cbbfd0bfc17 hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43671
diff changeset
290 try:
3cbbfd0bfc17 hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43671
diff changeset
291 if _redirect:
3cbbfd0bfc17 hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43671
diff changeset
292 try:
3cbbfd0bfc17 hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43671
diff changeset
293 stdoutno = procutil.stdout.fileno()
3cbbfd0bfc17 hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43671
diff changeset
294 stderrno = procutil.stderr.fileno()
3cbbfd0bfc17 hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43671
diff changeset
295 # temporarily redirect stdout to stderr, if possible
3cbbfd0bfc17 hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43671
diff changeset
296 if stdoutno >= 0 and stderrno >= 0:
3cbbfd0bfc17 hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43671
diff changeset
297 procutil.stdout.flush()
3cbbfd0bfc17 hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43671
diff changeset
298 oldstdout = os.dup(stdoutno)
3cbbfd0bfc17 hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43671
diff changeset
299 os.dup2(stderrno, stdoutno)
3cbbfd0bfc17 hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43671
diff changeset
300 except (OSError, AttributeError):
3cbbfd0bfc17 hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43671
diff changeset
301 # files seem to be bogus, give up on redirecting (WSGI, etc)
3cbbfd0bfc17 hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43671
diff changeset
302 pass
3cbbfd0bfc17 hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43671
diff changeset
303
3cbbfd0bfc17 hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43671
diff changeset
304 yield
3cbbfd0bfc17 hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43671
diff changeset
305
3cbbfd0bfc17 hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43671
diff changeset
306 finally:
3cbbfd0bfc17 hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43671
diff changeset
307 # The stderr is fully buffered on Windows when connected to a pipe.
3cbbfd0bfc17 hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43671
diff changeset
308 # A forcible flush is required to make small stderr data in the
3cbbfd0bfc17 hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43671
diff changeset
309 # remote side available to the client immediately.
45737
b3e8d8e4a40d hook: ignore EPIPE when flushing stdout/stderr
Mitchell Plamann <mplamann@janestreet.com>
parents: 44852
diff changeset
310 try:
b3e8d8e4a40d hook: ignore EPIPE when flushing stdout/stderr
Mitchell Plamann <mplamann@janestreet.com>
parents: 44852
diff changeset
311 procutil.stderr.flush()
b3e8d8e4a40d hook: ignore EPIPE when flushing stdout/stderr
Mitchell Plamann <mplamann@janestreet.com>
parents: 44852
diff changeset
312 except IOError as err:
b3e8d8e4a40d hook: ignore EPIPE when flushing stdout/stderr
Mitchell Plamann <mplamann@janestreet.com>
parents: 44852
diff changeset
313 if err.errno not in (errno.EPIPE, errno.EIO, errno.EBADF):
b3e8d8e4a40d hook: ignore EPIPE when flushing stdout/stderr
Mitchell Plamann <mplamann@janestreet.com>
parents: 44852
diff changeset
314 raise error.StdioError(err)
44652
3cbbfd0bfc17 hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43671
diff changeset
315
3cbbfd0bfc17 hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43671
diff changeset
316 if _redirect and oldstdout >= 0:
45737
b3e8d8e4a40d hook: ignore EPIPE when flushing stdout/stderr
Mitchell Plamann <mplamann@janestreet.com>
parents: 44852
diff changeset
317 try:
b3e8d8e4a40d hook: ignore EPIPE when flushing stdout/stderr
Mitchell Plamann <mplamann@janestreet.com>
parents: 44852
diff changeset
318 procutil.stdout.flush() # write hook output to stderr fd
b3e8d8e4a40d hook: ignore EPIPE when flushing stdout/stderr
Mitchell Plamann <mplamann@janestreet.com>
parents: 44852
diff changeset
319 except IOError as err:
b3e8d8e4a40d hook: ignore EPIPE when flushing stdout/stderr
Mitchell Plamann <mplamann@janestreet.com>
parents: 44852
diff changeset
320 if err.errno not in (errno.EPIPE, errno.EIO, errno.EBADF):
b3e8d8e4a40d hook: ignore EPIPE when flushing stdout/stderr
Mitchell Plamann <mplamann@janestreet.com>
parents: 44852
diff changeset
321 raise error.StdioError(err)
44652
3cbbfd0bfc17 hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43671
diff changeset
322 os.dup2(oldstdout, stdoutno)
3cbbfd0bfc17 hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43671
diff changeset
323 os.close(oldstdout)
3cbbfd0bfc17 hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43671
diff changeset
324
3cbbfd0bfc17 hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43671
diff changeset
325
31744
5678496659e9 hook: use 'htype' in 'runhooks'
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 31743
diff changeset
326 def runhooks(ui, repo, htype, hooks, throw=False, **args):
32897
799db2af824c py3: convert keys of kwargs back to bytes using pycompat.byteskwargs()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 32642
diff changeset
327 args = pycompat.byteskwargs(args)
26738
9abc2c921bbd hook.runhooks: return a dict of result values
Siddharth Agarwal <sid0@fb.com>
parents: 26737
diff changeset
328 res = {}
5833
323b9c55b328 hook: redirect stdout to stderr for ssh and http servers
Matt Mackall <mpm@selenic.com>
parents: 4622
diff changeset
329
44652
3cbbfd0bfc17 hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43671
diff changeset
330 with redirect_stdio():
26737
a930d66a04af hook: factor out determination of hooks from running them
Siddharth Agarwal <sid0@fb.com>
parents: 26692
diff changeset
331 for hname, cmd in hooks:
28938
ea1fec3e9aba hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 28937
diff changeset
332 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
333 if throw:
ea1fec3e9aba hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 28937
diff changeset
334 raise error.HookAbort(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
335 _(b'untrusted hook %s not executed') % hname,
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
336 hint=_(b"see 'hg help config.trusted'"),
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
337 )
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
338 ui.warn(_(b'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
339 r = 1
ea1fec3e9aba hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 28937
diff changeset
340 raised = False
ea1fec3e9aba hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 28937
diff changeset
341 elif callable(cmd):
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
342 r, raised = pythonhook(ui, repo, htype, hname, cmd, args, throw)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
343 elif cmd.startswith(b'python:'):
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
344 if cmd.count(b':') >= 2:
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
345 path, cmd = cmd[7:].rsplit(b':', 1)
13118
789e0fa2fcea hook: assume relative path to hook is given from repo root
Alexander Solovyov <alexander@solovyov.net>
parents: 11469
diff changeset
346 path = util.expandpath(path)
13119
ecf7d6e0eef0 hook: fix import path handling for repo=None
Matt Mackall <mpm@selenic.com>
parents: 13118
diff changeset
347 if repo:
ecf7d6e0eef0 hook: fix import path handling for repo=None
Matt Mackall <mpm@selenic.com>
parents: 13118
diff changeset
348 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
349 try:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
350 mod = extensions.loadpath(path, b'hghook.%s' % hname)
17217
1b2b727a885f hooks: print out more information when loading a python hook fails
Simon Heimberg <simohe@besonet.ch>
parents: 17048
diff changeset
351 except Exception:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
352 ui.write(_(b"loading %s hook failed:\n") % hname)
17217
1b2b727a885f hooks: print out more information when loading a python hook fails
Simon Heimberg <simohe@besonet.ch>
parents: 17048
diff changeset
353 raise
7916
f779e1996e23 ability to load hooks from arbitrary python module
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7787
diff changeset
354 hookfn = getattr(mod, cmd)
f779e1996e23 ability to load hooks from arbitrary python module
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7787
diff changeset
355 else:
f779e1996e23 ability to load hooks from arbitrary python module
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7787
diff changeset
356 hookfn = cmd[7:].strip()
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
357 r, raised = pythonhook(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
358 ui, repo, htype, hname, hookfn, args, throw
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
359 )
7416
196b05a548d0 hooks: restore io correctly on exception
Jesse Long <jesse@virtualpostman.co.za>
parents: 7280
diff changeset
360 else:
31746
0fa30fbccc34 hook: provide hook type information to external hook
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 31745
diff changeset
361 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
362 raised = False
26738
9abc2c921bbd hook.runhooks: return a dict of result values
Siddharth Agarwal <sid0@fb.com>
parents: 26737
diff changeset
363
26739
8429369eeb85 hook: for python hooks, also return whether an exception was raised
Siddharth Agarwal <sid0@fb.com>
parents: 26738
diff changeset
364 res[hname] = r, raised
6266
9f76df0edb7d hook.py: fix redirections introduced by 323b9c55b328
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5869
diff changeset
365
26738
9abc2c921bbd hook.runhooks: return a dict of result values
Siddharth Agarwal <sid0@fb.com>
parents: 26737
diff changeset
366 return res