зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1328301 - handle push/pull directory semantics changes in adb 1.0.36 for adb.py, r=gbrown.
This commit is contained in:
Родитель
c7973f5461
Коммит
88345f4996
|
@ -5,12 +5,14 @@
|
|||
import os
|
||||
import posixpath
|
||||
import re
|
||||
import shutil
|
||||
import subprocess
|
||||
import tempfile
|
||||
import time
|
||||
import traceback
|
||||
|
||||
from abc import ABCMeta, abstractmethod
|
||||
from distutils import dir_util
|
||||
|
||||
|
||||
class ADBProcess(object):
|
||||
|
@ -149,15 +151,19 @@ class ADBCommand(object):
|
|||
self._adb_port = adb_port
|
||||
self._timeout = timeout
|
||||
self._polling_interval = 0.1
|
||||
self._adb_version = ''
|
||||
|
||||
self._logger.debug("%s: %s" % (self.__class__.__name__,
|
||||
self.__dict__))
|
||||
|
||||
# catch early a missing or non executable adb command
|
||||
# and get the adb version while we are at it.
|
||||
try:
|
||||
subprocess.Popen([adb, 'help'],
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE).communicate()
|
||||
output = subprocess.Popen([adb, 'version'],
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE).communicate()
|
||||
re_version = re.compile(r'Android Debug Bridge version (.*)')
|
||||
self._adb_version = re_version.match(output[0]).group(1)
|
||||
except Exception as exc:
|
||||
raise ADBError('%s: %s is not executable.' % (exc, adb))
|
||||
|
||||
|
@ -1718,8 +1724,42 @@ class ADBDevice(ADBCommand):
|
|||
:raises: * ADBTimeoutError
|
||||
* ADBError
|
||||
"""
|
||||
self.command_output(["push", os.path.realpath(local), remote],
|
||||
timeout=timeout)
|
||||
# remove trailing /
|
||||
local = os.path.normpath(local)
|
||||
remote = os.path.normpath(remote)
|
||||
copy_required = False
|
||||
if self._adb_version >= '1.0.36' and \
|
||||
os.path.isdir(local) and self.is_dir(remote):
|
||||
# See do_sync_push in
|
||||
# https://android.googlesource.com/platform/system/core/+/master/adb/file_sync_client.cpp
|
||||
# Work around change in behavior in adb 1.0.36 where if
|
||||
# the remote destination directory exists, adb push will
|
||||
# copy the source directory *into* the destination
|
||||
# directory otherwise it will copy the source directory
|
||||
# *onto* the destination directory.
|
||||
#
|
||||
# If the destination directory does exist, push to its
|
||||
# parent directory. If the source and destination leaf
|
||||
# directory names are different, copy the source directory
|
||||
# to a temporary directory with the same leaf name as the
|
||||
# destination so that when we push to the parent, the
|
||||
# source is copied onto the destination directory.
|
||||
local_name = os.path.basename(local)
|
||||
remote_name = os.path.basename(remote)
|
||||
if local_name != remote_name:
|
||||
copy_required = True
|
||||
temp_parent = tempfile.mkdtemp()
|
||||
new_local = os.path.join(temp_parent, remote_name)
|
||||
dir_util.copy_tree(local, new_local)
|
||||
local = new_local
|
||||
remote = '/'.join(remote.rstrip('/').split('/')[:-1])
|
||||
try:
|
||||
self.command_output(["push", local, remote], timeout=timeout)
|
||||
except:
|
||||
raise
|
||||
finally:
|
||||
if copy_required:
|
||||
shutil.rmtree(temp_parent)
|
||||
|
||||
def pull(self, remote, local, timeout=None):
|
||||
"""Pulls a file or directory from the device.
|
||||
|
@ -1738,8 +1778,42 @@ class ADBDevice(ADBCommand):
|
|||
:raises: * ADBTimeoutError
|
||||
* ADBError
|
||||
"""
|
||||
self.command_output(["pull", remote, os.path.realpath(local)],
|
||||
timeout=timeout)
|
||||
# remove trailing /
|
||||
local = os.path.normpath(local)
|
||||
remote = os.path.normpath(remote)
|
||||
copy_required = False
|
||||
original_local = local
|
||||
if self._adb_version >= '1.0.36' and \
|
||||
os.path.isdir(local) and self.is_dir(remote):
|
||||
# See do_sync_pull in
|
||||
# https://android.googlesource.com/platform/system/core/+/master/adb/file_sync_client.cpp
|
||||
# Work around change in behavior in adb 1.0.36 where if
|
||||
# the local destination directory exists, adb pull will
|
||||
# copy the source directory *into* the destination
|
||||
# directory otherwise it will copy the source directory
|
||||
# *onto* the destination directory.
|
||||
#
|
||||
# If the destination directory does exist, pull to its
|
||||
# parent directory. If the source and destination leaf
|
||||
# directory names are different, pull the source directory
|
||||
# into a temporary directory and then copy the temporary
|
||||
# directory onto the destination.
|
||||
local_name = os.path.basename(local)
|
||||
remote_name = os.path.basename(remote)
|
||||
if local_name != remote_name:
|
||||
copy_required = True
|
||||
temp_parent = tempfile.mkdtemp()
|
||||
local = os.path.join(temp_parent, remote_name)
|
||||
else:
|
||||
local = '/'.join(local.rstrip('/').split('/')[:-1])
|
||||
try:
|
||||
self.command_output(["pull", remote, local], timeout=timeout)
|
||||
except:
|
||||
raise
|
||||
finally:
|
||||
if copy_required:
|
||||
dir_util.copy_tree(local, original_local)
|
||||
shutil.rmtree(temp_parent)
|
||||
|
||||
def rm(self, path, recursive=False, force=False, timeout=None, root=False):
|
||||
"""Delete files or directories on the device.
|
||||
|
|
Загрузка…
Ссылка в новой задаче