tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

common_exec.py (5742B)


      1 # Copyright (C) 2018 and later: Unicode, Inc. and others.
      2 # License & terms of use: http://www.unicode.org/copyright.html
      3 
      4 # Python 2/3 Compatibility (ICU-20299)
      5 # TODO(ICU-20301): Remove this.
      6 from __future__ import print_function
      7 
      8 from . import *
      9 from .. import *
     10 from .. import utils
     11 from ..request_types import *
     12 
     13 import os
     14 import shutil
     15 import subprocess
     16 import sys
     17 
     18 def run(build_dirs, requests, common_vars, verbose=True, **kwargs):
     19    for bd in build_dirs:
     20        makedirs(bd.format(**common_vars))
     21    for request in requests:
     22        status = run_helper(request, common_vars, verbose=verbose, **kwargs)
     23        if status != 0:
     24            print("!!! ERROR executing above command line: exit code %d" % status)
     25            return 1
     26    if verbose:
     27        print("All data build commands executed")
     28    return 0
     29 
     30 def makedirs(dirs):
     31    """makedirs compatible between Python 2 and 3"""
     32    try:
     33        # Python 3 version
     34        os.makedirs(dirs, exist_ok=True)
     35    except TypeError as e:
     36        # Python 2 version
     37        try:
     38            os.makedirs(dirs)
     39        except OSError as e:
     40            if e.errno != errno.EEXIST:
     41                raise e
     42 
     43 def run_helper(request, common_vars, platform, tool_dir, verbose, tool_cfg=None, **kwargs):
     44    if isinstance(request, PrintFileRequest):
     45        output_path = "{DIRNAME}/{FILENAME}".format(
     46            DIRNAME = utils.dir_for(request.output_file).format(**common_vars),
     47            FILENAME = request.output_file.filename,
     48        )
     49        if verbose:
     50            print("Printing to file: %s" % output_path)
     51        with open(output_path, "w") as f:
     52            f.write(request.content)
     53        return 0
     54    if isinstance(request, CopyRequest):
     55        input_path = "{DIRNAME}/{FILENAME}".format(
     56            DIRNAME = utils.dir_for(request.input_file).format(**common_vars),
     57            FILENAME = request.input_file.filename,
     58        )
     59        output_path = "{DIRNAME}/{FILENAME}".format(
     60            DIRNAME = utils.dir_for(request.output_file).format(**common_vars),
     61            FILENAME = request.output_file.filename,
     62        )
     63        if verbose:
     64            print("Copying file to: %s" % output_path)
     65        shutil.copyfile(input_path, output_path)
     66        return 0
     67    if isinstance(request, VariableRequest):
     68        # No-op
     69        return 0
     70 
     71    assert isinstance(request.tool, IcuTool)
     72    if platform == "windows":
     73        cmd_template = "{TOOL_DIR}/{TOOL}/{TOOL_CFG}/{TOOL}.exe {{ARGS}}".format(
     74            TOOL_DIR = tool_dir,
     75            TOOL_CFG = tool_cfg,
     76            TOOL = request.tool.name,
     77            **common_vars
     78        )
     79    elif platform == "unix":
     80        cmd_template = "{TOOL_DIR}/{TOOL} {{ARGS}}".format(
     81            TOOL_DIR = tool_dir,
     82            TOOL = request.tool.name,
     83            **common_vars
     84        )
     85    elif platform == "bazel":
     86        cmd_template = "{TOOL_DIR}/{TOOL}/{TOOL} {{ARGS}}".format(
     87            TOOL_DIR = tool_dir,
     88            TOOL = request.tool.name,
     89            **common_vars
     90        )
     91    else:
     92        raise ValueError("Unknown platform: %s" % platform)
     93 
     94    if isinstance(request, RepeatedExecutionRequest):
     95        for loop_vars in utils.repeated_execution_request_looper(request):
     96            command_line = utils.format_repeated_request_command(
     97                request,
     98                cmd_template,
     99                loop_vars,
    100                common_vars
    101            )
    102            if platform == "windows":
    103                # Note: this / to \ substitution may be too aggressive?
    104                command_line = command_line.replace("/", "\\")
    105            returncode = run_shell_command(command_line, platform, verbose)
    106            if returncode != 0:
    107                return returncode
    108        return 0
    109    if isinstance(request, SingleExecutionRequest):
    110        command_line = utils.format_single_request_command(
    111            request,
    112            cmd_template,
    113            common_vars
    114        )
    115        if platform == "windows":
    116            # Note: this / to \ substitution may be too aggressive?
    117            command_line = command_line.replace("/", "\\")
    118        returncode = run_shell_command(command_line, platform, verbose)
    119        return returncode
    120    assert False
    121 
    122 def run_shell_command(command_line, platform, verbose):
    123    changed_windows_comspec = False
    124    # If the command line length on Windows exceeds the absolute maximum that CMD supports (8191), then
    125    # we temporarily switch over to use PowerShell for the command, and then switch back to CMD.
    126    # We don't want to use PowerShell for everything though, as it tends to be slower.
    127    if (platform == "windows"):
    128        previous_comspec = os.environ["COMSPEC"]
    129        # Add 7 to the length for the argument /c with quotes.
    130        # For example:  C:\WINDOWS\system32\cmd.exe /c "<command_line>"
    131        if ((len(previous_comspec) + len(command_line) + 7) > 8190):
    132            if verbose:
    133                print("Command length exceeds the max length for CMD on Windows, using PowerShell instead.")
    134            os.environ["COMSPEC"] = 'powershell'
    135            changed_windows_comspec = True
    136    if verbose:
    137        print("Running: %s" % command_line)
    138        returncode = subprocess.call(
    139            command_line,
    140            shell = True
    141        )
    142    else:
    143        # Pipe output to /dev/null in quiet mode
    144        with open(os.devnull, "w") as devnull:
    145            returncode = subprocess.call(
    146                command_line,
    147                shell = True,
    148                stdout = devnull,
    149                stderr = devnull
    150            )
    151    if changed_windows_comspec:
    152        os.environ["COMSPEC"] = previous_comspec
    153    if returncode != 0:
    154        print("Command failed: %s" % command_line, file=sys.stderr)
    155    return returncode