Mercurial > hg
annotate mercurial/hook.py @ 51424:3cee8706f53b
phases: directly update the phase sets in advanceboundary
This is similar to what we do in retractboundary. There is no need to invalidate
the cache if we have everything at hand to update it.
author | Pierre-Yves David <pierre-yves.david@octobus.net> |
---|---|
date | Fri, 23 Feb 2024 06:37:25 +0100 |
parents | 18c8c18993f0 |
children | f4733654f144 |
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 |
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 _ |
d15b279ddade
hook: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
15 from . import ( |
d15b279ddade
hook: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
16 demandimport, |
32642
c032e137e494
py3: convert exception to bytes to pass into ui.warn()
Pulkit Goyal <7895pulkit@gmail.com>
parents:
32614
diff
changeset
|
17 encoding, |
25953
d15b279ddade
hook: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
18 error, |
d15b279ddade
hook: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
19 extensions, |
30519
20a42325fdef
py3: use pycompat.getcwd() instead of os.getcwd()
Pulkit Goyal <7895pulkit@gmail.com>
parents:
30473
diff
changeset
|
20 pycompat, |
25953
d15b279ddade
hook: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
21 util, |
d15b279ddade
hook: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
22 ) |
37119
d4a2e0d5d042
procutil: bulk-replace util.std* to point to new module
Yuya Nishihara <yuya@tcha.org>
parents:
36841
diff
changeset
|
23 from .utils import ( |
d4a2e0d5d042
procutil: bulk-replace util.std* to point to new module
Yuya Nishihara <yuya@tcha.org>
parents:
36841
diff
changeset
|
24 procutil, |
43671
664e24207728
procutil: move mainfrozen() to new resourceutil.py
Martin von Zweigbergk <martinvonz@google.com>
parents:
43503
diff
changeset
|
25 resourceutil, |
37751
483de34f23b1
hook: use stringutil.pprint instead of reinventing it
Augie Fackler <augie@google.com>
parents:
37463
diff
changeset
|
26 stringutil, |
37119
d4a2e0d5d042
procutil: bulk-replace util.std* to point to new module
Yuya Nishihara <yuya@tcha.org>
parents:
36841
diff
changeset
|
27 ) |
4622
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
28 |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
29 |
38041
242eb5132203
filemerge: support specifying a python function to custom merge-tools
hindlemail <tom_hindle@sil.org>
parents:
37942
diff
changeset
|
30 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
|
31 """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
|
32 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
|
33 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
|
34 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
|
35 |
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
36 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
|
37 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
|
38 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
|
39 |
21797
b009dd135aa0
hook: restore use of callable() since it was readded in Python 3.2
Augie Fackler <raf@durin42.com>
parents:
20548
diff
changeset
|
40 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
|
41 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
|
42 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
|
43 else: |
50923
c642c03969ff
dynamic-import: use sysstr for importing extension and others
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50325
diff
changeset
|
44 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
|
45 d = funcname.rfind('.') |
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') |
50923
c642c03969ff
dynamic-import: use sysstr for importing extension and others
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50325
diff
changeset
|
49 % (hname, stringutil.forcebytestr(funcname)) |
43076
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 |
50923
c642c03969ff
dynamic-import: use sysstr for importing extension and others
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50325
diff
changeset
|
92 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
|
93 msg %= ( |
c642c03969ff
dynamic-import: use sysstr for importing extension and others
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50325
diff
changeset
|
94 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
|
95 stringutil.forcebytestr(modname), |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
96 ) |
50923
c642c03969ff
dynamic-import: use sysstr for importing extension and others
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50325
diff
changeset
|
97 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
|
98 sys.path = oldpaths |
4622
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
99 try: |
50923
c642c03969ff
dynamic-import: use sysstr for importing extension and others
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50325
diff
changeset
|
100 for p in funcname.split('.')[1:]: |
4622
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
101 obj = getattr(obj, p) |
7280
810ca383da9c
remove unused variables
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
6762
diff
changeset
|
102 except AttributeError: |
26692
8d1cfd77b64f
hook: raise a separate exception for when loading a hook fails
Siddharth Agarwal <sid0@fb.com>
parents:
26587
diff
changeset
|
103 raise error.HookLoadError( |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
104 _(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
|
105 % (hname, stringutil.forcebytestr(funcname)) |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
106 ) |
21797
b009dd135aa0
hook: restore use of callable() since it was readded in Python 3.2
Augie Fackler <raf@durin42.com>
parents:
20548
diff
changeset
|
107 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
|
108 raise error.HookLoadError( |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
109 _(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
|
110 % (hname, stringutil.forcebytestr(funcname)) |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
111 ) |
20547
9d9f8ccffead
hooks: move logging of hook name to after we have found the hook
Mads Kiilerich <madski@unity3d.com>
parents:
20422
diff
changeset
|
112 |
50923
c642c03969ff
dynamic-import: use sysstr for importing extension and others
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50325
diff
changeset
|
113 ui.note( |
c642c03969ff
dynamic-import: use sysstr for importing extension and others
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50325
diff
changeset
|
114 _(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
|
115 ) |
30975
22fbca1d11ed
mercurial: switch to util.timer for all interval timings
Simon Farnsworth <simonfar@fb.com>
parents:
30519
diff
changeset
|
116 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
|
117 |
4622
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
118 try: |
35357
056a9c8813aa
py3: handle keyword arguments correctly in hook.py
Pulkit Goyal <7895pulkit@gmail.com>
parents:
34687
diff
changeset
|
119 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
|
120 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
|
121 if isinstance(exc, error.Abort): |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
122 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
|
123 else: |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
124 ui.warn( |
43117
8ff1ecfadcd1
cleanup: join string literals that are already on one line
Martin von Zweigbergk <martinvonz@google.com>
parents:
43106
diff
changeset
|
125 _(b'error: %s hook raised an exception: %s\n') |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
126 % (hname, stringutil.forcebytestr(exc)) |
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
127 ) |
25084
7046c7e7fcb4
hooks: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
24716
diff
changeset
|
128 if throw: |
4622
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
129 raise |
28108
2a71d9483199
hook: for python hook exceptions, add note to run with --traceback
Siddharth Agarwal <sid0@fb.com>
parents:
28106
diff
changeset
|
130 if not ui.tracebackflag: |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
131 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
|
132 ui.traceback() |
26739
8429369eeb85
hook: for python hooks, also return whether an exception was raised
Siddharth Agarwal <sid0@fb.com>
parents:
26738
diff
changeset
|
133 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
|
134 finally: |
30975
22fbca1d11ed
mercurial: switch to util.timer for all interval timings
Simon Farnsworth <simonfar@fb.com>
parents:
30519
diff
changeset
|
135 duration = util.timer() - starttime |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
136 ui.log( |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
137 b'pythonhook', |
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
138 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
|
139 htype, |
50923
c642c03969ff
dynamic-import: use sysstr for importing extension and others
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50325
diff
changeset
|
140 stringutil.forcebytestr(funcname), |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
141 duration, |
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
142 ) |
4622
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
143 if r: |
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
144 if throw: |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
145 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
|
146 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
|
147 return r, False |
4622
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
148 |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
149 |
31746
0fa30fbccc34
hook: provide hook type information to external hook
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
31745
diff
changeset
|
150 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
|
151 starttime = util.timer() |
7787
b8d750daadde
Introduce HG_PREPEND to solve pretxn races
Matt Mackall <mpm@selenic.com>
parents:
7644
diff
changeset
|
152 env = {} |
26751
520defbc0335
hook: centralize passing HG_PENDING to external hook process
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
26739
diff
changeset
|
153 |
520defbc0335
hook: centralize passing HG_PENDING to external hook process
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
26739
diff
changeset
|
154 # 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
|
155 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
|
156 tr = repo.currenttransaction() |
10695f8f3323
dirstate: don't write repo.currenttransaction to repo.dirstate if repo
Sietse Brouwer <sbbrouwer@gmail.com>
parents:
26861
diff
changeset
|
157 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
|
158 if tr and tr.writepending(): |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
159 env[b'HG_PENDING'] = repo.root |
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
160 env[b'HG_HOOKTYPE'] = htype |
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
161 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
|
162 |
46493
b910be772eb9
hooks: add a `auto` value for `hooks.*run-with-plain`
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
46492
diff
changeset
|
163 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
|
164 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
|
165 else: |
b910be772eb9
hooks: add a `auto` value for `hooks.*run-with-plain`
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
46492
diff
changeset
|
166 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
|
167 if plain: |
7289eac777ec
hooks: introduce a `:run-with-plain` option for hooks
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
46490
diff
changeset
|
168 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
|
169 else: |
7289eac777ec
hooks: introduce a `:run-with-plain` option for hooks
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
46490
diff
changeset
|
170 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
|
171 |
48913
f254fc73d956
global: bulk replace simple pycompat.iteritems(x) with x.items()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
48875
diff
changeset
|
172 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
|
173 # 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
|
174 # for external hooks |
09da5cf44772
hooks: provide access to transaction changes for internal hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
44652
diff
changeset
|
175 if k == b'changes': |
09da5cf44772
hooks: provide access to transaction changes for internal hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
44652
diff
changeset
|
176 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
|
177 if callable(v): |
7787
b8d750daadde
Introduce HG_PREPEND to solve pretxn races
Matt Mackall <mpm@selenic.com>
parents:
7644
diff
changeset
|
178 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
|
179 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
|
180 v = stringutil.pprint(v) |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
181 env[b'HG_' + k.upper()] = v |
7787
b8d750daadde
Introduce HG_PREPEND to solve pretxn races
Matt Mackall <mpm@selenic.com>
parents:
7644
diff
changeset
|
182 |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
183 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
|
184 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
|
185 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
|
186 if cmd != oldcmd: |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
187 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
|
188 |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
189 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
|
190 |
5869
2c565b9598b8
hooks: fix pre- and post- hooks specified in .hg/hgrc
Matt Mackall <mpm@selenic.com>
parents:
5833
diff
changeset
|
191 if repo: |
2c565b9598b8
hooks: fix pre- and post- hooks specified in .hg/hgrc
Matt Mackall <mpm@selenic.com>
parents:
5833
diff
changeset
|
192 cwd = repo.root |
2c565b9598b8
hooks: fix pre- and post- hooks specified in .hg/hgrc
Matt Mackall <mpm@selenic.com>
parents:
5833
diff
changeset
|
193 else: |
39818
24e493ec2229
py3: rename pycompat.getcwd() to encoding.getcwd() (API)
Matt Harbison <matt_harbison@yahoo.com>
parents:
38723
diff
changeset
|
194 cwd = encoding.getcwd() |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
195 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
|
196 |
50325
2761ce777fc4
hooks: invalidate the repo after the hooks
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48913
diff
changeset
|
197 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
|
198 repo.invalidatedirstate() |
2761ce777fc4
hooks: invalidate the repo after the hooks
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48913
diff
changeset
|
199 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
|
200 repo.invalidate() |
2761ce777fc4
hooks: invalidate the repo after the hooks
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48913
diff
changeset
|
201 |
30975
22fbca1d11ed
mercurial: switch to util.timer for all interval timings
Simon Farnsworth <simonfar@fb.com>
parents:
30519
diff
changeset
|
202 duration = util.timer() - starttime |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
203 ui.log( |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
204 b'exthook', |
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
205 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
|
206 name, |
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
207 cmd, |
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
208 duration, |
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
209 ) |
4622
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
210 if r: |
37463
bbd240f81ac5
procutil: make explainexit() simply return a message (API)
Yuya Nishihara <yuya@tcha.org>
parents:
37120
diff
changeset
|
211 desc = procutil.explainexit(r) |
4622
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
212 if throw: |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
213 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
|
214 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
|
215 return r |
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
216 |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
217 |
28938
ea1fec3e9aba
hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
28937
diff
changeset
|
218 # 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
|
219 _fromuntrusted = object() |
ea1fec3e9aba
hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
28937
diff
changeset
|
220 |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
221 |
15896
30c34fde40cc
hooks: prioritize run order of hooks
Matt Zuba <matt.zuba@goodwillaz.org>
parents:
15512
diff
changeset
|
222 def _allhooks(ui): |
28937
3112c5e18835
hook: split config reading further
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
28936
diff
changeset
|
223 """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
|
224 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
|
225 # 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
|
226 # 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
|
227 # 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
|
228 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
|
229 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
|
230 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
|
231 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
|
232 (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
|
233 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
|
234 # (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
|
235 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
|
236 |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
237 |
28938
ea1fec3e9aba
hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
28937
diff
changeset
|
238 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
|
239 """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
|
240 hooks = {} |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
241 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
|
242 if ( |
86b019899737
hooks: forbid ':' in hook name
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
46137
diff
changeset
|
243 name.startswith(b'priority.') |
86b019899737
hooks: forbid ':' in hook name
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
46137
diff
changeset
|
244 or name.startswith(b'tonative.') |
86b019899737
hooks: forbid ':' in hook name
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
46137
diff
changeset
|
245 or b':' in name |
86b019899737
hooks: forbid ':' in hook name
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
46137
diff
changeset
|
246 ): |
38629
38dfd308fe9d
hook: add support for disabling the shell to native command translation
Matt Harbison <matt_harbison@yahoo.com>
parents:
38628
diff
changeset
|
247 continue |
38dfd308fe9d
hook: add support for disabling the shell to native command translation
Matt Harbison <matt_harbison@yahoo.com>
parents:
38628
diff
changeset
|
248 |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
249 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
|
250 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
|
251 return hooks |
15896
30c34fde40cc
hooks: prioritize run order of hooks
Matt Zuba <matt.zuba@goodwillaz.org>
parents:
15512
diff
changeset
|
252 |
43076
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 _redirect = False |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
255 |
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
256 |
5833
323b9c55b328
hook: redirect stdout to stderr for ssh and http servers
Matt Mackall <mpm@selenic.com>
parents:
4622
diff
changeset
|
257 def redirect(state): |
6266
9f76df0edb7d
hook.py: fix redirections introduced by 323b9c55b328
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents:
5869
diff
changeset
|
258 global _redirect |
5833
323b9c55b328
hook: redirect stdout to stderr for ssh and http servers
Matt Mackall <mpm@selenic.com>
parents:
4622
diff
changeset
|
259 _redirect = state |
323b9c55b328
hook: redirect stdout to stderr for ssh and http servers
Matt Mackall <mpm@selenic.com>
parents:
4622
diff
changeset
|
260 |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
261 |
34687
e79b6300d97c
hook: add a 'hashook' function to test for hook existence
Boris Feld <boris.feld@octobus.net>
parents:
32897
diff
changeset
|
262 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
|
263 """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
|
264 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
|
265 return False |
e79b6300d97c
hook: add a 'hashook' function to test for hook existence
Boris Feld <boris.feld@octobus.net>
parents:
32897
diff
changeset
|
266 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
|
267 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
|
268 return True |
e79b6300d97c
hook: add a 'hashook' function to test for hook existence
Boris Feld <boris.feld@octobus.net>
parents:
32897
diff
changeset
|
269 return False |
e79b6300d97c
hook: add a 'hashook' function to test for hook existence
Boris Feld <boris.feld@octobus.net>
parents:
32897
diff
changeset
|
270 |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
271 |
31745
33504b54863e
hook: use 'htype' in 'hook'
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
31744
diff
changeset
|
272 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
|
273 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
|
274 return False |
15d4d475de9e
ui: add a variable to control whether hooks should be called
Idan Kamara <idankk86@gmail.com>
parents:
15896
diff
changeset
|
275 |
26737
a930d66a04af
hook: factor out determination of hooks from running them
Siddharth Agarwal <sid0@fb.com>
parents:
26692
diff
changeset
|
276 hooks = [] |
a930d66a04af
hook: factor out determination of hooks from running them
Siddharth Agarwal <sid0@fb.com>
parents:
26692
diff
changeset
|
277 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
|
278 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
|
279 hooks.append((hname, cmd)) |
a930d66a04af
hook: factor out determination of hooks from running them
Siddharth Agarwal <sid0@fb.com>
parents:
26692
diff
changeset
|
280 |
31745
33504b54863e
hook: use 'htype' in 'hook'
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
31744
diff
changeset
|
281 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
|
282 r = False |
9abc2c921bbd
hook.runhooks: return a dict of result values
Siddharth Agarwal <sid0@fb.com>
parents:
26737
diff
changeset
|
283 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
|
284 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
|
285 return r |
26737
a930d66a04af
hook: factor out determination of hooks from running them
Siddharth Agarwal <sid0@fb.com>
parents:
26692
diff
changeset
|
286 |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
287 |
44652
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
288 @contextlib.contextmanager |
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
289 def redirect_stdio(): |
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
290 """Redirects stdout to stderr, if possible.""" |
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
291 |
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
292 oldstdout = -1 |
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
293 try: |
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
294 if _redirect: |
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
295 try: |
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
296 stdoutno = procutil.stdout.fileno() |
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
297 stderrno = procutil.stderr.fileno() |
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
298 # 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
|
299 if stdoutno >= 0 and stderrno >= 0: |
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
300 procutil.stdout.flush() |
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
301 oldstdout = os.dup(stdoutno) |
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
302 os.dup2(stderrno, stdoutno) |
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
303 except (OSError, AttributeError): |
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
304 # 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
|
305 pass |
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
306 |
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
307 yield |
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
308 |
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
309 finally: |
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
310 # 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
|
311 # 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
|
312 # 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
|
313 try: |
b3e8d8e4a40d
hook: ignore EPIPE when flushing stdout/stderr
Mitchell Plamann <mplamann@janestreet.com>
parents:
44852
diff
changeset
|
314 procutil.stderr.flush() |
b3e8d8e4a40d
hook: ignore EPIPE when flushing stdout/stderr
Mitchell Plamann <mplamann@janestreet.com>
parents:
44852
diff
changeset
|
315 except IOError as err: |
b3e8d8e4a40d
hook: ignore EPIPE when flushing stdout/stderr
Mitchell Plamann <mplamann@janestreet.com>
parents:
44852
diff
changeset
|
316 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
|
317 raise error.StdioError(err) |
44652
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
318 |
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
319 if _redirect and oldstdout >= 0: |
45737
b3e8d8e4a40d
hook: ignore EPIPE when flushing stdout/stderr
Mitchell Plamann <mplamann@janestreet.com>
parents:
44852
diff
changeset
|
320 try: |
b3e8d8e4a40d
hook: ignore EPIPE when flushing stdout/stderr
Mitchell Plamann <mplamann@janestreet.com>
parents:
44852
diff
changeset
|
321 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
|
322 except IOError as err: |
b3e8d8e4a40d
hook: ignore EPIPE when flushing stdout/stderr
Mitchell Plamann <mplamann@janestreet.com>
parents:
44852
diff
changeset
|
323 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
|
324 raise error.StdioError(err) |
44652
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
325 os.dup2(oldstdout, stdoutno) |
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
326 os.close(oldstdout) |
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
327 |
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
328 |
31744
5678496659e9
hook: use 'htype' in 'runhooks'
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
31743
diff
changeset
|
329 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
|
330 args = pycompat.byteskwargs(args) |
26738
9abc2c921bbd
hook.runhooks: return a dict of result values
Siddharth Agarwal <sid0@fb.com>
parents:
26737
diff
changeset
|
331 res = {} |
5833
323b9c55b328
hook: redirect stdout to stderr for ssh and http servers
Matt Mackall <mpm@selenic.com>
parents:
4622
diff
changeset
|
332 |
44652
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
333 with redirect_stdio(): |
26737
a930d66a04af
hook: factor out determination of hooks from running them
Siddharth Agarwal <sid0@fb.com>
parents:
26692
diff
changeset
|
334 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
|
335 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
|
336 if throw: |
ea1fec3e9aba
hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
28937
diff
changeset
|
337 raise error.HookAbort( |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
338 _(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
|
339 hint=_(b"see 'hg help config.trusted'"), |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
340 ) |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
341 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
|
342 r = 1 |
ea1fec3e9aba
hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
28937
diff
changeset
|
343 raised = False |
ea1fec3e9aba
hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
28937
diff
changeset
|
344 elif callable(cmd): |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
345 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
|
346 elif cmd.startswith(b'python:'): |
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
347 if cmd.count(b':') >= 2: |
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
348 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
|
349 path = util.expandpath(path) |
13119
ecf7d6e0eef0
hook: fix import path handling for repo=None
Matt Mackall <mpm@selenic.com>
parents:
13118
diff
changeset
|
350 if repo: |
ecf7d6e0eef0
hook: fix import path handling for repo=None
Matt Mackall <mpm@selenic.com>
parents:
13118
diff
changeset
|
351 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
|
352 try: |
50923
c642c03969ff
dynamic-import: use sysstr for importing extension and others
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50325
diff
changeset
|
353 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
|
354 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
|
355 except Exception: |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
356 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
|
357 raise |
50923
c642c03969ff
dynamic-import: use sysstr for importing extension and others
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50325
diff
changeset
|
358 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
|
359 else: |
f779e1996e23
ability to load hooks from arbitrary python module
Alexander Solovyov <piranha@piranha.org.ua>
parents:
7787
diff
changeset
|
360 hookfn = cmd[7:].strip() |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
361 r, raised = pythonhook( |
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
362 ui, repo, htype, hname, hookfn, args, throw |
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
363 ) |
7416
196b05a548d0
hooks: restore io correctly on exception
Jesse Long <jesse@virtualpostman.co.za>
parents:
7280
diff
changeset
|
364 else: |
31746
0fa30fbccc34
hook: provide hook type information to external hook
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
31745
diff
changeset
|
365 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
|
366 raised = False |
26738
9abc2c921bbd
hook.runhooks: return a dict of result values
Siddharth Agarwal <sid0@fb.com>
parents:
26737
diff
changeset
|
367 |
26739
8429369eeb85
hook: for python hooks, also return whether an exception was raised
Siddharth Agarwal <sid0@fb.com>
parents:
26738
diff
changeset
|
368 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
|
369 |
26738
9abc2c921bbd
hook.runhooks: return a dict of result values
Siddharth Agarwal <sid0@fb.com>
parents:
26737
diff
changeset
|
370 return res |