[Android] Make gyp/apk_install.py resilient to user actions
If a user reinstalls/uninstalls/etc an APK, then the next build of that APK should always install it (regardless of whether the md5sum of the inputs matches the recording or not). Adds an option to CheckCallAndRecord to force the call. NOTRY=true BUG=158821,234048 Review URL: https://codereview.chromium.org/14254005 git-svn-id: http://src.chromium.org/svn/trunk/src/build@196170 4ff67af0-8c30-449e-8e8b-ad334ec8d88c
This commit is contained in:
Родитель
943a38a7f5
Коммит
a23902746b
|
@ -10,6 +10,7 @@
|
|||
|
||||
import optparse
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
|
@ -20,6 +21,39 @@ BUILD_ANDROID_DIR = os.path.join(os.path.dirname(__file__), '..')
|
|||
sys.path.append(BUILD_ANDROID_DIR)
|
||||
|
||||
from pylib import android_commands
|
||||
from pylib.utils import apk_helper
|
||||
|
||||
|
||||
def GetMetadata(apk_package):
|
||||
"""Gets the metadata on the device for the apk_package apk."""
|
||||
adb = android_commands.AndroidCommands()
|
||||
output = adb.RunShellCommand('ls -l /data/app/')
|
||||
# Matches lines like:
|
||||
# -rw-r--r-- system system 7376582 2013-04-19 16:34 org.chromium.chrome.testshell.apk
|
||||
# -rw-r--r-- system system 7376582 2013-04-19 16:34 org.chromium.chrome.testshell-1.apk
|
||||
apk_matcher = lambda s: re.match('.*%s(-[0-9]*)?.apk$' % apk_package, s)
|
||||
matches = filter(apk_matcher, output)
|
||||
return matches[0] if matches else None
|
||||
|
||||
|
||||
def HasInstallMetadataChanged(apk_package, metadata_path):
|
||||
"""Checks if the metadata on the device for apk_package has changed."""
|
||||
if not os.path.exists(metadata_path):
|
||||
return True
|
||||
|
||||
with open(metadata_path, 'r') as expected_file:
|
||||
return expected_file.read() != GetMetadata(apk_package)
|
||||
|
||||
|
||||
def RecordInstallMetadata(apk_package, metadata_path):
|
||||
"""Records the metadata from the device for apk_package."""
|
||||
metadata = GetMetadata(apk_package)
|
||||
if not metadata:
|
||||
raise 'APK install failed unexpectedly.'
|
||||
|
||||
with open(metadata_path, 'w') as outfile:
|
||||
outfile.write(metadata)
|
||||
|
||||
|
||||
def main(argv):
|
||||
parser = optparse.OptionParser()
|
||||
|
@ -39,17 +73,28 @@ def main(argv):
|
|||
'install', '-r',
|
||||
options.apk_path]
|
||||
|
||||
def Install():
|
||||
build_utils.CheckCallDie(install_cmd)
|
||||
build_utils.Touch(options.install_record)
|
||||
|
||||
serial_number = android_commands.AndroidCommands().Adb().GetSerialNumber()
|
||||
apk_package = apk_helper.GetPackageName(options.apk_path)
|
||||
|
||||
metadata_path = '%s.%s.device.time.stamp' % (options.apk_path, serial_number)
|
||||
|
||||
# If the APK on the device does not match the one that was last installed by
|
||||
# the build, then the APK has to be installed (regardless of the md5 record).
|
||||
force_install = HasInstallMetadataChanged(apk_package, metadata_path)
|
||||
|
||||
def Install():
|
||||
build_utils.CheckCallDie(install_cmd)
|
||||
RecordInstallMetadata(apk_package, metadata_path)
|
||||
build_utils.Touch(options.install_record)
|
||||
|
||||
|
||||
record_path = '%s.%s.md5.stamp' % (options.apk_path, serial_number)
|
||||
md5_check.CallAndRecordIfStale(
|
||||
Install,
|
||||
record_path=record_path,
|
||||
input_paths=[options.apk_path],
|
||||
input_strings=install_cmd)
|
||||
input_strings=install_cmd,
|
||||
force=force_install)
|
||||
|
||||
if options.stamp:
|
||||
build_utils.Touch(options.stamp)
|
||||
|
|
|
@ -7,18 +7,21 @@ import os
|
|||
|
||||
|
||||
def CallAndRecordIfStale(
|
||||
function, record_path=None, input_paths=[], input_strings=[]):
|
||||
function, record_path=None, input_paths=[], input_strings=[], force=False):
|
||||
"""Calls function if the md5sum of the input paths/strings has changed.
|
||||
|
||||
The md5sum of the inputs is compared with the one stored in record_path. If
|
||||
this has changed (or the record doesn't exist), function will be called and
|
||||
the new md5sum will be recorded.
|
||||
|
||||
If force is True, the function will be called regardless of whether the
|
||||
md5sum is out of date.
|
||||
"""
|
||||
md5_checker = _Md5Checker(
|
||||
record_path=record_path,
|
||||
input_paths=input_paths,
|
||||
input_strings=input_strings)
|
||||
if md5_checker.IsStale():
|
||||
if force or md5_checker.IsStale():
|
||||
function()
|
||||
md5_checker.Write()
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ class TestMd5Check(unittest.TestCase):
|
|||
|
||||
record_path = tempfile.NamedTemporaryFile(suffix='.stamp')
|
||||
|
||||
def CheckCallAndRecord(should_call, message):
|
||||
def CheckCallAndRecord(should_call, message, force=False):
|
||||
self.called = False
|
||||
def MarkCalled():
|
||||
self.called = True
|
||||
|
@ -31,11 +31,13 @@ class TestMd5Check(unittest.TestCase):
|
|||
MarkCalled,
|
||||
record_path=record_path.name,
|
||||
input_paths=input_files,
|
||||
input_strings=input_strings)
|
||||
input_strings=input_strings,
|
||||
force=force)
|
||||
self.failUnlessEqual(should_call, self.called, message)
|
||||
|
||||
CheckCallAndRecord(True, 'should call when record doesn\'t exist')
|
||||
CheckCallAndRecord(False, 'should not call when nothing changed')
|
||||
CheckCallAndRecord(True, force=True, message='should call when forced')
|
||||
|
||||
input_file1.write('some more input')
|
||||
input_file1.flush()
|
||||
|
|
Загрузка…
Ссылка в новой задаче