Bug 1328301 - handle push/pull directory semantics changes in adb 1.0.36 for devicemanagerADB, r=gbrown

This commit is contained in:
Bob Clary 2017-01-21 09:49:56 -08:00
Родитель 88345f4996
Коммит 2d71f27173
1 изменённых файлов: 73 добавлений и 14 удалений

Просмотреть файл

@ -5,11 +5,12 @@
import logging
import re
import os
import shutil
import tempfile
import time
import traceback
from distutils import dir_util
from devicemanager import DeviceManager, DMError
from mozprocess import ProcessHandler
import mozfile
@ -32,6 +33,7 @@ class DeviceManagerADB(DeviceManager):
_pollingInterval = 0.01
_packageName = None
_tempDir = None
_adb_version = None
connected = False
def __init__(self, host=None, port=5555, retryLimit=5, packageName='fennec',
@ -271,18 +273,42 @@ class DeviceManagerADB(DeviceManager):
self._useZip = False
self.pushDir(localDir, remoteDir, retryLimit=retryLimit, timeout=timeout)
else:
# If the remote directory exists, newer implementations of
# "adb push" will create a sub-directory, while older versions
# will not! Bug 1285040
self.mkDirs(remoteDir + "/x")
self.removeDir(remoteDir)
tmpDir = tempfile.mkdtemp()
# copytree's target dir must not already exist, so create a subdir
tmpDirTarget = os.path.join(tmpDir, "tmp")
shutil.copytree(localDir, tmpDirTarget)
self._checkCmd(["push", tmpDirTarget, remoteDir],
retryLimit=retryLimit, timeout=timeout)
mozfile.remove(tmpDir)
localDir = os.path.normpath(localDir)
remoteDir = os.path.normpath(remoteDir)
copyRequired = False
if self._adb_version >= '1.0.36' and \
os.path.isdir(localDir) and self.dirExists(remoteDir):
# 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.
localName = os.path.basename(localDir)
remoteName = os.path.basename(remoteDir)
if localName != remoteName:
copyRequired = True
tempParent = tempfile.mkdtemp()
newLocal = os.path.join(tempParent, remoteName)
dir_util.copy_tree(localDir, newLocal)
localDir = newLocal
remoteDir = '/'.join(remoteDir.rstrip('/').split('/')[:-1])
try:
self._checkCmd(["push", localDir, remoteDir],
retryLimit=retryLimit, timeout=timeout)
except:
raise
finally:
if copyRequired:
mozfile.remove(tempParent)
def dirExists(self, remotePath):
self._detectLsModifier()
@ -464,7 +490,37 @@ class DeviceManagerADB(DeviceManager):
self._runPull(remoteFile, localFile)
def getDirectory(self, remoteDir, localDir, checkDir=True):
localDir = os.path.normpath(localDir)
remoteDir = os.path.normpath(remoteDir)
copyRequired = False
originalLocal = localDir
if self._adb_version >= '1.0.36' and \
os.path.isdir(localDir) and self.dirExists(remoteDir):
# 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.
localName = os.path.basename(localDir)
remoteName = os.path.basename(remoteDir)
if localName != remoteName:
copyRequired = True
tempParent = tempfile.mkdtemp()
localDir = os.path.join(tempParent, remoteName)
else:
localDir = '/'.join(localDir.rstrip('/').split('/')[:-1])
self._runCmd(["pull", remoteDir, localDir]).wait()
if copyRequired:
dir_util.copy_tree(localDir, originalLocal)
mozfile.remove(tempParent)
def validateFile(self, remoteFile, localFile):
md5Remote = self._getRemoteHash(remoteFile)
@ -682,7 +738,10 @@ class DeviceManagerADB(DeviceManager):
raise DMError("invalid adb path, or adb not executable: %s" % self._adbPath)
try:
self._checkCmd(["version"], timeout=self.short_timeout)
proc = self._runCmd(["version"], timeout=self.short_timeout)
re_version = re.compile(r'Android Debug Bridge version (.*)')
self._adb_version = re_version.match(proc.output[0]).group(1)
self._logger.info("Detected adb %s", self._adb_version)
except os.error as err:
raise DMError(
"unable to execute ADB (%s): ensure Android SDK is installed "