OLD | NEW |
1 # Copyright (c) 2010 The Chromium OS Authors. All rights reserved. | 1 # Copyright (c) 2010 The Chromium OS Authors. All rights reserved. |
2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 """Common python commands used by various build scripts.""" | 5 """Common python commands used by various build scripts.""" |
6 | 6 |
7 import os | 7 import os |
8 import re | 8 import re |
| 9 import signal |
9 import subprocess | 10 import subprocess |
10 import sys | 11 import sys |
11 | 12 |
12 _STDOUT_IS_TTY = hasattr(sys.stdout, 'isatty') and sys.stdout.isatty() | 13 _STDOUT_IS_TTY = hasattr(sys.stdout, 'isatty') and sys.stdout.isatty() |
13 | 14 |
14 | 15 |
15 class CommandResult(object): | 16 class CommandResult(object): |
16 """An object to store various attributes of a child process.""" | 17 """An object to store various attributes of a child process.""" |
17 | 18 |
18 def __init__(self): | 19 def __init__(self): |
19 self.cmd = None | 20 self.cmd = None |
20 self.error = None | 21 self.error = None |
21 self.output = None | 22 self.output = None |
22 self.returncode = None | 23 self.returncode = None |
23 | 24 |
24 | 25 |
25 class RunCommandError(Exception): | 26 class RunCommandError(Exception): |
26 """Error caught in RunCommand() method.""" | 27 """Error caught in RunCommand() method.""" |
27 pass | 28 pass |
28 | 29 |
29 | 30 |
30 def RunCommand(cmd, print_cmd=True, error_ok=False, error_message=None, | 31 def RunCommand(cmd, print_cmd=True, error_ok=False, error_message=None, |
31 exit_code=False, redirect_stdout=False, redirect_stderr=False, | 32 exit_code=False, redirect_stdout=False, redirect_stderr=False, |
32 cwd=None, input=None, enter_chroot=False, shell=False): | 33 cwd=None, input=None, enter_chroot=False, shell=False, |
| 34 env=None, ignore_sigint=False): |
33 """Runs a command. | 35 """Runs a command. |
34 | 36 |
35 Args: | 37 Args: |
36 cmd: cmd to run. Should be input to subprocess.Popen. | 38 cmd: cmd to run. Should be input to subprocess.Popen. |
37 print_cmd: prints the command before running it. | 39 print_cmd: prints the command before running it. |
38 error_ok: does not raise an exception on error. | 40 error_ok: does not raise an exception on error. |
39 error_message: prints out this message when an error occurrs. | 41 error_message: prints out this message when an error occurrs. |
40 exit_code: returns the return code of the shell command. | 42 exit_code: returns the return code of the shell command. |
41 redirect_stdout: returns the stdout. | 43 redirect_stdout: returns the stdout. |
42 redirect_stderr: holds stderr output until input is communicated. | 44 redirect_stderr: holds stderr output until input is communicated. |
43 cwd: the working directory to run this cmd. | 45 cwd: the working directory to run this cmd. |
44 input: input to pipe into this command through stdin. | 46 input: input to pipe into this command through stdin. |
45 enter_chroot: this command should be run from within the chroot. If set, | 47 enter_chroot: this command should be run from within the chroot. If set, |
46 cwd must point to the scripts directory. | 48 cwd must point to the scripts directory. |
47 shell: If shell is True, the specified command will be executed through | 49 shell: If shell is True, the specified command will be executed through |
48 the shell. | 50 the shell. |
| 51 env: If non-None, this is the environment for the new process. |
| 52 ignore_sigint: If True, we'll ignore signal.SIGINT before calling the |
| 53 child. This is the desired behavior if we know our child will handle |
| 54 Ctrl-C. If we don't do this, I think we and the child will both get |
| 55 Ctrl-C at the same time, which means we'll forcefully kill the child. |
49 | 56 |
50 Returns: | 57 Returns: |
51 A CommandResult object. | 58 A CommandResult object. |
52 | 59 |
53 Raises: | 60 Raises: |
54 Exception: Raises generic exception on error with optional error_message. | 61 Exception: Raises generic exception on error with optional error_message. |
55 """ | 62 """ |
56 # Set default for variables. | 63 # Set default for variables. |
57 stdout = None | 64 stdout = None |
58 stderr = None | 65 stderr = None |
(...skipping 13 matching lines...) Expand all Loading... |
72 if enter_chroot: cmd = ['./enter_chroot.sh', '--'] + cmd | 79 if enter_chroot: cmd = ['./enter_chroot.sh', '--'] + cmd |
73 cmd_str = ' '.join(cmd) | 80 cmd_str = ' '.join(cmd) |
74 | 81 |
75 # Print out the command before running. | 82 # Print out the command before running. |
76 if print_cmd: | 83 if print_cmd: |
77 Info('RunCommand: %s' % cmd_str) | 84 Info('RunCommand: %s' % cmd_str) |
78 cmd_result.cmd = cmd_str | 85 cmd_result.cmd = cmd_str |
79 | 86 |
80 try: | 87 try: |
81 proc = subprocess.Popen(cmd, cwd=cwd, stdin=stdin, stdout=stdout, | 88 proc = subprocess.Popen(cmd, cwd=cwd, stdin=stdin, stdout=stdout, |
82 stderr=stderr, shell=shell) | 89 stderr=stderr, shell=shell, env=env) |
83 (cmd_result.output, cmd_result.error) = proc.communicate(input) | 90 if ignore_sigint: |
| 91 old_sigint = signal.signal(signal.SIGINT, signal.SIG_IGN) |
| 92 try: |
| 93 (cmd_result.output, cmd_result.error) = proc.communicate(input) |
| 94 finally: |
| 95 if ignore_sigint: |
| 96 signal.signal(signal.SIGINT, old_sigint) |
| 97 |
84 if exit_code: | 98 if exit_code: |
85 cmd_result.returncode = proc.returncode | 99 cmd_result.returncode = proc.returncode |
86 | 100 |
87 if not error_ok and proc.returncode: | 101 if not error_ok and proc.returncode: |
88 msg = ('Command "%s" failed.\n' % cmd_str + | 102 msg = ('Command "%s" failed.\n' % cmd_str + |
89 (error_message or cmd_result.error or cmd_result.output or '')) | 103 (error_message or cmd_result.error or cmd_result.output or '')) |
90 raise RunCommandError(msg) | 104 raise RunCommandError(msg) |
91 # TODO(sosa): is it possible not to use the catch-all Exception here? | 105 # TODO(sosa): is it possible not to use the catch-all Exception here? |
92 except Exception, e: | 106 except Exception, e: |
93 if not error_ok: | 107 if not error_ok: |
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
242 Returns: | 256 Returns: |
243 a string: absolute path to output directory. | 257 a string: absolute path to output directory. |
244 """ | 258 """ |
245 src_root = GetSrcRoot() | 259 src_root = GetSrcRoot() |
246 rel_path = 'build/images/%s' % board | 260 rel_path = 'build/images/%s' % board |
247 # ASSUME: --build_attempt always sets to 1 | 261 # ASSUME: --build_attempt always sets to 1 |
248 version_str = '-'.join([cros_version, 'a1']) | 262 version_str = '-'.join([cros_version, 'a1']) |
249 output_dir = os.path.join(os.path.dirname(src_root), rel_path, version_str) | 263 output_dir = os.path.join(os.path.dirname(src_root), rel_path, version_str) |
250 Info ('output_dir = %s' % output_dir) | 264 Info ('output_dir = %s' % output_dir) |
251 return output_dir | 265 return output_dir |
OLD | NEW |