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 inspect | 7 import inspect |
8 import os | 8 import os |
9 import subprocess | 9 import subprocess |
10 import sys | 10 import sys |
11 | 11 |
12 _STDOUT_IS_TTY = hasattr(sys.stdout, 'isatty') and sys.stdout.isatty() | 12 _STDOUT_IS_TTY = hasattr(sys.stdout, 'isatty') and sys.stdout.isatty() |
13 | 13 |
14 # TODO(sosa): Move logging to logging module. | 14 # TODO(sosa): Move logging to logging module. |
15 | 15 |
| 16 class RunCommandException(Exception): |
| 17 """Raised when there is an error in RunCommand.""" |
| 18 pass |
| 19 |
| 20 |
16 def GetCallerName(): | 21 def GetCallerName(): |
17 """Returns the name of the calling module with __main__.""" | 22 """Returns the name of the calling module with __main__.""" |
18 top_frame = inspect.stack()[-1][0] | 23 top_frame = inspect.stack()[-1][0] |
19 return os.path.basename(top_frame.f_code.co_filename) | 24 return os.path.basename(top_frame.f_code.co_filename) |
20 | 25 |
21 | 26 |
22 def RunCommand(cmd, print_cmd=True, error_ok=False, error_message=None, | 27 def RunCommand(cmd, print_cmd=True, error_ok=False, error_message=None, |
23 exit_code=False, redirect_stdout=False, redirect_stderr=False, | 28 exit_code=False, redirect_stdout=False, redirect_stderr=False, |
24 cwd=None, input=None, enter_chroot=False): | 29 cwd=None, input=None, enter_chroot=False, num_retries=0): |
25 """Runs a shell command. | 30 """Runs a shell command. |
26 | 31 |
27 Keyword arguments: | 32 Arguments: |
28 cmd - cmd to run. Should be input to subprocess.POpen. If a string, | 33 cmd: cmd to run. Should be input to subprocess.POpen. If a string, |
29 converted to an array using split(). | 34 converted to an array using split(). |
30 print_cmd -- prints the command before running it. | 35 print_cmd: prints the command before running it. |
31 error_ok -- does not raise an exception on error. | 36 error_ok: does not raise an exception on error. |
32 error_message -- prints out this message when an error occurrs. | 37 error_message: prints out this message when an error occurrs. |
33 exit_code -- returns the return code of the shell command. | 38 exit_code: returns the return code of the shell command. |
34 redirect_stdout -- returns the stdout. | 39 redirect_stdout: returns the stdout. |
35 redirect_stderr -- holds stderr output until input is communicated. | 40 redirect_stderr: holds stderr output until input is communicated. |
36 cwd -- the working directory to run this cmd. | 41 cwd: the working directory to run this cmd. |
37 input -- input to pipe into this command through stdin. | 42 input: input to pipe into this command through stdin. |
38 enter_chroot -- this command should be run from within the chroot. If set, | 43 enter_chroot: this command should be run from within the chroot. If set, |
39 cwd must point to the scripts directory. | 44 cwd must point to the scripts directory. |
| 45 num_retries: the number of retries to perform before dying |
| 46 |
| 47 Returns: |
| 48 If exit_code is True, returns the return code of the shell command. |
| 49 Else returns the output of the shell command. |
| 50 |
40 Raises: | 51 Raises: |
41 Exception: Raises generic exception on error with optional error_message. | 52 Exception: Raises RunCommandException on error with optional error_message. |
42 """ | 53 """ |
43 # Set default for variables. | 54 # Set default for variables. |
44 stdout = None | 55 stdout = None |
45 stderr = None | 56 stderr = None |
46 stdin = None | 57 stdin = None |
47 output = '' | 58 output = '' |
48 | 59 |
49 # Modify defaults based on parameters. | 60 # Modify defaults based on parameters. |
50 if redirect_stdout: stdout = subprocess.PIPE | 61 if redirect_stdout: stdout = subprocess.PIPE |
51 if redirect_stderr: stderr = subprocess.PIPE | 62 if redirect_stderr: stderr = subprocess.PIPE |
52 if input: stdin = subprocess.PIPE | 63 if input: stdin = subprocess.PIPE |
53 if enter_chroot: cmd = ['./enter_chroot.sh', '--'] + cmd | 64 if enter_chroot: cmd = ['./enter_chroot.sh', '--'] + cmd |
54 | 65 |
55 # Print out the command before running. | 66 # Print out the command before running. |
56 if print_cmd: | 67 if print_cmd: |
57 Info('PROGRAM(%s) -> RunCommand: %r in dir %s' % | 68 Info('PROGRAM(%s) -> RunCommand: %r in dir %s' % |
58 (GetCallerName(), cmd, cwd)) | 69 (GetCallerName(), cmd, cwd)) |
59 | 70 |
60 try: | 71 for retry_count in range(num_retries + 1): |
61 proc = subprocess.Popen(cmd, cwd=cwd, stdin=stdin, | 72 try: |
62 stdout=stdout, stderr=stderr) | 73 proc = subprocess.Popen(cmd, cwd=cwd, stdin=stdin, |
63 (output, error) = proc.communicate(input) | 74 stdout=stdout, stderr=stderr) |
64 if exit_code: | 75 (output, error) = proc.communicate(input) |
65 return proc.returncode | 76 if exit_code and retry_count == num_retries: |
| 77 return proc.returncode |
66 | 78 |
67 if not error_ok and proc.returncode: | 79 if proc.returncode == 0: |
68 raise Exception('Command "%r" failed.\n' % (cmd) + | 80 break |
69 (error_message or error or output or '')) | 81 |
70 except Exception, e: | 82 raise RunCommandException('Command "%r" failed.\n' % (cmd) + |
71 if not error_ok: | 83 (error_message or error or output or '')) |
72 raise | 84 except Exception, e: |
73 else: | 85 if not error_ok and retry_count == num_retries: |
74 Warning(str(e)) | 86 raise RunCommandException(e) |
| 87 else: |
| 88 Warning(str(e)) |
| 89 if print_cmd: |
| 90 Info('PROGRAM(%s) -> RunCommand: retrying %r in dir %s' % |
| 91 (GetCallerName(), cmd, cwd)) |
75 | 92 |
76 return output | 93 return output |
77 | 94 |
78 | 95 |
79 class Color(object): | 96 class Color(object): |
80 """Conditionally wraps text in ANSI color escape sequences.""" | 97 """Conditionally wraps text in ANSI color escape sequences.""" |
81 BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = range(8) | 98 BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = range(8) |
82 BOLD = -1 | 99 BOLD = -1 |
83 COLOR_START = '\033[1;%dm' | 100 COLOR_START = '\033[1;%dm' |
84 BOLD_START = '\033[1m' | 101 BOLD_START = '\033[1m' |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
168 | 185 |
169 # Strip the repository root from the path and strip first /. | 186 # Strip the repository root from the path and strip first /. |
170 relative_path = path_abs_path.replace(root_abs_path, '')[1:] | 187 relative_path = path_abs_path.replace(root_abs_path, '')[1:] |
171 | 188 |
172 if relative_path == path_abs_path: | 189 if relative_path == path_abs_path: |
173 raise Exception('Error: path is outside your src tree, cannot reinterpret.') | 190 raise Exception('Error: path is outside your src tree, cannot reinterpret.') |
174 | 191 |
175 new_path = os.path.join('/home', os.getenv('USER'), 'trunk', relative_path) | 192 new_path = os.path.join('/home', os.getenv('USER'), 'trunk', relative_path) |
176 return new_path | 193 return new_path |
177 | 194 |
OLD | NEW |