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