155 lines
5.6 KiB
Python
155 lines
5.6 KiB
Python
# 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
|