Mercurial > hg
annotate mercurial/hook.py @ 45059:79f6f9fa18c1
documentation: add some internals documentation about bid merge
This is an important algorithm that was only documented on the wiki so far.
Some update to the algorithm (and associated doc) is to expected in the future
since the bid merge algorithm is bug-ridden when it comes to file deletion comes
to play.
Differential Revision: https://phab.mercurial-scm.org/D8711
author | Pierre-Yves David <pierre-yves.david@octobus.net> |
---|---|
date | Mon, 22 Jun 2020 13:32:20 +0200 |
parents | fd3b94f1712d |
children | b3e8d8e4a40d |
rev | line source |
---|---|
4622
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1 # hook.py - hook support for mercurial |
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
2 # |
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
3 # Copyright 2007 Matt Mackall <mpm@selenic.com> |
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
4 # |
8225
46293a0c7e9f
updated license to be explicit about GPL version 2
Martin Geisler <mg@lazybytes.net>
parents:
8209
diff
changeset
|
5 # This software may be used and distributed according to the terms of the |
10263 | 6 # GNU General Public License version 2 or any later version. |
4622
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
7 |
25953
d15b279ddade
hook: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
8 from __future__ import absolute_import |
d15b279ddade
hook: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
9 |
44652
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
10 import contextlib |
25953
d15b279ddade
hook: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
11 import os |
d15b279ddade
hook: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
12 import sys |
d15b279ddade
hook: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
13 |
d15b279ddade
hook: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
14 from .i18n import _ |
43089
c59eb1560c44
py3: manually import getattr where it is needed
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43077
diff
changeset
|
15 from .pycompat import getattr |
25953
d15b279ddade
hook: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
16 from . import ( |
d15b279ddade
hook: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
17 demandimport, |
32642
c032e137e494
py3: convert exception to bytes to pass into ui.warn()
Pulkit Goyal <7895pulkit@gmail.com>
parents:
32614
diff
changeset
|
18 encoding, |
25953
d15b279ddade
hook: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
19 error, |
d15b279ddade
hook: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
20 extensions, |
30519
20a42325fdef
py3: use pycompat.getcwd() instead of os.getcwd()
Pulkit Goyal <7895pulkit@gmail.com>
parents:
30473
diff
changeset
|
21 pycompat, |
25953
d15b279ddade
hook: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
22 util, |
d15b279ddade
hook: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
23 ) |
37119
d4a2e0d5d042
procutil: bulk-replace util.std* to point to new module
Yuya Nishihara <yuya@tcha.org>
parents:
36841
diff
changeset
|
24 from .utils import ( |
d4a2e0d5d042
procutil: bulk-replace util.std* to point to new module
Yuya Nishihara <yuya@tcha.org>
parents:
36841
diff
changeset
|
25 procutil, |
43671
664e24207728
procutil: move mainfrozen() to new resourceutil.py
Martin von Zweigbergk <martinvonz@google.com>
parents:
43503
diff
changeset
|
26 resourceutil, |
37751
483de34f23b1
hook: use stringutil.pprint instead of reinventing it
Augie Fackler <augie@google.com>
parents:
37463
diff
changeset
|
27 stringutil, |
37119
d4a2e0d5d042
procutil: bulk-replace util.std* to point to new module
Yuya Nishihara <yuya@tcha.org>
parents:
36841
diff
changeset
|
28 ) |
4622
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
29 |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
30 |
38041
242eb5132203
filemerge: support specifying a python function to custom merge-tools
hindlemail <tom_hindle@sil.org>
parents:
37942
diff
changeset
|
31 def pythonhook(ui, repo, htype, hname, funcname, args, throw): |
4622
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
32 '''call python hook. hook is callable object, looked up as |
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
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 |
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
39 be run as hooks without wrappers to convert return values.''' |
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
40 |
21797
b009dd135aa0
hook: restore use of callable() since it was readded in Python 3.2
Augie Fackler <raf@durin42.com>
parents:
20548
diff
changeset
|
41 if callable(funcname): |
20548
5bd6a9fec103
hooks: for python hooks, consistently use __name__ etc as name, not the repr
Mads Kiilerich <madski@unity3d.com>
parents:
20547
diff
changeset
|
42 obj = funcname |
43503
313e3a279828
cleanup: remove pointless r-prefixes on double-quoted strings
Augie Fackler <augie@google.com>
parents:
43117
diff
changeset
|
43 funcname = pycompat.sysbytes(obj.__module__ + "." + obj.__name__) |
20548
5bd6a9fec103
hooks: for python hooks, consistently use __name__ etc as name, not the repr
Mads Kiilerich <madski@unity3d.com>
parents:
20547
diff
changeset
|
44 else: |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
45 d = funcname.rfind(b'.') |
4622
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
46 if d == -1: |
26692
8d1cfd77b64f
hook: raise a separate exception for when loading a hook fails
Siddharth Agarwal <sid0@fb.com>
parents:
26587
diff
changeset
|
47 raise error.HookLoadError( |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
48 _(b'%s hook is invalid: "%s" not in a module') |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
49 % (hname, funcname) |
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
50 ) |
4622
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
51 modname = funcname[:d] |
10103
37679dbf2ee3
hook: fix bug (reuse of variable) introduced in 872d49dd577a
Sune Foldager <cryo@cyanite.org>
parents:
9851
diff
changeset
|
52 oldpaths = sys.path |
43671
664e24207728
procutil: move mainfrozen() to new resourceutil.py
Martin von Zweigbergk <martinvonz@google.com>
parents:
43503
diff
changeset
|
53 if resourceutil.mainfrozen(): |
9332
872d49dd577a
hook: fix full path imports on Windows (issue1779)
Steve Borho <steve@borho.org>
parents:
8366
diff
changeset
|
54 # binary installs require sys.path manipulation |
10103
37679dbf2ee3
hook: fix bug (reuse of variable) introduced in 872d49dd577a
Sune Foldager <cryo@cyanite.org>
parents:
9851
diff
changeset
|
55 modpath, modfile = os.path.split(modname) |
37679dbf2ee3
hook: fix bug (reuse of variable) introduced in 872d49dd577a
Sune Foldager <cryo@cyanite.org>
parents:
9851
diff
changeset
|
56 if modpath and modfile: |
37679dbf2ee3
hook: fix bug (reuse of variable) introduced in 872d49dd577a
Sune Foldager <cryo@cyanite.org>
parents:
9851
diff
changeset
|
57 sys.path = sys.path[:] + [modpath] |
37679dbf2ee3
hook: fix bug (reuse of variable) introduced in 872d49dd577a
Sune Foldager <cryo@cyanite.org>
parents:
9851
diff
changeset
|
58 modname = modfile |
25328
2cfb0bbf83a1
hooks: replace if-try-finally with a "with" statement
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
25184
diff
changeset
|
59 with demandimport.deactivated(): |
4622
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
60 try: |
36108
c4146cf4dd20
py3: use system strings when calling __import__
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35357
diff
changeset
|
61 obj = __import__(pycompat.sysstr(modname)) |
28109
b892e424f88c
hook: don't crash on syntax errors in python hooks
Siddharth Agarwal <sid0@fb.com>
parents:
28108
diff
changeset
|
62 except (ImportError, SyntaxError): |
28078
2058e1a894f2
hook: use sys.exc_info rather than the deprecated equivalents
Siddharth Agarwal <sid0@fb.com>
parents:
27228
diff
changeset
|
63 e1 = sys.exc_info() |
25328
2cfb0bbf83a1
hooks: replace if-try-finally with a "with" statement
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
25184
diff
changeset
|
64 try: |
2cfb0bbf83a1
hooks: replace if-try-finally with a "with" statement
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
25184
diff
changeset
|
65 # extensions are loaded with hgext_ prefix |
43503
313e3a279828
cleanup: remove pointless r-prefixes on double-quoted strings
Augie Fackler <augie@google.com>
parents:
43117
diff
changeset
|
66 obj = __import__("hgext_%s" % pycompat.sysstr(modname)) |
28109
b892e424f88c
hook: don't crash on syntax errors in python hooks
Siddharth Agarwal <sid0@fb.com>
parents:
28108
diff
changeset
|
67 except (ImportError, SyntaxError): |
28078
2058e1a894f2
hook: use sys.exc_info rather than the deprecated equivalents
Siddharth Agarwal <sid0@fb.com>
parents:
27228
diff
changeset
|
68 e2 = sys.exc_info() |
25328
2cfb0bbf83a1
hooks: replace if-try-finally with a "with" statement
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
25184
diff
changeset
|
69 if ui.tracebackflag: |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
70 ui.warn( |
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
71 _( |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
72 b'exception from first failed import ' |
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
73 b'attempt:\n' |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
74 ) |
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
75 ) |
25328
2cfb0bbf83a1
hooks: replace if-try-finally with a "with" statement
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
25184
diff
changeset
|
76 ui.traceback(e1) |
2cfb0bbf83a1
hooks: replace if-try-finally with a "with" statement
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
25184
diff
changeset
|
77 if ui.tracebackflag: |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
78 ui.warn( |
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
79 _( |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
80 b'exception from second failed import ' |
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
81 b'attempt:\n' |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
82 ) |
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
83 ) |
25328
2cfb0bbf83a1
hooks: replace if-try-finally with a "with" statement
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
25184
diff
changeset
|
84 ui.traceback(e2) |
28080
37b818cad146
hook: for python hook ImportErrors, add note to run with --traceback
Siddharth Agarwal <sid0@fb.com>
parents:
28079
diff
changeset
|
85 |
37b818cad146
hook: for python hook ImportErrors, add note to run with --traceback
Siddharth Agarwal <sid0@fb.com>
parents:
28079
diff
changeset
|
86 if not ui.tracebackflag: |
37b818cad146
hook: for python hook ImportErrors, add note to run with --traceback
Siddharth Agarwal <sid0@fb.com>
parents:
28079
diff
changeset
|
87 tracebackhint = _( |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
88 b'run with --traceback for stack trace' |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
89 ) |
28080
37b818cad146
hook: for python hook ImportErrors, add note to run with --traceback
Siddharth Agarwal <sid0@fb.com>
parents:
28079
diff
changeset
|
90 else: |
37b818cad146
hook: for python hook ImportErrors, add note to run with --traceback
Siddharth Agarwal <sid0@fb.com>
parents:
28079
diff
changeset
|
91 tracebackhint = None |
26692
8d1cfd77b64f
hook: raise a separate exception for when loading a hook fails
Siddharth Agarwal <sid0@fb.com>
parents:
26587
diff
changeset
|
92 raise error.HookLoadError( |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
93 _(b'%s hook is invalid: import of "%s" failed') |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
94 % (hname, modname), |
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
95 hint=tracebackhint, |
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
96 ) |
9332
872d49dd577a
hook: fix full path imports on Windows (issue1779)
Steve Borho <steve@borho.org>
parents:
8366
diff
changeset
|
97 sys.path = oldpaths |
4622
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
98 try: |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
99 for p in funcname.split(b'.')[1:]: |
4622
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
100 obj = getattr(obj, p) |
7280
810ca383da9c
remove unused variables
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
6762
diff
changeset
|
101 except AttributeError: |
26692
8d1cfd77b64f
hook: raise a separate exception for when loading a hook fails
Siddharth Agarwal <sid0@fb.com>
parents:
26587
diff
changeset
|
102 raise error.HookLoadError( |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
103 _(b'%s hook is invalid: "%s" is not defined') |
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
104 % (hname, funcname) |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
105 ) |
21797
b009dd135aa0
hook: restore use of callable() since it was readded in Python 3.2
Augie Fackler <raf@durin42.com>
parents:
20548
diff
changeset
|
106 if not callable(obj): |
26692
8d1cfd77b64f
hook: raise a separate exception for when loading a hook fails
Siddharth Agarwal <sid0@fb.com>
parents:
26587
diff
changeset
|
107 raise error.HookLoadError( |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
108 _(b'%s hook is invalid: "%s" is not callable') |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
109 % (hname, funcname) |
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
110 ) |
20547
9d9f8ccffead
hooks: move logging of hook name to after we have found the hook
Mads Kiilerich <madski@unity3d.com>
parents:
20422
diff
changeset
|
111 |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
112 ui.note(_(b"calling hook %s: %s\n") % (hname, funcname)) |
30975
22fbca1d11ed
mercurial: switch to util.timer for all interval timings
Simon Farnsworth <simonfar@fb.com>
parents:
30519
diff
changeset
|
113 starttime = util.timer() |
20547
9d9f8ccffead
hooks: move logging of hook name to after we have found the hook
Mads Kiilerich <madski@unity3d.com>
parents:
20422
diff
changeset
|
114 |
4622
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
115 try: |
35357
056a9c8813aa
py3: handle keyword arguments correctly in hook.py
Pulkit Goyal <7895pulkit@gmail.com>
parents:
34687
diff
changeset
|
116 r = obj(ui=ui, repo=repo, hooktype=htype, **pycompat.strkwargs(args)) |
25660
328739ea70c3
global: mass rewrite to use modern exception syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25328
diff
changeset
|
117 except Exception as exc: |
26587
56b2bcea2529
error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25953
diff
changeset
|
118 if isinstance(exc, error.Abort): |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
119 ui.warn(_(b'error: %s hook failed: %s\n') % (hname, exc.args[0])) |
25084
7046c7e7fcb4
hooks: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
24716
diff
changeset
|
120 else: |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
121 ui.warn( |
43117
8ff1ecfadcd1
cleanup: join string literals that are already on one line
Martin von Zweigbergk <martinvonz@google.com>
parents:
43106
diff
changeset
|
122 _(b'error: %s hook raised an exception: %s\n') |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
123 % (hname, stringutil.forcebytestr(exc)) |
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
124 ) |
25084
7046c7e7fcb4
hooks: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
24716
diff
changeset
|
125 if throw: |
4622
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
126 raise |
28108
2a71d9483199
hook: for python hook exceptions, add note to run with --traceback
Siddharth Agarwal <sid0@fb.com>
parents:
28106
diff
changeset
|
127 if not ui.tracebackflag: |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
128 ui.warn(_(b'(run with --traceback for stack trace)\n')) |
25084
7046c7e7fcb4
hooks: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
24716
diff
changeset
|
129 ui.traceback() |
26739
8429369eeb85
hook: for python hooks, also return whether an exception was raised
Siddharth Agarwal <sid0@fb.com>
parents:
26738
diff
changeset
|
130 return True, True |
14889
a59058fd074a
hooks: redirect stdout/err/in to the ui descriptors when calling python hooks
Idan Kamara <idankk86@gmail.com>
parents:
14711
diff
changeset
|
131 finally: |
30975
22fbca1d11ed
mercurial: switch to util.timer for all interval timings
Simon Farnsworth <simonfar@fb.com>
parents:
30519
diff
changeset
|
132 duration = util.timer() - starttime |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
133 ui.log( |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
134 b'pythonhook', |
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
135 b'pythonhook-%s: %s finished in %0.2f seconds\n', |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
136 htype, |
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
137 funcname, |
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
138 duration, |
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
139 ) |
4622
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
140 if r: |
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
141 if throw: |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
142 raise error.HookAbort(_(b'%s hook failed') % hname) |
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
143 ui.warn(_(b'warning: %s hook failed\n') % hname) |
26739
8429369eeb85
hook: for python hooks, also return whether an exception was raised
Siddharth Agarwal <sid0@fb.com>
parents:
26738
diff
changeset
|
144 return r, False |
4622
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
145 |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
146 |
31746
0fa30fbccc34
hook: provide hook type information to external hook
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
31745
diff
changeset
|
147 def _exthook(ui, repo, htype, name, cmd, args, throw): |
30975
22fbca1d11ed
mercurial: switch to util.timer for all interval timings
Simon Farnsworth <simonfar@fb.com>
parents:
30519
diff
changeset
|
148 starttime = util.timer() |
7787
b8d750daadde
Introduce HG_PREPEND to solve pretxn races
Matt Mackall <mpm@selenic.com>
parents:
7644
diff
changeset
|
149 env = {} |
26751
520defbc0335
hook: centralize passing HG_PENDING to external hook process
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
26739
diff
changeset
|
150 |
520defbc0335
hook: centralize passing HG_PENDING to external hook process
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
26739
diff
changeset
|
151 # make in-memory changes visible to external process |
27228
10695f8f3323
dirstate: don't write repo.currenttransaction to repo.dirstate if repo
Sietse Brouwer <sbbrouwer@gmail.com>
parents:
26861
diff
changeset
|
152 if repo is not None: |
10695f8f3323
dirstate: don't write repo.currenttransaction to repo.dirstate if repo
Sietse Brouwer <sbbrouwer@gmail.com>
parents:
26861
diff
changeset
|
153 tr = repo.currenttransaction() |
10695f8f3323
dirstate: don't write repo.currenttransaction to repo.dirstate if repo
Sietse Brouwer <sbbrouwer@gmail.com>
parents:
26861
diff
changeset
|
154 repo.dirstate.write(tr) |
10695f8f3323
dirstate: don't write repo.currenttransaction to repo.dirstate if repo
Sietse Brouwer <sbbrouwer@gmail.com>
parents:
26861
diff
changeset
|
155 if tr and tr.writepending(): |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
156 env[b'HG_PENDING'] = repo.root |
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
157 env[b'HG_HOOKTYPE'] = htype |
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
158 env[b'HG_HOOKNAME'] = name |
26751
520defbc0335
hook: centralize passing HG_PENDING to external hook process
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
26739
diff
changeset
|
159 |
43106
d783f945a701
py3: finish porting iteritems() to pycompat and remove source transformer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43089
diff
changeset
|
160 for k, v in pycompat.iteritems(args): |
44835
09da5cf44772
hooks: provide access to transaction changes for internal hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
44652
diff
changeset
|
161 # 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
|
162 # for external hooks |
09da5cf44772
hooks: provide access to transaction changes for internal hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
44652
diff
changeset
|
163 if k == b'changes': |
09da5cf44772
hooks: provide access to transaction changes for internal hooks
Joerg Sonnenberger <joerg@bec.de>
parents:
44652
diff
changeset
|
164 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
|
165 if callable(v): |
7787
b8d750daadde
Introduce HG_PREPEND to solve pretxn races
Matt Mackall <mpm@selenic.com>
parents:
7644
diff
changeset
|
166 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
|
167 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
|
168 v = stringutil.pprint(v) |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
169 env[b'HG_' + k.upper()] = v |
7787
b8d750daadde
Introduce HG_PREPEND to solve pretxn races
Matt Mackall <mpm@selenic.com>
parents:
7644
diff
changeset
|
170 |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
171 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
|
172 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
|
173 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
|
174 if cmd != oldcmd: |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
175 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
|
176 |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
177 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
|
178 |
5869
2c565b9598b8
hooks: fix pre- and post- hooks specified in .hg/hgrc
Matt Mackall <mpm@selenic.com>
parents:
5833
diff
changeset
|
179 if repo: |
2c565b9598b8
hooks: fix pre- and post- hooks specified in .hg/hgrc
Matt Mackall <mpm@selenic.com>
parents:
5833
diff
changeset
|
180 cwd = repo.root |
2c565b9598b8
hooks: fix pre- and post- hooks specified in .hg/hgrc
Matt Mackall <mpm@selenic.com>
parents:
5833
diff
changeset
|
181 else: |
39818
24e493ec2229
py3: rename pycompat.getcwd() to encoding.getcwd() (API)
Matt Harbison <matt_harbison@yahoo.com>
parents:
38723
diff
changeset
|
182 cwd = encoding.getcwd() |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
183 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
|
184 |
30975
22fbca1d11ed
mercurial: switch to util.timer for all interval timings
Simon Farnsworth <simonfar@fb.com>
parents:
30519
diff
changeset
|
185 duration = util.timer() - starttime |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
186 ui.log( |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
187 b'exthook', |
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
188 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
|
189 name, |
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
190 cmd, |
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
191 duration, |
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
192 ) |
4622
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
193 if r: |
37463
bbd240f81ac5
procutil: make explainexit() simply return a message (API)
Yuya Nishihara <yuya@tcha.org>
parents:
37120
diff
changeset
|
194 desc = procutil.explainexit(r) |
4622
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
195 if throw: |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
196 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
|
197 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
|
198 return r |
fff50306e6dd
hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
199 |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
200 |
28938
ea1fec3e9aba
hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
28937
diff
changeset
|
201 # 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
|
202 _fromuntrusted = object() |
ea1fec3e9aba
hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
28937
diff
changeset
|
203 |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
204 |
15896
30c34fde40cc
hooks: prioritize run order of hooks
Matt Zuba <matt.zuba@goodwillaz.org>
parents:
15512
diff
changeset
|
205 def _allhooks(ui): |
28937
3112c5e18835
hook: split config reading further
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
28936
diff
changeset
|
206 """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
|
207 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
|
208 # 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
|
209 # 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
|
210 # 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
|
211 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
|
212 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
|
213 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
|
214 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
|
215 (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
|
216 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
|
217 # (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
|
218 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
|
219 |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
220 |
28938
ea1fec3e9aba
hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
28937
diff
changeset
|
221 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
|
222 """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
|
223 hooks = {} |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
224 for name, cmd in ui.configitems(b'hooks', untrusted=_untrusted): |
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
225 if name.startswith(b'priority.') or name.startswith(b'tonative.'): |
38629
38dfd308fe9d
hook: add support for disabling the shell to native command translation
Matt Harbison <matt_harbison@yahoo.com>
parents:
38628
diff
changeset
|
226 continue |
38dfd308fe9d
hook: add support for disabling the shell to native command translation
Matt Harbison <matt_harbison@yahoo.com>
parents:
38628
diff
changeset
|
227 |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
228 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
|
229 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
|
230 return hooks |
15896
30c34fde40cc
hooks: prioritize run order of hooks
Matt Zuba <matt.zuba@goodwillaz.org>
parents:
15512
diff
changeset
|
231 |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
232 |
5833
323b9c55b328
hook: redirect stdout to stderr for ssh and http servers
Matt Mackall <mpm@selenic.com>
parents:
4622
diff
changeset
|
233 _redirect = False |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
234 |
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
235 |
5833
323b9c55b328
hook: redirect stdout to stderr for ssh and http servers
Matt Mackall <mpm@selenic.com>
parents:
4622
diff
changeset
|
236 def redirect(state): |
6266
9f76df0edb7d
hook.py: fix redirections introduced by 323b9c55b328
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents:
5869
diff
changeset
|
237 global _redirect |
5833
323b9c55b328
hook: redirect stdout to stderr for ssh and http servers
Matt Mackall <mpm@selenic.com>
parents:
4622
diff
changeset
|
238 _redirect = state |
323b9c55b328
hook: redirect stdout to stderr for ssh and http servers
Matt Mackall <mpm@selenic.com>
parents:
4622
diff
changeset
|
239 |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
240 |
34687
e79b6300d97c
hook: add a 'hashook' function to test for hook existence
Boris Feld <boris.feld@octobus.net>
parents:
32897
diff
changeset
|
241 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
|
242 """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
|
243 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
|
244 return False |
e79b6300d97c
hook: add a 'hashook' function to test for hook existence
Boris Feld <boris.feld@octobus.net>
parents:
32897
diff
changeset
|
245 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
|
246 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
|
247 return True |
e79b6300d97c
hook: add a 'hashook' function to test for hook existence
Boris Feld <boris.feld@octobus.net>
parents:
32897
diff
changeset
|
248 return False |
e79b6300d97c
hook: add a 'hashook' function to test for hook existence
Boris Feld <boris.feld@octobus.net>
parents:
32897
diff
changeset
|
249 |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
250 |
31745
33504b54863e
hook: use 'htype' in 'hook'
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
31744
diff
changeset
|
251 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
|
252 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
|
253 return False |
15d4d475de9e
ui: add a variable to control whether hooks should be called
Idan Kamara <idankk86@gmail.com>
parents:
15896
diff
changeset
|
254 |
26737
a930d66a04af
hook: factor out determination of hooks from running them
Siddharth Agarwal <sid0@fb.com>
parents:
26692
diff
changeset
|
255 hooks = [] |
a930d66a04af
hook: factor out determination of hooks from running them
Siddharth Agarwal <sid0@fb.com>
parents:
26692
diff
changeset
|
256 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
|
257 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
|
258 hooks.append((hname, cmd)) |
a930d66a04af
hook: factor out determination of hooks from running them
Siddharth Agarwal <sid0@fb.com>
parents:
26692
diff
changeset
|
259 |
31745
33504b54863e
hook: use 'htype' in 'hook'
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
31744
diff
changeset
|
260 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
|
261 r = False |
9abc2c921bbd
hook.runhooks: return a dict of result values
Siddharth Agarwal <sid0@fb.com>
parents:
26737
diff
changeset
|
262 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
|
263 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
|
264 return r |
26737
a930d66a04af
hook: factor out determination of hooks from running them
Siddharth Agarwal <sid0@fb.com>
parents:
26692
diff
changeset
|
265 |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
266 |
44652
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
267 @contextlib.contextmanager |
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
268 def redirect_stdio(): |
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
269 """Redirects stdout to stderr, if possible.""" |
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
270 |
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
271 oldstdout = -1 |
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
272 try: |
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
273 if _redirect: |
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
274 try: |
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
275 stdoutno = procutil.stdout.fileno() |
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
276 stderrno = procutil.stderr.fileno() |
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
277 # 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
|
278 if stdoutno >= 0 and stderrno >= 0: |
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
279 procutil.stdout.flush() |
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
280 oldstdout = os.dup(stdoutno) |
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
281 os.dup2(stderrno, stdoutno) |
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
282 except (OSError, AttributeError): |
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
283 # 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
|
284 pass |
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
285 |
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
286 yield |
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
287 |
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
288 finally: |
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
289 # 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
|
290 # 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
|
291 # remote side available to the client immediately. |
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
292 procutil.stderr.flush() |
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
293 |
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
294 if _redirect and oldstdout >= 0: |
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
295 procutil.stdout.flush() # write hook output to stderr fd |
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
296 os.dup2(oldstdout, stdoutno) |
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
297 os.close(oldstdout) |
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
298 |
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
299 |
31744
5678496659e9
hook: use 'htype' in 'runhooks'
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
31743
diff
changeset
|
300 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
|
301 args = pycompat.byteskwargs(args) |
26738
9abc2c921bbd
hook.runhooks: return a dict of result values
Siddharth Agarwal <sid0@fb.com>
parents:
26737
diff
changeset
|
302 res = {} |
5833
323b9c55b328
hook: redirect stdout to stderr for ssh and http servers
Matt Mackall <mpm@selenic.com>
parents:
4622
diff
changeset
|
303 |
44652
3cbbfd0bfc17
hook: move stdio redirection to context manager
Gregory Szorc <gregory.szorc@gmail.com>
parents:
43671
diff
changeset
|
304 with redirect_stdio(): |
26737
a930d66a04af
hook: factor out determination of hooks from running them
Siddharth Agarwal <sid0@fb.com>
parents:
26692
diff
changeset
|
305 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
|
306 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
|
307 if throw: |
ea1fec3e9aba
hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
28937
diff
changeset
|
308 raise error.HookAbort( |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
309 _(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
|
310 hint=_(b"see 'hg help config.trusted'"), |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
311 ) |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
312 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
|
313 r = 1 |
ea1fec3e9aba
hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
28937
diff
changeset
|
314 raised = False |
ea1fec3e9aba
hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
28937
diff
changeset
|
315 elif callable(cmd): |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
316 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
|
317 elif cmd.startswith(b'python:'): |
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
318 if cmd.count(b':') >= 2: |
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
319 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
|
320 path = util.expandpath(path) |
13119
ecf7d6e0eef0
hook: fix import path handling for repo=None
Matt Mackall <mpm@selenic.com>
parents:
13118
diff
changeset
|
321 if repo: |
ecf7d6e0eef0
hook: fix import path handling for repo=None
Matt Mackall <mpm@selenic.com>
parents:
13118
diff
changeset
|
322 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
|
323 try: |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
324 mod = extensions.loadpath(path, b'hghook.%s' % hname) |
17217
1b2b727a885f
hooks: print out more information when loading a python hook fails
Simon Heimberg <simohe@besonet.ch>
parents:
17048
diff
changeset
|
325 except Exception: |
43077
687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents:
43076
diff
changeset
|
326 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
|
327 raise |
7916
f779e1996e23
ability to load hooks from arbitrary python module
Alexander Solovyov <piranha@piranha.org.ua>
parents:
7787
diff
changeset
|
328 hookfn = getattr(mod, cmd) |
f779e1996e23
ability to load hooks from arbitrary python module
Alexander Solovyov <piranha@piranha.org.ua>
parents:
7787
diff
changeset
|
329 else: |
f779e1996e23
ability to load hooks from arbitrary python module
Alexander Solovyov <piranha@piranha.org.ua>
parents:
7787
diff
changeset
|
330 hookfn = cmd[7:].strip() |
43076
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
331 r, raised = pythonhook( |
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
332 ui, repo, htype, hname, hookfn, args, throw |
2372284d9457
formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents:
40971
diff
changeset
|
333 ) |
7416
196b05a548d0
hooks: restore io correctly on exception
Jesse Long <jesse@virtualpostman.co.za>
parents:
7280
diff
changeset
|
334 else: |
31746
0fa30fbccc34
hook: provide hook type information to external hook
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
31745
diff
changeset
|
335 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
|
336 raised = False |
26738
9abc2c921bbd
hook.runhooks: return a dict of result values
Siddharth Agarwal <sid0@fb.com>
parents:
26737
diff
changeset
|
337 |
26739
8429369eeb85
hook: for python hooks, also return whether an exception was raised
Siddharth Agarwal <sid0@fb.com>
parents:
26738
diff
changeset
|
338 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
|
339 |
26738
9abc2c921bbd
hook.runhooks: return a dict of result values
Siddharth Agarwal <sid0@fb.com>
parents:
26737
diff
changeset
|
340 return res |