mercurial/hook.py
author Pierre-Yves David <pierre-yves.david@octobus.net>
Wed, 16 Oct 2019 17:49:30 +0200
changeset 43254 181d28ba05da
parent 43117 8ff1ecfadcd1
child 43503 313e3a279828
permissions -rw-r--r--
copies: avoid instancing more changectx to access parent revisions We just need to know the revision numbers of the parents, creating full context is needlessly expensive. This provide a small, but noticeable performance boost. revision: large amount; added files: large amount; rename small amount; c3b14617fbd7 9ba6ab77fd29 before: ! wall 2.885636 comb 2.900000 user 2.870000 sys 0.030000 (median of 10) after: ! wall 2.702270 comb 2.710000 user 2.690000 sys 0.020000 (median of 10) revision: large amount; added files: small amount; rename small amount; c3b14617fbd7 f650a9b140d2 before: ! wall 4.298271 comb 4.290000 user 4.240000 sys 0.050000 (median of 10) after: ! wall 3.976610 comb 3.970000 user 3.920000 sys 0.050000 (median of 10) revision: large amount; added files: large amount; rename large amount; 08ea3258278e d9fa043f30c0 before: ! wall 0.773397 comb 0.770000 user 0.770000 sys 0.000000 (median of 11) after: ! wall 0.701634 comb 0.700000 user 0.700000 sys 0.000000 (median of 13) revision: small amount; added files: large amount; rename large amount; df6f7a526b60 a83dc6a2d56f before: ! wall 0.013585 comb 0.010000 user 0.010000 sys 0.000000 (median of 217) after: ! wall 0.013550 comb 0.010000 user 0.010000 sys 0.000000 (median of 218) revision: small amount; added files: large amount; rename small amount; 4aa4e1f8e19a 169138063d63 before: ! wall 0.003202 comb 0.000000 user 0.000000 sys 0.000000 (median of 929) after: ! wall 0.002993 comb 0.010000 user 0.010000 sys 0.000000 (median of 992) revision: small amount; added files: small amount; rename small amount; 4bc173b045a6 964879152e2e before: ! wall 0.000077 comb 0.000000 user 0.000000 sys 0.000000 (median of 12060) after: ! wall 0.000072 comb 0.000000 user 0.000000 sys 0.000000 (median of 12804) revision: medium amount; added files: large amount; rename medium amount; c95f1ced15f2 2c68e87c3efe before: ! wall 0.510614 comb 0.500000 user 0.500000 sys 0.000000 (median of 18) after: ! wall 0.473681 comb 0.470000 user 0.470000 sys 0.000000 (median of 20) revision: medium amount; added files: medium amount; rename small amount; d343da0c55a8 d7746d32bf9d before: ! wall 0.126552 comb 0.130000 user 0.130000 sys 0.000000 (median of 77) after: ! wall 0.115240 comb 0.110000 user 0.110000 sys 0.000000 (median of 85) Differential Revision: https://phab.mercurial-scm.org/D7122
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
4622
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     1
# hook.py - hook support for mercurial
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     2
#
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     3
# Copyright 2007 Matt Mackall <mpm@selenic.com>
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     4
#
8225
46293a0c7e9f updated license to be explicit about GPL version 2
Martin Geisler <mg@lazybytes.net>
parents: 8209
diff changeset
     5
# This software may be used and distributed according to the terms of the
10263
25e572394f5c Update license to GPLv2+
Matt Mackall <mpm@selenic.com>
parents: 10103
diff changeset
     6
# GNU General Public License version 2 or any later version.
4622
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     7
25953
d15b279ddade hook: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
     8
from __future__ import absolute_import
d15b279ddade hook: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
     9
d15b279ddade hook: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
    10
import os
d15b279ddade hook: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
    11
import sys
d15b279ddade hook: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
    12
d15b279ddade hook: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
    13
from .i18n import _
43089
c59eb1560c44 py3: manually import getattr where it is needed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43077
diff changeset
    14
from .pycompat import getattr
25953
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,
37751
483de34f23b1 hook: use stringutil.pprint instead of reinventing it
Augie Fackler <augie@google.com>
parents: 37463
diff changeset
    25
    stringutil,
