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

Unified Diff: build/android/pylib/device/device_utils.py

Issue 715853002: Migrate device utils WriteFile to AdbWrapper (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fixed edge cases Created 6 years, 1 month 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 side-by-side diff with in-line comments
Download patch
Index: build/android/pylib/device/device_utils.py
diff --git a/build/android/pylib/device/device_utils.py b/build/android/pylib/device/device_utils.py
index b75a41a2f1a2401e98982ad044386ec517984fff..4c6a81fdb55b01b4a4829b25ae50617a3268be27 100644
--- a/build/android/pylib/device/device_utils.py
+++ b/build/android/pylib/device/device_utils.py
@@ -24,6 +24,7 @@ from pylib.device import decorators
from pylib.device import device_errors
from pylib.device.commands import install_commands
from pylib.utils import apk_helper
+from pylib.utils import device_temp_file
from pylib.utils import host_utils
from pylib.utils import parallelizer
from pylib.utils import timeout_retry
@@ -866,16 +867,19 @@ class DeviceUtils(object):
return self.old_interface.GetFileContents(device_path)
@decorators.WithTimeoutAndRetriesFromInstance()
- def WriteFile(self, device_path, contents, as_root=False, timeout=None,
- retries=None):
+ def WriteFile(self, device_path, contents, as_root=False, force_push=False,
+ timeout=None, retries=None):
"""Writes |contents| to a file on the device.
Args:
device_path: A string containing the absolute path to the file to write
- on the device.
+ on the device.
contents: A string containing the data to write to the device.
as_root: A boolean indicating whether the write should be executed with
- root privileges.
+ root privileges (if available).
+ force_push: A boolean indicating whether to force the operation to be
Sami 2014/11/12 14:14:14 Is force_push needed by anything other than tests?
perezju 2014/11/12 17:37:03 Well, yes, certainly it's useful for testing, but
+ performed by pushing a file to the device. The default is, when the
+ contents are short, to pass the contents using a shell script instead.
timeout: timeout in seconds
retries: number of retries
@@ -884,39 +888,31 @@ class DeviceUtils(object):
CommandTimeoutError on timeout.
DeviceUnreachableError on missing device.
"""
- if as_root:
- if not self.old_interface.CanAccessProtectedFileContents():
- raise device_errors.CommandFailedError(
- 'Cannot write to %s with root privileges.' % device_path)
- self.old_interface.SetProtectedFileContents(device_path, contents)
+ if len(contents) < 512 and not force_push:
+ # When as_root=True and su is needed, trying to execute
+ # su -c echo -n {contents} > {device_path}
+ # won't work, because echo is interpreted by the shell and not an actual
Sami 2014/11/12 14:14:14 nit: I presume it's not the echo that gets execute
perezju 2014/11/12 17:37:02 No. "su -c cmd > /some/file" works fine, because t
+ # command on the device. So instead we must make sure that in those cases
+ # the command to execute becomes:
+ # su -c sh -c 'echo -n {contents}' > {device_path}
+ cmd = 'echo -n %s' % cmd_helper.SingleQuote(contents)
+ sh_cmd = 'sh -c %s > %s' % (cmd_helper.SingleQuote(cmd),
+ cmd_helper.SingleQuote(device_path))
+ self.RunShellCommand(sh_cmd, as_root=as_root, check_return=True)
perezju 2014/11/12 01:31:24 Not sure why this never hit us before! Probably Wr
jbudorick 2014/11/12 01:42:37 Wow, nice catch. This is a nasty little corner cas
perezju 2014/11/12 17:37:03 Indeed, echo (and sometimes with as_root=True!) is
else:
- self.old_interface.SetFileContents(device_path, contents)
-
- @decorators.WithTimeoutAndRetriesFromInstance()
- def WriteTextFile(self, device_path, text, as_root=False, timeout=None,
- retries=None):
- """Writes |text| to a file on the device.
-
- Assuming that |text| is a small string, this is typically more efficient
- than |WriteFile|, as no files are pushed into the device.
-
- Args:
- device_path: A string containing the absolute path to the file to write
- on the device.
- text: A short string of text to write to the file on the device.
- as_root: A boolean indicating whether the write should be executed with
- root privileges.
- timeout: timeout in seconds
- retries: number of retries
-
- Raises:
- CommandFailedError if the file could not be written on the device.
- CommandTimeoutError on timeout.
- DeviceUnreachableError on missing device.
- """
- cmd = 'echo %s > %s' % (cmd_helper.SingleQuote(text),
- cmd_helper.SingleQuote(device_path))
- self.RunShellCommand(cmd, as_root=as_root, check_return=True)
+ with tempfile.NamedTemporaryFile() as host_temp:
+ host_temp.write(contents)
+ host_temp.flush()
+ if as_root and self.NeedsSU():
+ with device_temp_file.DeviceTempFile(self) as device_temp:
+ self.adb.Push(host_temp.name, device_temp.name)
+ # Here we need 'cp' rather than 'mv' because the temp and
+ # destination files might be on different file systems (e.g.
+ # on internal storage and an external sd card)
+ self.RunShellCommand(['cp', device_temp.name, device_path],
+ as_root=True, check_return=True)
perezju 2014/11/12 01:31:24 So, I had to resort to 'cp' rather than 'mv' in th
jbudorick 2014/11/12 01:42:37 While I think we should try to move away from usin
+ else:
+ self.adb.Push(host_temp.name, device_path)
@decorators.WithTimeoutAndRetriesFromInstance()
def Ls(self, device_path, timeout=None, retries=None):

Powered by Google App Engine
This is Rietveld 408576698