OXYGENHUB
◆ main openmsx / build / executils.py
2.0 KiB · Python · last changed chore(): initial commit 1 month ago source blame history raw
1
from msysutils import msysActive, msysShell
2
3
from os import environ
4
from shlex import split as shsplit
5
from subprocess import PIPE, Popen
6
7
def captureStdout(log, commandLine):
8
	'''Run a command and capture what it writes to stdout.
9
	If the command fails or writes something to stderr, that is logged.
10
	Returns the captured string, or None if the command failed.
11
	'''
12
	# TODO: This is a modified copy-paste from compilers._Command.
13
	commandParts = shsplit(commandLine)
14
	env = dict(environ)
15
	env['LC_ALL'] = 'C.UTF-8'
16
	while commandParts:
17
		if '=' in commandParts[0]:
18
			name, value = commandParts[0].split('=', 1)
19
			del commandParts[0]
20
			env[name] = value
21
		else:
22
			break
23
	else:
24
		raise ValueError(
25
			'No command specified in "%s"' % commandLine
26
			)
27
28
	if msysActive() and commandParts[0] != 'sh':
29
		commandParts = [
30
			msysShell(), '-c', shjoin(commandParts)
31
			]
32
33
	try:
34
		proc = Popen(
35
			commandParts, bufsize = -1, env = env,
36
			stdin = None, stdout = PIPE, stderr = PIPE,
37
			)
38
	except OSError as ex:
39
		print('Failed to execute "%s": %s' % (commandLine, ex), file=log)
40
		return None
41
	stdoutdata, stderrdata = proc.communicate()
42
	if stderrdata:
43
		severity = 'warning' if proc.returncode == 0 else 'error'
44
		log.write('%s executing "%s"\n' % (severity.capitalize(), commandLine))
45
		# pylint 0.18.0 somehow thinks stderrdata is a list, not a string.
46
		# pylint: disable-msg=E1103
47
		stderrdata = stderrdata.decode('utf-8').replace('\r', '')
48
		log.write(stderrdata)
49
		if not stderrdata.endswith('\n'):
50
			log.write('\n')
51
	if proc.returncode == 0:
52
		return stdoutdata.decode('utf-8')
53
	else:
54
		print('Execution failed with exit code %d' % proc.returncode, file=log)
55
		return None
56
57
def shjoin(parts):
58
	'''Joins the given sequence into a single string with space as a separator.
59
	Characters that have a special meaning for the shell are escaped.
60
	This is the counterpart of shlex.split().
61
	'''
62
	def escape(part):
63
		return ''.join(
64
			'\\' + ch if ch in '\\ \'"$()[]' else ch
65
			for ch in part
66
			)
67
	return ' '.join(escape(part) for part in parts)