37119
d4a2e0d5d042 procutil: bulk-replace util.std* to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36841
diff changeset
    26
)
4622
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    27
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
    28
38041
242eb5132203 filemerge: support specifying a python function to custom merge-tools
hindlemail <tom_hindle@sil.org>
parents: 37942
diff changeset
    29
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
    30
    '''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
    31
    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
    32
    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
    33
    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
    34
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    35
    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
    36
    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
    37
    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
    38
21797
b009dd135aa0 hook: restore use of callable() since it was readded in Python 3.2
Augie Fackler <raf@durin42.com>
parents: 20548
diff changeset
    39
    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
    40
        obj = funcname
32614
4b426ae96ff2 py3: ensure that we don't concat bytes and str and the end result is bytes
Pulkit Goyal <7895pulkit@gmail.com>
parents: 31747
diff changeset
    41
        funcname = pycompat.sysbytes(obj.__module__ + r"." + 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
    42
    else:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    43
        d = funcname.rfind(b'.')
4622
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    44
        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
    45
            raise error.HookLoadError(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    46
                _(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
    47
                % (hname, funcname)
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
    48
            )
4622
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    49
        modname = funcname[:d]
10103
37679dbf2ee3 hook: fix bug (reuse of variable) introduced in 872d49dd577a
Sune Foldager <cryo@cyanite.org>
parents: 9851
diff changeset
    50
        oldpaths = sys.path
37120
a8a902d7176e procutil: bulk-replace function calls to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 37119
diff changeset
    51
        if procutil.mainfrozen():
9332
872d49dd577a hook: fix full path imports on Windows (issue1779)
Steve Borho <steve@borho.org>
parents: 8366
diff changeset
    52
            # 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
    53
            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
    54
            if modpath and modfile:
37679dbf2ee3 hook: fix bug (reuse of variable) introduced in 872d49dd577a
Sune Foldager <cryo@cyanite.org>
parents: 9851
diff changeset
    55
                sys.path = sys.path[:] + [modpath]
37679dbf2ee3 hook: fix bug (reuse of variable) introduced in 872d49dd577a
Sune Foldager <cryo@cyanite.org>
parents: 9851
diff changeset
    56
                modname = modfile
25328
2cfb0bbf83a1 hooks: replace if-try-finally with a "with" statement
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 25184
diff changeset
    57
        with demandimport.deactivated():
4622
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    58
            try:
36108
c4146cf4dd20 py3: use system strings when calling __import__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35357
diff changeset
    59
                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
    60
            except (ImportError, SyntaxError):
28078
2058e1a894f2 hook: use sys.exc_info rather than the deprecated equivalents
Siddharth Agarwal <sid0@fb.com>
parents: 27228
diff changeset
    61
                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
    62
                try:
2cfb0bbf83a1 hooks: replace if-try-finally with a "with" statement
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 25184
diff changeset
    63
                    # extensions are loaded with hgext_ prefix
36108
c4146cf4dd20 py3: use system strings when calling __import__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35357
diff changeset
    64
                    obj = __import__(r"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
    65
                except (ImportError, SyntaxError):
28078
2058e1a894f2 hook: use sys.exc_info rather than the deprecated equivalents
Siddharth Agarwal <sid0@fb.com>
parents: 27228
diff changeset
    66
                    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
    67
                    if ui.tracebackflag:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
    68
                        ui.warn(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
    69
                            _(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    70
                                b'exception from first failed import '
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    71
                                b'attempt:\n'
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
    72
                            )
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
    73
                        )
25328
2cfb0bbf83a1 hooks: replace if-try-finally with a "with" statement
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 25184
diff changeset
    74
                    ui.traceback(e1)
2cfb0bbf83a1 hooks: replace if-try-finally with a "with" statement
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 25184
diff changeset
    75
                    if ui.tracebackflag:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
    76
                        ui.warn(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
    77
                            _(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    78
                                b'exception from second failed import '
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    79
                                b'attempt:\n'
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
    80
                            )
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
    81
                        )
25328
2cfb0bbf83a1 hooks: replace if-try-finally with a "with" statement
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 25184
diff changeset
    82
                    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
    83
37b818cad146 hook: for python hook ImportErrors, add note to run with --traceback
Siddharth Agarwal <sid0@fb.com>
parents: 28079
diff changeset
    84
                    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
    85
                        tracebackhint = _(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    86
                            b'run with --traceback for stack trace'
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
    87
                        )
28080
37b818cad146 hook: for python hook ImportErrors, add note to run with --traceback
Siddharth Agarwal <sid0@fb.com>
parents: 28079
diff changeset
    88
                    else:
37b818cad146 hook: for python hook ImportErrors, add note to run with --traceback
Siddharth Agarwal <sid0@fb.com>
parents: 28079
diff changeset
    89
                        tracebackhint = None
26692
8d1cfd77b64f hook: raise a separate exception for when loading a hook fails
Siddharth Agarwal <sid0@fb.com>
parents: 26587
diff changeset
    90
                    raise error.HookLoadError(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    91
                        _(b'%s hook is invalid: import of "%s" failed')
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
    92
                        % (hname, modname),
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
    93
                        hint=tracebackhint,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
    94
                    )
9332
872d49dd577a hook: fix full path imports on Windows (issue1779)
Steve Borho <steve@borho.org>
parents: 8366
diff changeset
    95
        sys.path = oldpaths
4622
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    96
        try:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    97
            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
    98
                obj = getattr(obj, p)
7280
810ca383da9c remove unused variables
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 6762
diff changeset
    99
        except AttributeError:
26692
8d1cfd77b64f hook: raise a separate exception for when loading a hook fails
Siddharth Agarwal <sid0@fb.com>
parents: 26587
diff changeset
   100
            raise error.HookLoadError(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   101
                _(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
   102
                % (hname, funcname)
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
   103
            )
21797
b009dd135aa0 hook: restore use of callable() since it was readded in Python 3.2
Augie Fackler <raf@durin42.com>
parents: 20548
diff changeset
   104
        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
   105
            raise error.HookLoadError(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   106
                _(b'%s hook is invalid: "%s" is not callable')
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
   107
                % (hname, funcname)
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
   108
            )
20547
9d9f8ccffead hooks: move logging of hook name to after we have found the hook
Mads Kiilerich <madski@unity3d.com>
parents: 20422
diff changeset
   109
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   110
    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
   111
    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
   112
4622
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   113
    try:
35357
056a9c8813aa py3: handle keyword arguments correctly in hook.py
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34687
diff changeset
   114
        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
   115
    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
   116
        if isinstance(exc, error.Abort):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   117
            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
   118
        else:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
   119
            ui.warn(
43117
8ff1ecfadcd1 cleanup: join string literals that are already on one line
Martin von Zweigbergk <martinvonz@google.com>
parents: 43106
diff changeset
   120
                _(b'error: %s hook raised an exception: %s\n')
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
   121
                % (hname, stringutil.forcebytestr(exc))
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
   122
            )
25084
7046c7e7fcb4 hooks: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents: 24716
diff changeset
   123
        if throw:
4622
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   124
            raise
28108
2a71d9483199 hook: for python hook exceptions, add note to run with --traceback
Siddharth Agarwal <sid0@fb.com>
parents: 28106
diff changeset
   125
        if not ui.tracebackflag:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   126
            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
   127
        ui.traceback()
26739
8429369eeb85 hook: for python hooks, also return whether an exception was raised
Siddharth Agarwal <sid0@fb.com>
parents: 26738
diff changeset
   128
        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
   129
    finally:
30975
22fbca1d11ed mercurial: switch to util.timer for all interval timings
Simon Farnsworth <simonfar@fb.com>
parents: 30519
diff changeset
   130
        duration = util.timer() - starttime
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
   131
        ui.log(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   132
            b'pythonhook',
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   133
            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
   134
            htype,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
   135
            funcname,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
   136
            duration,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
   137
        )
4622
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   138
    if r:
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   139
        if throw:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   140
            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
   141
        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
   142
    return r, False
4622
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   143
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
   144
31746
0fa30fbccc34 hook: provide hook type information to external hook
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 31745
diff changeset
   145
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
   146
    starttime = util.timer()
7787
b8d750daadde Introduce HG_PREPEND to solve pretxn races
Matt Mackall <mpm@selenic.com>
parents: 7644
diff changeset
   147
    env = {}
26751
520defbc0335 hook: centralize passing HG_PENDING to external hook process
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 26739
diff changeset
   148
520defbc0335 hook: centralize passing HG_PENDING to external hook process
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 26739
diff changeset
   149
    # 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
   150
    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
   151
        tr = repo.currenttransaction()
10695f8f3323 dirstate: don't write repo.currenttransaction to repo.dirstate if repo
Sietse Brouwer <sbbrouwer@gmail.com>
parents: 26861
diff changeset
   152
        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
   153
        if tr and tr.writepending():
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   154
            env[b'HG_PENDING'] = repo.root
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   155
    env[b'HG_HOOKTYPE'] = htype
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   156
    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
   157
43106
d783f945a701 py3: finish porting iteritems() to pycompat and remove source transformer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43089
diff changeset
   158
    for k, v in pycompat.iteritems(args):
21797
b009dd135aa0 hook: restore use of callable() since it was readded in Python 3.2
Augie Fackler <raf@durin42.com>
parents: 20548
diff changeset
   159
        if callable(v):
7787
b8d750daadde Introduce HG_PREPEND to solve pretxn races
Matt Mackall <mpm@selenic.com>
parents: 7644
diff changeset
   160
            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
   161
        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
   162
            v = stringutil.pprint(v)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   163
        env[b'HG_' + k.upper()] = v
7787
b8d750daadde Introduce HG_PREPEND to solve pretxn races
Matt Mackall <mpm@selenic.com>
parents: 7644
diff changeset
   164
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   165
    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
   166
        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
   167
        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
   168
        if cmd != oldcmd:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   169
            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
   170
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   171
    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
   172
5869
2c565b9598b8 hooks: fix pre- and post- hooks specified in .hg/hgrc
Matt Mackall <mpm@selenic.com>
parents: 5833
diff changeset
   173
    if repo:
2c565b9598b8 hooks: fix pre- and post- hooks specified in .hg/hgrc
Matt Mackall <mpm@selenic.com>
parents: 5833
diff changeset
   174
        cwd = repo.root
2c565b9598b8 hooks: fix pre- and post- hooks specified in .hg/hgrc
Matt Mackall <mpm@selenic.com>
parents: 5833
diff changeset
   175
    else:
39818
24e493ec2229 py3: rename pycompat.getcwd() to encoding.getcwd() (API)
Matt Harbison <matt_harbison@yahoo.com>
parents: 38723
diff changeset
   176
        cwd = encoding.getcwd()
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   177
    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
   178
30975
22fbca1d11ed mercurial: switch to util.timer for all interval timings
Simon Farnsworth <simonfar@fb.com>
parents: 30519
diff changeset
   179
    duration = util.timer() - starttime
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
   180
    ui.log(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   181
        b'exthook',
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   182
        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
   183
        name,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
   184
        cmd,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
   185
        duration,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
   186
    )
4622
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   187
    if r:
37463
bbd240f81ac5 procutil: make explainexit() simply return a message (API)
Yuya Nishihara <yuya@tcha.org>
parents: 37120
diff changeset
   188
        desc = procutil.explainexit(r)
4622
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   189
        if throw:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   190
            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
   191
        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
   192
    return r
fff50306e6dd hooks: separate hook code into a separate module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   193
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
   194
28938
ea1fec3e9aba hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 28937
diff changeset
   195
# 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
   196
_fromuntrusted = object()
ea1fec3e9aba hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 28937
diff changeset
   197
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
   198
15896
30c34fde40cc hooks: prioritize run order of hooks
Matt Zuba <matt.zuba@goodwillaz.org>
parents: 15512
diff changeset
   199
def _allhooks(ui):
28937
3112c5e18835 hook: split config reading further
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 28936
diff changeset
   200
    """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
   201
    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
   202
    # 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
   203
    # 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
   204
    # 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
   205
    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
   206
    for name, value in untrustedhooks.items():
ea1fec3e9aba hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 28937
diff changeset
   207
        trustedvalue = hooks.get(name, (None, None, name, _fromuntrusted))
ea1fec3e9aba hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 28937
diff changeset
   208
        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
   209
            (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
   210
            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
   211
    # (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
   212
    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
   213
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
   214
28938
ea1fec3e9aba hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 28937
diff changeset
   215
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
   216
    """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
   217
    hooks = {}
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   218
    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
   219
        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
   220
            continue
38dfd308fe9d hook: add support for disabling the shell to native command translation
Matt Harbison <matt_harbison@yahoo.com>
parents: 38628
diff changeset
   221
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   222
        priority = ui.configint(b'hooks', b'priority.%s' % name, 0)
38629
38dfd308fe9d hook: add support for disabling the shell to native command translation
Matt Harbison <matt_harbison@yahoo.com>
parents: 38628
diff changeset
   223
        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
   224
    return hooks
15896
30c34fde40cc hooks: prioritize run order of hooks
Matt Zuba <matt.zuba@goodwillaz.org>
parents: 15512
diff changeset
   225
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
   226
5833
323b9c55b328 hook: redirect stdout to stderr for ssh and http servers
Matt Mackall <mpm@selenic.com>
parents: 4622
diff changeset
   227
_redirect = False
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
   228
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
   229
5833
323b9c55b328 hook: redirect stdout to stderr for ssh and http servers
Matt Mackall <mpm@selenic.com>
parents: 4622
diff changeset
   230
def redirect(state):
6266
9f76df0edb7d hook.py: fix redirections introduced by 323b9c55b328
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5869
diff changeset
   231
    global _redirect
5833
323b9c55b328 hook: redirect stdout to stderr for ssh and http servers
Matt Mackall <mpm@selenic.com>
parents: 4622
diff changeset
   232
    _redirect = state
323b9c55b328 hook: redirect stdout to stderr for ssh and http servers
Matt Mackall <mpm@selenic.com>
parents: 4622
diff changeset
   233
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
   234
34687
e79b6300d97c hook: add a 'hashook' function to test for hook existence
Boris Feld <boris.feld@octobus.net>
parents: 32897
diff changeset
   235
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
   236
    """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
   237
    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
   238
        return False
e79b6300d97c hook: add a 'hashook' function to test for hook existence
Boris Feld <boris.feld@octobus.net>
parents: 32897
diff changeset
   239
    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
   240
        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
   241
            return True
e79b6300d97c hook: add a 'hashook' function to test for hook existence
Boris Feld <boris.feld@octobus.net>
parents: 32897
diff changeset
   242
    return False
e79b6300d97c hook: add a 'hashook' function to test for hook existence
Boris Feld <boris.feld@octobus.net>
parents: 32897
diff changeset
   243
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
   244
31745
33504b54863e hook: use 'htype' in 'hook'
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 31744
diff changeset
   245
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
   246
    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
   247
        return False
15d4d475de9e ui: add a variable to control whether hooks should be called
Idan Kamara <idankk86@gmail.com>
parents: 15896
diff changeset
   248
26737
a930d66a04af hook: factor out determination of hooks from running them
Siddharth Agarwal <sid0@fb.com>
parents: 26692
diff changeset
   249
    hooks = []
a930d66a04af hook: factor out determination of hooks from running them
Siddharth Agarwal <sid0@fb.com>
parents: 26692
diff changeset
   250
    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
   251
        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
   252
            hooks.append((hname, cmd))
a930d66a04af hook: factor out determination of hooks from running them
Siddharth Agarwal <sid0@fb.com>
parents: 26692
diff changeset
   253
31745
33504b54863e hook: use 'htype' in 'hook'
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 31744
diff changeset
   254
    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
   255
    r = False
9abc2c921bbd hook.runhooks: return a dict of result values
Siddharth Agarwal <sid0@fb.com>
parents: 26737
diff changeset
   256
    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
   257
        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
   258
    return r
26737
a930d66a04af hook: factor out determination of hooks from running them
Siddharth Agarwal <sid0@fb.com>
parents: 26692
diff changeset
   259
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
   260
31744
5678496659e9 hook: use 'htype' in 'runhooks'
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 31743
diff changeset
   261
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
   262
    args = pycompat.byteskwargs(args)
26738
9abc2c921bbd hook.runhooks: return a dict of result values
Siddharth Agarwal <sid0@fb.com>
parents: 26737
diff changeset
   263
    res = {}
9658
852b1f3032d2 hook: only redirect stdout if it and stderr are valid files
Sune Foldager <cryo@cyanite.org>
parents: 9332
diff changeset
   264
    oldstdout = -1
5833
323b9c55b328 hook: redirect stdout to stderr for ssh and http servers
Matt Mackall <mpm@selenic.com>
parents: 4622
diff changeset
   265
7416
196b05a548d0 hooks: restore io correctly on exception
Jesse Long <jesse@virtualpostman.co.za>
parents: 7280
diff changeset
   266
    try:
26737
a930d66a04af hook: factor out determination of hooks from running them
Siddharth Agarwal <sid0@fb.com>
parents: 26692
diff changeset
   267
        for hname, cmd in hooks:
17963
6180dcb29ec5 hooks: delay I/O redirection until we actually run a hook (issue3711)
Matt Mackall <mpm@selenic.com>
parents: 17428
diff changeset
   268
            if oldstdout == -1 and _redirect:
6180dcb29ec5 hooks: delay I/O redirection until we actually run a hook (issue3711)
Matt Mackall <mpm@selenic.com>
parents: 17428
diff changeset
   269
                try:
37119
d4a2e0d5d042 procutil: bulk-replace util.std* to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36841
diff changeset
   270
                    stdoutno = procutil.stdout.fileno()
d4a2e0d5d042 procutil: bulk-replace util.std* to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36841
diff changeset
   271
                    stderrno = procutil.stderr.fileno()
17963
6180dcb29ec5 hooks: delay I/O redirection until we actually run a hook (issue3711)
Matt Mackall <mpm@selenic.com>
parents: 17428
diff changeset
   272
                    # temporarily redirect stdout to stderr, if possible
6180dcb29ec5 hooks: delay I/O redirection until we actually run a hook (issue3711)
Matt Mackall <mpm@selenic.com>
parents: 17428
diff changeset
   273
                    if stdoutno >= 0 and stderrno >= 0:
37119
d4a2e0d5d042 procutil: bulk-replace util.std* to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36841
diff changeset
   274
                        procutil.stdout.flush()
17963
6180dcb29ec5 hooks: delay I/O redirection until we actually run a hook (issue3711)
Matt Mackall <mpm@selenic.com>
parents: 17428
diff changeset
   275
                        oldstdout = os.dup(stdoutno)
6180dcb29ec5 hooks: delay I/O redirection until we actually run a hook (issue3711)
Matt Mackall <mpm@selenic.com>
parents: 17428
diff changeset
   276
                        os.dup2(stderrno, stdoutno)
17964
2c63896783e3 hooks: be even more forgiven of non-fd descriptors (issue3711)
Matt Mackall <mpm@selenic.com>
parents: 17963
diff changeset
   277
                except (OSError, AttributeError):
2c63896783e3 hooks: be even more forgiven of non-fd descriptors (issue3711)
Matt Mackall <mpm@selenic.com>
parents: 17963
diff changeset
   278
                    # files seem to be bogus, give up on redirecting (WSGI, etc)
17963
6180dcb29ec5 hooks: delay I/O redirection until we actually run a hook (issue3711)
Matt Mackall <mpm@selenic.com>
parents: 17428
diff changeset
   279
                    pass
6180dcb29ec5 hooks: delay I/O redirection until we actually run a hook (issue3711)
Matt Mackall <mpm@selenic.com>
parents: 17428
diff changeset
   280
28938
ea1fec3e9aba hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 28937
diff changeset
   281
            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
   282
                if throw:
ea1fec3e9aba hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 28937
diff changeset
   283
                    raise error.HookAbort(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   284
                        _(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
   285
                        hint=_(b"see 'hg help config.trusted'"),
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
   286
                    )
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   287
                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
   288
                r = 1
ea1fec3e9aba hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 28937
diff changeset
   289
                raised = False
ea1fec3e9aba hook: report untrusted hooks as failure (issue5110) (BC)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 28937
diff changeset
   290
            elif callable(cmd):
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
   291
                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
   292
            elif cmd.startswith(b'python:'):
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   293
                if cmd.count(b':') >= 2:
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   294
                    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
   295
                    path = util.expandpath(path)
13119
ecf7d6e0eef0 hook: fix import path handling for repo=None
Matt Mackall <mpm@selenic.com>
parents: 13118
diff changeset
   296
                    if repo:
ecf7d6e0eef0 hook: fix import path handling for repo=None
Matt Mackall <mpm@selenic.com>
parents: 13118
diff changeset
   297
                        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
   298
                    try:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   299
                        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
   300
                    except Exception:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   301
                        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
   302
                        raise
7916
f779e1996e23 ability to load hooks from arbitrary python module
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7787
diff changeset
   303
                    hookfn = getattr(mod, cmd)
f779e1996e23 ability to load hooks from arbitrary python module
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7787
diff changeset
   304
                else:
f779e1996e23 ability to load hooks from arbitrary python module
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7787
diff changeset
   305
                    hookfn = cmd[7:].strip()
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
   306
                r, raised = pythonhook(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
   307
                    ui, repo, htype, hname, hookfn, args, throw
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40971
diff changeset
   308
                )
7416
196b05a548d0 hooks: restore io correctly on exception
Jesse Long <jesse@virtualpostman.co.za>
parents: 7280
diff changeset
   309
            else:
31746
0fa30fbccc34 hook: provide hook type information to external hook
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 31745
diff changeset
   310
                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
   311
                raised = False
26738
9abc2c921bbd hook.runhooks: return a dict of result values
Siddharth Agarwal <sid0@fb.com>
parents: 26737
diff changeset
   312
26739
8429369eeb85 hook: for python hooks, also return whether an exception was raised
Siddharth Agarwal <sid0@fb.com>
parents: 26738
diff changeset
   313
            res[hname] = r, raised
36841
9c636ec1ef37 hook: ensure stderr is flushed when an exception is raised, for test stability
Matt Harbison <matt_harbison@yahoo.com>
parents: 36108
diff changeset
   314
    finally:
9c636ec1ef37 hook: ensure stderr is flushed when an exception is raised, for test stability
Matt Harbison <matt_harbison@yahoo.com>
parents: 36108
diff changeset
   315
        # The stderr is fully buffered on Windows when connected to a pipe.
9c636ec1ef37 hook: ensure stderr is flushed when an exception is raised, for test stability
Matt Harbison <matt_harbison@yahoo.com>
parents: 36108
diff changeset
   316
        # A forcible flush is required to make small stderr data in the
9c636ec1ef37 hook: ensure stderr is flushed when an exception is raised, for test stability
Matt Harbison <matt_harbison@yahoo.com>
parents: 36108
diff changeset
   317
        # remote side available to the client immediately.
37119
d4a2e0d5d042 procutil: bulk-replace util.std* to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36841
diff changeset
   318
        procutil.stderr.flush()
24716
2abbf4750915 hook: forcibly flush stderr for Windows test stability
Matt Harbison <matt_harbison@yahoo.com>
parents: 23426
diff changeset
   319
9658
852b1f3032d2 hook: only redirect stdout if it and stderr are valid files
Sune Foldager <cryo@cyanite.org>
parents: 9332
diff changeset
   320
        if _redirect and oldstdout >= 0:
37119
d4a2e0d5d042 procutil: bulk-replace util.std* to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36841
diff changeset
   321
            procutil.stdout.flush()  # write hook output to stderr fd
9658
852b1f3032d2 hook: only redirect stdout if it and stderr are valid files
Sune Foldager <cryo@cyanite.org>
parents: 9332
diff changeset
   322
            os.dup2(oldstdout, stdoutno)
7416
196b05a548d0 hooks: restore io correctly on exception
Jesse Long <jesse@virtualpostman.co.za>
parents: 7280
diff changeset
   323
            os.close(oldstdout)
6266
9f76df0edb7d hook.py: fix redirections introduced by 323b9c55b328
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5869
diff changeset
   324
26738
9abc2c921bbd hook.runhooks: return a dict of result values
Siddharth Agarwal <sid0@fb.com>
parents: 26737
diff changeset
   325
    return res