summaryrefslogtreecommitdiffstats
path: root/tools/update-verify/python/util/commands.py
blob: e53464e6f82cc3e79b6a201ba6d79dd5d1b05f7d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
# You can obtain one at http://mozilla.org/MPL/2.0/.

"""Functions for running commands"""

import logging
import os
import subprocess
import time

import six

log = logging.getLogger(__name__)


# timeout message, used in TRANSIENT_HG_ERRORS and in tests.
TERMINATED_PROCESS_MSG = "timeout, process terminated"


def log_cmd(cmd, **kwargs):
    # cwd is special in that we always want it printed, even if it's not
    # explicitly chosen
    kwargs = kwargs.copy()
    if "cwd" not in kwargs:
        kwargs["cwd"] = os.getcwd()
    log.info("command: START")
    log.info("command: %s" % subprocess.list2cmdline(cmd))
    for key, value in six.iteritems(kwargs):
        log.info("command: %s: %s", key, str(value))


def merge_env(env):
    new_env = os.environ.copy()
    new_env.update(env)
    return new_env


def run_cmd(cmd, **kwargs):
    """Run cmd (a list of arguments).  Raise subprocess.CalledProcessError if
    the command exits with non-zero.  If the command returns successfully,
    return 0."""
    log_cmd(cmd, **kwargs)
    # We update this after logging because we don't want all of the inherited
    # env vars muddling up the output
    if "env" in kwargs:
        kwargs["env"] = merge_env(kwargs["env"])
    try:
        t = time.monotonic()
        log.info("command: output:")
        return subprocess.check_call(cmd, **kwargs)
    except subprocess.CalledProcessError:
        log.info("command: ERROR", exc_info=True)
        raise
    finally:
        elapsed = time.monotonic() - t
        log.info("command: END (%.2fs elapsed)\n", elapsed)