Mercurial > hg
annotate mercurial/hook.py @ 52164:e01e84e5e426
rust-revlog: add a Rust-only `InnerRevlog`
This mirrors the Python `InnerRevlog` and will be used in a future patch
to replace said Python implementation. This allows us to start doing more
things in pure Rust, in particular reading and writing operations.
A lot of changes have to be introduced all at once, it wouldn't be very
useful to separate this patch IMO since all of them are either interlocked
or only useful with the rest.
author | Raphaël Gomès <rgomes@octobus.net> |
---|---|
date | Thu, 10 Oct 2024 10:34:51 +0200 |
parents | f4733654f144 |
children |
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 | 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 |
51863
f4733654f144
typing: add `from __future__ import annotations` to most files
Matt Harbison <matt_harbison@yahoo.com>
parents:
50929
diff
changeset
|
8 from __future__ import annotations |
25953
d15b279ddade
hook: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
9 |
44652
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
10 import contextlib |
45737
b3e8d8e4a40d
hook: ignore EPIPE when flushing stdout/stderr
Mitchell Plamann <mplamann@janestreet.com>
parents:
44852
diff
changeset
|
11 import errno |
25953
d15b279ddade
hook: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
12 import os |
d15b279ddade
hook: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
13 import sys |
d15b279ddade
hook: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
14 |
d15b279ddade
hook: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
15 from .i18n import _ |
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 |
50923
c642c03969ff
dynamic-import: use sysstr for importing extension and others
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50325
diff
changeset
|
43 funcname = 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: |
50923
c642c03969ff
dynamic-import: use sysstr for importing extension and others
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50325
diff
changeset
|
45 funcname = pycompat.sysstr(funcname) |
c642c03969ff
dynamic-import: use sysstr for importing extension and others
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50325
diff
changeset
|
46 d = funcname.rfind('.') |
4622
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
47 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
|
48 raise error.HookLoadError( |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
49 _(b'%s hook is invalid: "%s" not in a module') |
50923
c642c03969ff
dynamic-import: use sysstr for importing extension and others
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50325
diff
changeset
|
50 % (hname, stringutil.forcebytestr(funcname)) |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
51 ) |
4622
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
52 modname = funcname[:d] |
10103
37679dbf2ee3
hook: fix bug (reuse of variable) introduced in 872d49dd577a
Sune Foldager <cryo@cyanite.org>
parents:
9851
diff
changeset
|
53 oldpaths = sys.path |
43671
664e24207728
procutil: move mainfrozen() to new resourceutil.py
Martin von Zweigbergk <martinvonz@google.com>
parents:
43503
diff
changeset
|
54 if resourceutil.mainfrozen(): |
9332
872d49dd577a
hook: fix full path imports on Windows (issue1779)
Steve Borho <steve@borho.org>
parents:
8366
diff
changeset
|
55 # 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
|
56 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
|
57 if modpath and modfile: |
37679dbf2ee3
hook: fix bug (reuse of variable) introduced in 872d49dd577a
Sune Foldager <cryo@cyanite.org>
parents:
9851
diff
changeset
|
58 sys.path = sys.path[:] + [modpath] |
37679dbf2ee3
hook: fix bug (reuse of variable) introduced in 872d49dd577a
Sune Foldager <cryo@cyanite.org>
parents:
9851
diff
changeset
|
59 modname = modfile |
25328
2cfb0bbf83a1
hooks: replace if-try-finally with a "with" statement
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
25184
diff
changeset
|
60 with demandimport.deactivated(): |
4622
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
61 try: |
36108
c4146cf4dd20
py3: use system strings when calling __import__
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35357
diff
changeset
|
62 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
|
63 except (ImportError, SyntaxError): |
28078
2058e1a894f2
hook: use sys.exc_info rather than the deprecated equivalents
Siddharth Agarwal <sid0@fb.com>
parents:
27228
diff
changeset
|
64 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
|
65 try: |
2cfb0bbf83a1
hooks: replace if-try-finally with a "with" statement
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
25184
diff
changeset
|
66 # 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
|
67 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
|
68 except (ImportError, SyntaxError): |
28078
2058e1a894f2
hook: use sys.exc_info rather than the deprecated equivalents
Siddharth Agarwal <sid0@fb.com>
parents:
27228
diff
changeset
|
69 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
|
70 if ui.tracebackflag: |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
71 ui.warn( |
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
72 _( |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
73 b'exception from first failed import ' |
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
74 b'attempt:\n' |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
75 ) |
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
76 ) |
25328
2cfb0bbf83a1
hooks: replace if-try-finally with a "with" statement
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
25184
diff
changeset
|
77 ui.traceback(e1) |
2cfb0bbf83a1
hooks: replace if-try-finally with a "with" statement
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
25184
diff
changeset
|
78 if ui.tracebackflag: |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
79 ui.warn( |
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
80 _( |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
81 b'exception from second failed import ' |
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
82 b'attempt:\n' |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
83 ) |
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
84 ) |
25328
2cfb0bbf83a1
hooks: replace if-try-finally with a "with" statement
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
25184
diff
changeset
|
85 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
|
86 |
37b818cad146
hook: for python hook ImportErrors, add note to run with --traceback
Siddharth Agarwal <sid0@fb.com>
parents:
28079
diff
changeset
|
87 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
|
88 tracebackhint = _( |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
89 b'run with --traceback for stack trace' |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
90 ) |
28080
37b818cad146
hook: for python hook ImportErrors, add note to run with --traceback
Siddharth Agarwal <sid0@fb.com>
parents:
28079
diff
changeset
|
91 else: |
37b818cad146
hook: for python hook ImportErrors, add note to run with --traceback
Siddharth Agarwal <sid0@fb.com>
parents:
28079
diff
changeset
|
92 tracebackhint = None |
50923
c642c03969ff
dynamic-import: use sysstr for importing extension and others
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50325
diff
changeset
|
93 msg = _(b'%s hook is invalid: import of "%s" failed') |
c642c03969ff
dynamic-import: use sysstr for importing extension and others
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50325
diff
changeset
|
94 msg %= ( |
c642c03969ff
dynamic-import: use sysstr for importing extension and others
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50325
diff
changeset
|
95 stringutil.forcebytestr(hname), |
c642c03969ff
dynamic-import: use sysstr for importing extension and others
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50325
diff
changeset
|
96 stringutil.forcebytestr(modname), |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
97 ) |
50923
c642c03969ff
dynamic-import: use sysstr for importing extension and others
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50325
diff
changeset
|
98 raise error.HookLoadError(msg, hint=tracebackhint) |
9332
872d49dd577a
hook: fix full path imports on Windows (issue1779)
Steve Borho <steve@borho.org>
parents:
8366
diff
changeset
|
99 sys.path = oldpaths |
4622
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
100 try: |
50923
c642c03969ff
dynamic-import: use sysstr for importing extension and others
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50325
diff
changeset
|
101 for p in funcname.split('.')[1:]: |
4622
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
102 obj = getattr(obj, p) |
7280
810ca383da9c
remove unused variables
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
6762
diff
changeset
|
103 except AttributeError: |
26692
8d1cfd77b64f
hook: raise a separate exception for when loading a hook fails
Siddharth Agarwal <sid0@fb.com>
parents:
26587
diff
changeset
|
104 raise error.HookLoadError( |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
105 _(b'%s hook is invalid: "%s" is not defined') |
50923
c642c03969ff
dynamic-import: use sysstr for importing extension and others
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50325
diff
changeset
|
106 % (hname, stringutil.forcebytestr(funcname)) |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
107 ) |
21797
b009dd135aa0
hook: restore use of callable() since it was readded in Python 3.2
Augie Fackler <raf@durin42.com>
parents:
20548
diff
changeset
|
108 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
|
109 raise error.HookLoadError( |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
110 _(b'%s hook is invalid: "%s" is not callable') |
50923
c642c03969ff
dynamic-import: use sysstr for importing extension and others
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50325
diff
changeset
|
111 % (hname, stringutil.forcebytestr(funcname)) |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
112 ) |
20547
9d9f8ccffead
hooks: move logging of hook name to after we have found the hook
Mads Kiilerich <madski@unity3d.com>
parents:
20422
diff
changeset
|
113 |
50923
c642c03969ff
dynamic-import: use sysstr for importing extension and others
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50325
diff
changeset
|
114 ui.note( |
c642c03969ff
dynamic-import: use sysstr for importing extension and others
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50325
diff
changeset
|
115 _(b"calling hook %s: %s\n") % (hname, stringutil.forcebytestr(funcname)) |
c642c03969ff
dynamic-import: use sysstr for importing extension and others
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50325
diff
changeset
|
116 ) |
30975
22fbca1d11ed
mercurial: switch to util.timer for all interval timings
Simon Farnsworth <simonfar@fb.com>
parents:
30519
diff
changeset
|
117 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
|
118 |
4622
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
119 try: |
35357
056a9c8813aa
py3: handle keyword arguments correctly in hook.py
Pulkit Goyal <7895pulkit@gmail.com>
parents:
34687
diff
changeset
|
120 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
|
121 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
|
122 if isinstance(exc, error.Abort): |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
123 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
|
124 else: |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
125 ui.warn( |
43117
8ff1ecfadcd1
cleanup: join string literals that are already on one line
Martin von Zweigbergk <martinvonz@google.com>
parents:
43106
diff
changeset
|
126 _(b'error: %s hook raised an exception: %s\n') |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
127 % (hname, stringutil.forcebytestr(exc)) |
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
128 ) |
25084
7046c7e7fcb4
hooks: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
24716
diff
changeset
|
129 if throw: |
4622
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
130 raise |
28108
2a71d9483199
hook: for python hook exceptions, add note to run with --traceback
Siddharth Agarwal <sid0@fb.com>
parents:
28106
diff
changeset
|
131 if not ui.tracebackflag: |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
132 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
|
133 ui.traceback() |
26739
8429369eeb85
hook: for python hooks, also return whether an exception was raised
Siddharth Agarwal <sid0@fb.com>
parents:
26738
diff
changeset
|
134 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
|
135 finally: |
30975
22fbca1d11ed
mercurial: switch to util.timer for all interval timings
Simon Farnsworth <simonfar@fb.com>
parents:
30519
diff
changeset
|
136 duration = util.timer() - starttime |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
137 ui.log( |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
138 b'pythonhook', |
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
139 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
|
140 htype, |
50923
c642c03969ff
dynamic-import: use sysstr for importing extension and others
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50325
diff
changeset
|
141 stringutil.forcebytestr(funcname), |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
142 duration, |
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
143 ) |
4622
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
144 if r: |
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
145 if throw: |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
146 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
|
147 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
|
148 return r, False |
4622
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
149 |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
150 |
31746
0fa30fbccc34
hook: provide hook type information to external hook
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
31745
diff
changeset
|
151 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
|
152 starttime = util.timer() |
7787
b8d750daadde
Introduce HG_PREPEND to solve pretxn races
Matt Mackall <mpm@selenic.com>
parents:
7644
diff
changeset
|
153 env = {} |
26751
520defbc0335
hook: centralize passing HG_PENDING to external hook process
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
26739
diff
changeset
|
154 |
520defbc0335
hook: centralize passing HG_PENDING to external hook process
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
26739
diff
changeset
|
155 # 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
|
156 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
|
157 tr = repo.currenttransaction() |
10695f8f3323
dirstate: don't write repo.currenttransaction to repo.dirstate if repo
Sietse Brouwer <sbbrouwer@gmail.com>
parents:
26861
diff
changeset
|
158 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
|
159 if tr and tr.writepending(): |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
160 env[b'HG_PENDING'] = repo.root |
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
161 env[b'HG_HOOKTYPE'] = htype |
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
162 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
|
163 |
46493
b910be772eb9
hooks: add a `auto` value for `hooks.*run-with-plain`
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
46492
diff
changeset
|
164 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
|
165 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
|
166 else: |
b910be772eb9
hooks: add a `auto` value for `hooks.*run-with-plain`
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
46492
diff
changeset
|
167 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
|
168 if plain: |
7289eac777ec
hooks: introduce a `:run-with-plain` option for hooks
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
46490
diff
changeset
|
169 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
|
170 else: |
7289eac777ec
hooks: introduce a `:run-with-plain` option for hooks
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
46490
diff
changeset
|
171 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
|
172 |
48913
f254fc73d956
global: bulk replace simple pycompat.iteritems(x) with x.items()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
48875
diff
changeset
|
173 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
|
174 # 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
|
175 # for external hooks |
09da5cf44772
hooks: provide access to transaction changes for internal hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
44652
diff
changeset
|
176 if k == b'changes': |
09da5cf44772
hooks: provide access to transaction changes for internal hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
44652
diff
changeset
|
177 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
|
178 if callable(v): |
7787
b8d750daadde
Introduce HG_PREPEND to solve pretxn races
Matt Mackall <mpm@selenic.com>
parents:
7644
diff
changeset
|
179 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
|
180 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
|
181 v = stringutil.pprint(v) |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
182 env[b'HG_' + k.upper()] = v |
7787
b8d750daadde
Introduce HG_PREPEND to solve pretxn races
Matt Mackall <mpm@selenic.com>
parents:
7644
diff
changeset
|
183 |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
184 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
|
185 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
|
186 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
|
187 if cmd != oldcmd: |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
188 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
|
189 |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
190 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
|
191 |
5869
2c565b9598b8
hooks: fix pre- and post- hooks specified in .hg/hgrc
Matt Mackall <mpm@selenic.com>
parents:
5833
diff
changeset
|
192 if repo: |
2c565b9598b8
hooks: fix pre- and post- hooks specified in .hg/hgrc
Matt Mackall <mpm@selenic.com>
parents:
5833
diff
changeset
|
193 cwd = repo.root |
2c565b9598b8
hooks: fix pre- and post- hooks specified in .hg/hgrc
Matt Mackall <mpm@selenic.com>
parents:
5833
diff
changeset
|
194 else: |
39818
24e493ec2229
py3: rename pycompat.getcwd() to encoding.getcwd() (API)
Matt Harbison <matt_harbison@yahoo.com>
parents:
38723
diff
changeset
|
195 cwd = encoding.getcwd() |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
196 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
|
197 |
50325
2761ce777fc4
hooks: invalidate the repo after the hooks
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48913
diff
changeset
|
198 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
|
199 repo.invalidatedirstate() |
2761ce777fc4
hooks: invalidate the repo after the hooks
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48913
diff
changeset
|
200 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
|
201 repo.invalidate() |
2761ce777fc4
hooks: invalidate the repo after the hooks
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48913
diff
changeset
|
202 |
30975
22fbca1d11ed
mercurial: switch to util.timer for all interval timings
Simon Farnsworth <simonfar@fb.com>
parents:
30519
diff
changeset
|
203 duration = util.timer() - starttime |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
204 ui.log( |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
205 b'exthook', |
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
206 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
|
207 name, |
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
208 cmd, |
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
209 duration, |
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
210 ) |
4622
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
211 if r: |
37463
bbd240f81ac5
procutil: make explainexit() simply return a message (API)
Yuya Nishihara <yuya@tcha.org>
parents:
37120
diff
changeset
|
212 desc = procutil.explainexit(r) |
4622
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
213 if throw: |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
214 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
|
215 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
|
216 return r |
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
217 |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
218 |
28938
ea1fec3e9aba
hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
28937
diff
changeset
|
219 # 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
|
220 _fromuntrusted = object() |
ea1fec3e9aba
hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
28937
diff
changeset
|
221 |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
222 |
15896
30c34fde40cc
hooks: prioritize run order of hooks
Matt Zuba <matt.zuba@goodwillaz.org>
parents:
15512
diff
changeset
|
223 def _allhooks(ui): |
28937
3112c5e18835
hook: split config reading further
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
28936
diff
changeset
|
224 """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
|
225 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
|
226 # 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
|
227 # 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
|
228 # 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
|
229 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
|
230 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
|
231 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
|
232 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
|
233 (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
|
234 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
|
235 # (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
|
236 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
|
237 |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
238 |
28938
ea1fec3e9aba
hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
28937
diff
changeset
|
239 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
|
240 """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
|
241 hooks = {} |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
242 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
|
243 if ( |
86b019899737
hooks: forbid ':' in hook name
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
46137
diff
changeset
|
244 name.startswith(b'priority.') |
86b019899737
hooks: forbid ':' in hook name
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
46137
diff
changeset
|
245 or name.startswith(b'tonative.') |
86b019899737
hooks: forbid ':' in hook name
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
46137
diff
changeset
|
246 or b':' in name |
86b019899737
hooks: forbid ':' in hook name
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
46137
diff
changeset
|
247 ): |
38629
38dfd308fe9d
hook: add support for disabling the shell to native command translation
Matt Harbison <matt_harbison@yahoo.com>
parents:
38628
diff
changeset
|
248 continue |
38dfd308fe9d
hook: add support for disabling the shell to native command translation
Matt Harbison <matt_harbison@yahoo.com>
parents:
38628
diff
changeset
|
249 |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
250 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
|
251 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
|
252 return hooks |
15896
30c34fde40cc
hooks: prioritize run order of hooks
Matt Zuba <matt.zuba@goodwillaz.org>
parents:
15512
diff
changeset
|
253 |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
254 |
5833
323b9c55b328
hook: redirect stdout to stderr for ssh and http servers
Matt Mackall <mpm@selenic.com>
parents:
4622
diff
changeset
|
255 _redirect = False |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
256 |
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
257 |
5833
323b9c55b328
hook: redirect stdout to stderr for ssh and http servers
Matt Mackall <mpm@selenic.com>
parents:
4622
diff
changeset
|
258 def redirect(state): |
6266
9f76df0edb7d
hook.py: fix redirections introduced by 323b9c55b328
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents:
5869
diff
changeset
|
259 global _redirect |
5833
323b9c55b328
hook: redirect stdout to stderr for ssh and http servers
Matt Mackall <mpm@selenic.com>
parents:
4622
diff
changeset
|
260 _redirect = state |
323b9c55b328
hook: redirect stdout to stderr for ssh and http servers
Matt Mackall <mpm@selenic.com>
parents:
4622
diff
changeset
|
261 |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
262 |
34687
e79b6300d97c
hook: add a 'hashook' function to test for hook existence
Boris Feld <boris.feld@octobus.net>
parents:
32897
diff
changeset
|
263 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
|
264 """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
|
265 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
|
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 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
|
268 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
|
269 return True |
e79b6300d97c
hook: add a 'hashook' function to test for hook existence
Boris Feld <boris.feld@octobus.net>
parents:
32897
diff
changeset
|
270 return False |
e79b6300d97c
hook: add a 'hashook' function to test for hook existence
Boris Feld <boris.feld@octobus.net>
parents:
32897
diff
changeset
|
271 |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
272 |
31745
33504b54863e
hook: use 'htype' in 'hook'
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
31744
diff
changeset
|
273 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
|
274 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
|
275 return False |
15d4d475de9e
ui: add a variable to control whether hooks should be called
Idan Kamara <idankk86@gmail.com>
parents:
15896
diff
changeset
|
276 |
26737
a930d66a04af
hook: factor out determination of hooks from running them
Siddharth Agarwal <sid0@fb.com>
parents:
26692
diff
changeset
|
277 hooks = [] |
a930d66a04af
hook: factor out determination of hooks from running them
Siddharth Agarwal <sid0@fb.com>
parents:
26692
diff
changeset
|
278 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
|
279 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
|
280 hooks.append((hname, cmd)) |
a930d66a04af
hook: factor out determination of hooks from running them
Siddharth Agarwal <sid0@fb.com>
parents:
26692
diff
changeset
|
281 |
31745
33504b54863e
hook: use 'htype' in 'hook'
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
31744
diff
changeset
|
282 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
|
283 r = False |
9abc2c921bbd
hook.runhooks: return a dict of result values
Siddharth Agarwal <sid0@fb.com>
parents:
26737
diff
changeset
|
284 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
|
285 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
|
286 return r |
26737
a930d66a04af
hook: factor out determination of hooks from running them
Siddharth Agarwal <sid0@fb.com>
parents:
26692
diff
changeset
|
287 |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
288 |
44652
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
289 @contextlib.contextmanager |
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
290 def redirect_stdio(): |
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
291 """Redirects stdout to stderr, if possible.""" |
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
292 |
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
293 oldstdout = -1 |
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
294 try: |
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
295 if _redirect: |
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
296 try: |
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
297 stdoutno = procutil.stdout.fileno() |
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
298 stderrno = procutil.stderr.fileno() |
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
299 # 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
|
300 if stdoutno >= 0 and stderrno >= 0: |
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
301 procutil.stdout.flush() |
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
302 oldstdout = os.dup(stdoutno) |
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
303 os.dup2(stderrno, stdoutno) |
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
304 except (OSError, AttributeError): |
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
305 # 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
|
306 pass |
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
307 |
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
308 yield |
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
309 |
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
310 finally: |
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
311 # 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
|
312 # 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
|
313 # 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
|
314 try: |
b3e8d8e4a40d
hook: ignore EPIPE when flushing stdout/stderr
Mitchell Plamann <mplamann@janestreet.com>
parents:
44852
diff
changeset
|
315 procutil.stderr.flush() |
b3e8d8e4a40d
hook: ignore EPIPE when flushing stdout/stderr
Mitchell Plamann <mplamann@janestreet.com>
parents:
44852
diff
changeset
|
316 except IOError as err: |
b3e8d8e4a40d
hook: ignore EPIPE when flushing stdout/stderr
Mitchell Plamann <mplamann@janestreet.com>
parents:
44852
diff
changeset
|
317 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
|
318 raise error.StdioError(err) |
44652
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
319 |
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
320 if _redirect and oldstdout >= 0: |
45737
b3e8d8e4a40d
hook: ignore EPIPE when flushing stdout/stderr
Mitchell Plamann <mplamann@janestreet.com>
parents:
44852
diff
changeset
|
321 try: |
b3e8d8e4a40d
hook: ignore EPIPE when flushing stdout/stderr
Mitchell Plamann <mplamann@janestreet.com>
parents:
44852
diff
changeset
|
322 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
|
323 except IOError as err: |
b3e8d8e4a40d
hook: ignore EPIPE when flushing stdout/stderr
Mitchell Plamann <mplamann@janestreet.com>
parents:
44852
diff
changeset
|
324 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
|
325 raise error.StdioError(err) |
44652
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
326 os.dup2(oldstdout, stdoutno) |
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
327 os.close(oldstdout) |
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
328 |
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
329 |
31744
5678496659e9
hook: use 'htype' in 'runhooks'
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
31743
diff
changeset
|
330 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
|
331 args = pycompat.byteskwargs(args) |
26738
9abc2c921bbd
hook.runhooks: return a dict of result values
Siddharth Agarwal <sid0@fb.com>
parents:
26737
diff
changeset
|
332 res = {} |
5833
323b9c55b328
hook: redirect stdout to stderr for ssh and http servers
Matt Mackall <mpm@selenic.com>
parents:
4622
diff
changeset
|
333 |
44652
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
334 with redirect_stdio(): |
26737
a930d66a04af
hook: factor out determination of hooks from running them
Siddharth Agarwal <sid0@fb.com>
parents:
26692
diff
changeset
|
335 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
|
336 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
|
337 if throw: |
ea1fec3e9aba
hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
28937
diff
changeset
|
338 raise error.HookAbort( |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
339 _(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
|
340 hint=_(b"see 'hg help config.trusted'"), |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
341 ) |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
342 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
|
343 r = 1 |
ea1fec3e9aba
hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
28937
diff
changeset
|
344 raised = False |
ea1fec3e9aba
hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
28937
diff
changeset
|
345 elif callable(cmd): |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
346 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
|
347 elif cmd.startswith(b'python:'): |
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
348 if cmd.count(b':') >= 2: |
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
349 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
|
350 path = util.expandpath(path) |
13119
ecf7d6e0eef0
hook: fix import path handling for repo=None
Matt Mackall <mpm@selenic.com>
parents:
13118
diff
changeset
|
351 if repo: |
ecf7d6e0eef0
hook: fix import path handling for repo=None
Matt Mackall <mpm@selenic.com>
parents:
13118
diff
changeset
|
352 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
|
353 try: |
50923
c642c03969ff
dynamic-import: use sysstr for importing extension and others
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50325
diff
changeset
|
354 mod_name = 'hghook.%s' % pycompat.sysstr(hname) |
c642c03969ff
dynamic-import: use sysstr for importing extension and others
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50325
diff
changeset
|
355 mod = extensions.loadpath(path, mod_name) |
17217
1b2b727a885f
hooks: print out more information when loading a python hook fails
Simon Heimberg <simohe@besonet.ch>
parents:
17048
diff
changeset
|
356 except Exception: |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
357 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
|
358 raise |
50923
c642c03969ff
dynamic-import: use sysstr for importing extension and others
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50325
diff
changeset
|
359 hookfn = getattr(mod, pycompat.sysstr(cmd)) |
7916
f779e1996e23
ability to load hooks from arbitrary python module
Alexander Solovyov <piranha@piranha.org.ua>
parents:
7787
diff
changeset
|
360 else: |
f779e1996e23
ability to load hooks from arbitrary python module
Alexander Solovyov <piranha@piranha.org.ua>
parents:
7787
diff
changeset
|
361 hookfn = cmd[7:].strip() |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
362 r, raised = pythonhook( |
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
363 ui, repo, htype, hname, hookfn, args, throw |
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
364 ) |
7416
196b05a548d0
hooks: restore io correctly on exception
Jesse Long <jesse@virtualpostman.co.za>
parents:
7280
diff
changeset
|
365 else: |
31746
0fa30fbccc34
hook: provide hook type information to external hook
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
31745
diff
changeset
|
366 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
|
367 raised = False |
26738
9abc2c921bbd
hook.runhooks: return a dict of result values
Siddharth Agarwal <sid0@fb.com>
parents:
26737
diff
changeset
|
368 |
26739
8429369eeb85
hook: for python hooks, also return whether an exception was raised
Siddharth Agarwal <sid0@fb.com>
parents:
26738
diff
changeset
|
369 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
|
370 |
26738
9abc2c921bbd
hook.runhooks: return a dict of result values
Siddharth Agarwal <sid0@fb.com>
parents:
26737
diff
changeset
|
371 return res |