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

Side by Side Diff: build/android/pylib/device/device_utils.py

Issue 773043005: Revert of Allow RunShellCommand to work even with very large commands (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years 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/device/device_utils_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 2014 The Chromium Authors. All rights reserved. 1 # Copyright 2014 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 """Provides a variety of device interactions based on adb. 5 """Provides a variety of device interactions based on adb.
6 6
7 Eventually, this will be based on adb_wrapper. 7 Eventually, this will be based on adb_wrapper.
8 """ 8 """
9 # pylint: disable=W0613 9 # pylint: disable=W0613
10 10
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
51 """Restarts the adb server. 51 """Restarts the adb server.
52 52
53 Raises: 53 Raises:
54 CommandFailedError if we fail to kill or restart the server. 54 CommandFailedError if we fail to kill or restart the server.
55 """ 55 """
56 pylib.android_commands.AndroidCommands().RestartAdbServer() 56 pylib.android_commands.AndroidCommands().RestartAdbServer()
57 57
58 58
59 class DeviceUtils(object): 59 class DeviceUtils(object):
60 60
61 _MAX_ADB_COMMAND_LENGTH = 512
62 _VALID_SHELL_VARIABLE = re.compile('^[a-zA-Z_][a-zA-Z0-9_]*$') 61 _VALID_SHELL_VARIABLE = re.compile('^[a-zA-Z_][a-zA-Z0-9_]*$')
63 62
64 def __init__(self, device, default_timeout=_DEFAULT_TIMEOUT, 63 def __init__(self, device, default_timeout=_DEFAULT_TIMEOUT,
65 default_retries=_DEFAULT_RETRIES): 64 default_retries=_DEFAULT_RETRIES):
66 """DeviceUtils constructor. 65 """DeviceUtils constructor.
67 66
68 Args: 67 Args:
69 device: Either a device serial, an existing AdbWrapper instance, or an 68 device: Either a device serial, an existing AdbWrapper instance, or an
70 an existing AndroidCommands instance. 69 an existing AndroidCommands instance.
71 default_timeout: An integer containing the default number of seconds to 70 default_timeout: An integer containing the default number of seconds to
(...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after
420 more lines. 419 more lines.
421 CommandTimeoutError on timeout. 420 CommandTimeoutError on timeout.
422 DeviceUnreachableError on missing device. 421 DeviceUnreachableError on missing device.
423 """ 422 """
424 def env_quote(key, value): 423 def env_quote(key, value):
425 if not DeviceUtils._VALID_SHELL_VARIABLE.match(key): 424 if not DeviceUtils._VALID_SHELL_VARIABLE.match(key):
426 raise KeyError('Invalid shell variable name %r' % key) 425 raise KeyError('Invalid shell variable name %r' % key)
427 # using double quotes here to allow interpolation of shell variables 426 # using double quotes here to allow interpolation of shell variables
428 return '%s=%s' % (key, cmd_helper.DoubleQuote(value)) 427 return '%s=%s' % (key, cmd_helper.DoubleQuote(value))
429 428
430 def do_run(cmd):
431 try:
432 return self.adb.Shell(cmd)
433 except device_errors.AdbCommandFailedError as exc:
434 if check_return:
435 raise
436 else:
437 return exc.output
438
439 if not isinstance(cmd, basestring): 429 if not isinstance(cmd, basestring):
440 cmd = ' '.join(cmd_helper.SingleQuote(s) for s in cmd) 430 cmd = ' '.join(cmd_helper.SingleQuote(s) for s in cmd)
441 if env: 431 if env:
442 env = ' '.join(env_quote(k, v) for k, v in env.iteritems()) 432 env = ' '.join(env_quote(k, v) for k, v in env.iteritems())
443 cmd = '%s %s' % (env, cmd) 433 cmd = '%s %s' % (env, cmd)
444 if cwd: 434 if cwd:
445 cmd = 'cd %s && %s' % (cmd_helper.SingleQuote(cwd), cmd) 435 cmd = 'cd %s && %s' % (cmd_helper.SingleQuote(cwd), cmd)
446 if as_root and self.NeedsSU(): 436 if as_root and self.NeedsSU():
447 # "su -c sh -c" allows using shell features in |cmd| 437 # "su -c sh -c" allows using shell features in |cmd|
448 cmd = 'su -c sh -c %s' % cmd_helper.SingleQuote(cmd) 438 cmd = 'su -c sh -c %s' % cmd_helper.SingleQuote(cmd)
449 if timeout is None: 439 if timeout is None:
450 timeout = self._default_timeout 440 timeout = self._default_timeout
451 441
452 if len(cmd) < self._MAX_ADB_COMMAND_LENGTH: 442 try:
453 output = do_run(cmd) 443 output = self.adb.Shell(cmd)
454 else: 444 except device_errors.AdbCommandFailedError as e:
455 with device_temp_file.DeviceTempFile(self.adb, suffix='.sh') as script: 445 if check_return:
456 self._WriteFileWithPush(script.name, cmd) 446 raise
457 output = do_run('sh %s' % script.name_quoted) 447 else:
448 output = e.output
458 449
459 output = output.splitlines() 450 output = output.splitlines()
460 if single_line: 451 if single_line:
461 if not output: 452 if not output:
462 return '' 453 return ''
463 elif len(output) == 1: 454 elif len(output) == 1:
464 return output[0] 455 return output[0]
465 else: 456 else:
466 msg = 'one line of output was expected, but got: %s' 457 msg = 'one line of output was expected, but got: %s'
467 raise device_errors.CommandFailedError(msg % output, str(self)) 458 raise device_errors.CommandFailedError(msg % output, str(self))
(...skipping 425 matching lines...) Expand 10 before | Expand all | Expand 10 after
893 # TODO(jbudorick) Evaluate whether we want to return a list of lines after 884 # TODO(jbudorick) Evaluate whether we want to return a list of lines after
894 # the implementation switch, and if file not found should raise exception. 885 # the implementation switch, and if file not found should raise exception.
895 if as_root: 886 if as_root:
896 if not self.old_interface.CanAccessProtectedFileContents(): 887 if not self.old_interface.CanAccessProtectedFileContents():
897 raise device_errors.CommandFailedError( 888 raise device_errors.CommandFailedError(
898 'Cannot read from %s with root privileges.' % device_path) 889 'Cannot read from %s with root privileges.' % device_path)
899 return self.old_interface.GetProtectedFileContents(device_path) 890 return self.old_interface.GetProtectedFileContents(device_path)
900 else: 891 else:
901 return self.old_interface.GetFileContents(device_path) 892 return self.old_interface.GetFileContents(device_path)
902 893
903 def _WriteFileWithPush(self, device_path, contents):
904 with tempfile.NamedTemporaryFile() as host_temp:
905 host_temp.write(contents)
906 host_temp.flush()
907 self.adb.Push(host_temp.name, device_path)
908
909 @decorators.WithTimeoutAndRetriesFromInstance() 894 @decorators.WithTimeoutAndRetriesFromInstance()
910 def WriteFile(self, device_path, contents, as_root=False, force_push=False, 895 def WriteFile(self, device_path, contents, as_root=False, force_push=False,
911 timeout=None, retries=None): 896 timeout=None, retries=None):
912 """Writes |contents| to a file on the device. 897 """Writes |contents| to a file on the device.
913 898
914 Args: 899 Args:
915 device_path: A string containing the absolute path to the file to write 900 device_path: A string containing the absolute path to the file to write
916 on the device. 901 on the device.
917 contents: A string containing the data to write to the device. 902 contents: A string containing the data to write to the device.
918 as_root: A boolean indicating whether the write should be executed with 903 as_root: A boolean indicating whether the write should be executed with
919 root privileges (if available). 904 root privileges (if available).
920 force_push: A boolean indicating whether to force the operation to be 905 force_push: A boolean indicating whether to force the operation to be
921 performed by pushing a file to the device. The default is, when the 906 performed by pushing a file to the device. The default is, when the
922 contents are short, to pass the contents using a shell script instead. 907 contents are short, to pass the contents using a shell script instead.
923 timeout: timeout in seconds 908 timeout: timeout in seconds
924 retries: number of retries 909 retries: number of retries
925 910
926 Raises: 911 Raises:
927 CommandFailedError if the file could not be written on the device. 912 CommandFailedError if the file could not be written on the device.
928 CommandTimeoutError on timeout. 913 CommandTimeoutError on timeout.
929 DeviceUnreachableError on missing device. 914 DeviceUnreachableError on missing device.
930 """ 915 """
931 if not force_push and len(contents) < self._MAX_ADB_COMMAND_LENGTH: 916 if len(contents) < 512 and not force_push:
932 # If the contents are small, for efficieny we write the contents using
933 # using a shell command rather than push
934 cmd = 'echo -n %s > %s' % (cmd_helper.SingleQuote(contents), 917 cmd = 'echo -n %s > %s' % (cmd_helper.SingleQuote(contents),
935 cmd_helper.SingleQuote(device_path)) 918 cmd_helper.SingleQuote(device_path))
936 self.RunShellCommand(cmd, as_root=as_root, check_return=True) 919 self.RunShellCommand(cmd, as_root=as_root, check_return=True)
937 elif as_root and self.NeedsSU():
938 # Adb does not allow to "push with su", so we first push to a temp file
939 # on a safe location, and then copy it to the desired location with su
940 with device_temp_file.DeviceTempFile(self.adb) as device_temp:
941 self._WriteFileWithPush(device_temp.name, contents)
942 # Here we need 'cp' rather than 'mv' because the temp and
943 # destination files might be on different file systems (e.g.
944 # on internal storage and an external sd card)
945 self.RunShellCommand(['cp', device_temp.name, device_path],
946 as_root=True, check_return=True)
947 else: 920 else:
948 # If root is not needed, we can push directly to the desired location 921 with tempfile.NamedTemporaryFile() as host_temp:
949 self._WriteFileWithPush(device_path, contents) 922 host_temp.write(contents)
923 host_temp.flush()
924 if as_root and self.NeedsSU():
925 with device_temp_file.DeviceTempFile(self) as device_temp:
926 self.adb.Push(host_temp.name, device_temp.name)
927 # Here we need 'cp' rather than 'mv' because the temp and
928 # destination files might be on different file systems (e.g.
929 # on internal storage and an external sd card)
930 self.RunShellCommand(['cp', device_temp.name, device_path],
931 as_root=True, check_return=True)
932 else:
933 self.adb.Push(host_temp.name, device_path)
950 934
951 @decorators.WithTimeoutAndRetriesFromInstance() 935 @decorators.WithTimeoutAndRetriesFromInstance()
952 def Ls(self, device_path, timeout=None, retries=None): 936 def Ls(self, device_path, timeout=None, retries=None):
953 """Lists the contents of a directory on the device. 937 """Lists the contents of a directory on the device.
954 938
955 Args: 939 Args:
956 device_path: A string containing the path of the directory on the device 940 device_path: A string containing the path of the directory on the device
957 to list. 941 to list.
958 timeout: timeout in seconds 942 timeout: timeout in seconds
959 retries: number of retries 943 retries: number of retries
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after
1210 Returns: 1194 Returns:
1211 A Parallelizer operating over |devices|. 1195 A Parallelizer operating over |devices|.
1212 """ 1196 """
1213 if not devices or len(devices) == 0: 1197 if not devices or len(devices) == 0:
1214 devices = pylib.android_commands.GetAttachedDevices() 1198 devices = pylib.android_commands.GetAttachedDevices()
1215 parallelizer_type = (parallelizer.Parallelizer if async 1199 parallelizer_type = (parallelizer.Parallelizer if async
1216 else parallelizer.SyncParallelizer) 1200 else parallelizer.SyncParallelizer)
1217 return parallelizer_type([ 1201 return parallelizer_type([
1218 d if isinstance(d, DeviceUtils) else DeviceUtils(d) 1202 d if isinstance(d, DeviceUtils) else DeviceUtils(d)
1219 for d in devices]) 1203 for d in devices])
OLDNEW
« no previous file with comments | « no previous file | build/android/pylib/device/device_utils_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698