Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(647)

Side by Side Diff: build/android/pylib/cmd_helper.py

Issue 659533002: New run shell implementation for DeviceUtils (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fixed nit, and TODO to make cmd_helper_test run on bots Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | build/android/pylib/cmd_helper_test.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 # Copyright (c) 2012 The Chromium 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 """A wrapper for subprocess to make calling shell commands easier.""" 5 """A wrapper for subprocess to make calling shell commands easier."""
6 6
7 import logging 7 import logging
8 import os 8 import os
9 import pipes 9 import pipes
10 import select 10 import select
11 import signal 11 import signal
12 import string
12 import StringIO 13 import StringIO
13 import subprocess 14 import subprocess
14 import time 15 import time
15 16
16 # fcntl is not available on Windows. 17 # fcntl is not available on Windows.
17 try: 18 try:
18 import fcntl 19 import fcntl
19 except ImportError: 20 except ImportError:
20 fcntl = None 21 fcntl = None
21 22
23 _SafeShellChars = frozenset(string.ascii_letters + string.digits + '@%_-+=:,./')
24
25 def SingleQuote(s):
26 """Return an shell-escaped version of the string using single quotes.
27
28 Reliably quote a string which may contain unsafe characters (e.g. space,
29 quote, or other special characters such as '$').
30
31 The returned value can be used in a shell command line as one token that gets
32 to be interpreted literally.
33
34 Args:
35 s: The string to quote.
36
37 Return:
38 The string quoted using single quotes.
39 """
40 return pipes.quote(s)
41
42 def DoubleQuote(s):
43 """Return an shell-escaped version of the string using double quotes.
44
45 Reliably quote a string which may contain unsafe characters (e.g. space
46 or quote characters), while retaining some shell features such as variable
47 interpolation.
48
49 The returned value can be used in a shell command line as one token that gets
50 to be further interpreted by the shell.
51
52 The set of characters that retain their special meaning may depend on the
53 shell implementation. This set usually includes: '$', '`', '\', '!', '*',
54 and '@'.
55
56 Args:
57 s: The string to quote.
58
59 Return:
60 The string quoted using double quotes.
61 """
62 if not s:
63 return '""'
64 elif all(c in _SafeShellChars for c in s):
65 return s
66 else:
67 return '"' + s.replace('"', '\\"') + '"'
68
22 69
23 def Popen(args, stdout=None, stderr=None, shell=None, cwd=None, env=None): 70 def Popen(args, stdout=None, stderr=None, shell=None, cwd=None, env=None):
24 return subprocess.Popen( 71 return subprocess.Popen(
25 args=args, cwd=cwd, stdout=stdout, stderr=stderr, 72 args=args, cwd=cwd, stdout=stdout, stderr=stderr,
26 shell=shell, close_fds=True, env=env, 73 shell=shell, close_fds=True, env=env,
27 preexec_fn=lambda: signal.signal(signal.SIGPIPE, signal.SIG_DFL)) 74 preexec_fn=lambda: signal.signal(signal.SIGPIPE, signal.SIG_DFL))
28 75
29 76
30 def Call(args, stdout=None, stderr=None, shell=None, cwd=None, env=None): 77 def Call(args, stdout=None, stderr=None, shell=None, cwd=None, env=None):
31 pipe = Popen(args, stdout=stdout, stderr=stderr, shell=shell, cwd=cwd, 78 pipe = Popen(args, stdout=stdout, stderr=stderr, shell=shell, cwd=cwd,
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
81 Returns: 128 Returns:
82 The 2-tuple (exit code, output). 129 The 2-tuple (exit code, output).
83 """ 130 """
84 if isinstance(args, basestring): 131 if isinstance(args, basestring):
85 args_repr = args 132 args_repr = args
86 if not shell: 133 if not shell:
87 raise Exception('string args must be run with shell=True') 134 raise Exception('string args must be run with shell=True')
88 elif shell: 135 elif shell:
89 raise Exception('array args must be run with shell=False') 136 raise Exception('array args must be run with shell=False')
90 else: 137 else:
91 args_repr = ' '.join(map(pipes.quote, args)) 138 args_repr = ' '.join(map(SingleQuote, args))
92 139
93 s = '[host]' 140 s = '[host]'
94 if cwd: 141 if cwd:
95 s += ':' + cwd 142 s += ':' + cwd
96 s += '> ' + args_repr 143 s += '> ' + args_repr
97 logging.info(s) 144 logging.info(s)
98 pipe = Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, 145 pipe = Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
99 shell=shell, cwd=cwd) 146 shell=shell, cwd=cwd)
100 stdout, stderr = pipe.communicate() 147 stdout, stderr = pipe.communicate()
101 148
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
158 break 205 break
159 finally: 206 finally:
160 try: 207 try:
161 # Make sure the process doesn't stick around if we fail with an 208 # Make sure the process doesn't stick around if we fail with an
162 # exception. 209 # exception.
163 process.kill() 210 process.kill()
164 except OSError: 211 except OSError:
165 pass 212 pass
166 process.wait() 213 process.wait()
167 return process.returncode, output.getvalue() 214 return process.returncode, output.getvalue()
OLDNEW
« no previous file with comments | « no previous file | build/android/pylib/cmd_helper_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698