summaryrefslogtreecommitdiffstats
path: root/build
diff options
context:
space:
mode:
authorcjhopman@chromium.org <cjhopman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-04-16 17:05:20 +0000
committercjhopman@chromium.org <cjhopman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-04-16 17:05:20 +0000
commitba50fd8275458583684065943041fdbd96254713 (patch)
treebe19ae14cd8a9a1d12b961f6c5fa33f9302ec438 /build
parentbfe06bc74b95f3c1ca8e41afcf9bed115b12679b (diff)
downloadchromium_src-ba50fd8275458583684065943041fdbd96254713.zip
chromium_src-ba50fd8275458583684065943041fdbd96254713.tar.gz
chromium_src-ba50fd8275458583684065943041fdbd96254713.tar.bz2
[Android] Refactor md5_check + add tests
This adds a function md5_check.CallAndRecordIfStale that makes the common (and currently only) use of Md5Checker much simpler (i.e just call this function). All the users of md5_check are updated to use this function, and everything else in md5_check is no longer part of the public API. Also, adds tests for the md5_check module. These are only run manually currently. BUG=158821 Review URL: https://codereview.chromium.org/14263006 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@194377 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'build')
-rwxr-xr-xbuild/android/gyp/apk_install.py13
-rwxr-xr-xbuild/android/gyp/create_device_library_links.py12
-rwxr-xr-xbuild/android/gyp/dex.py16
-rwxr-xr-xbuild/android/gyp/jar.py17
-rwxr-xr-xbuild/android/gyp/jar_toc.py14
-rwxr-xr-xbuild/android/gyp/javac.py16
-rwxr-xr-xbuild/android/gyp/push_libraries.py14
-rw-r--r--build/android/gyp/util/md5_check.py55
-rw-r--r--build/android/gyp/util/md5_check_test.py67
9 files changed, 158 insertions, 66 deletions
diff --git a/build/android/gyp/apk_install.py b/build/android/gyp/apk_install.py
index f8e7caa..8f1e69b 100755
--- a/build/android/gyp/apk_install.py
+++ b/build/android/gyp/apk_install.py
@@ -38,13 +38,12 @@ def main(argv):
options.apk_path]
serial_number = android_commands.AndroidCommands().Adb().GetSerialNumber()
- md5_stamp = '%s.%s.md5' % (options.apk_path, serial_number)
-
- md5_checker = md5_check.Md5Checker(
- stamp=md5_stamp, inputs=[options.apk_path], command=install_cmd)
- if md5_checker.IsStale():
- build_utils.CheckCallDie(install_cmd)
- md5_checker.Write()
+ record_path = '%s.%s.md5.stamp' % (options.apk_path, serial_number)
+ md5_check.CallAndRecordIfStale(
+ lambda: build_utils.CheckCallDie(install_cmd),
+ record_path=record_path,
+ input_paths=[options.apk_path],
+ input_strings=install_cmd)
if options.stamp:
build_utils.Touch(options.stamp)
diff --git a/build/android/gyp/create_device_library_links.py b/build/android/gyp/create_device_library_links.py
index e71f727..48aa61e 100755
--- a/build/android/gyp/create_device_library_links.py
+++ b/build/android/gyp/create_device_library_links.py
@@ -47,14 +47,16 @@ def CreateLinks(options):
serial_number = adb.Adb().GetSerialNumber()
for lib in libraries:
host_path = os.path.join(options.libraries_dir, lib)
-
- md5_stamp = '%s.%s.link.md5' % (host_path, serial_number)
- md5_checker = md5_check.Md5Checker(stamp=md5_stamp, inputs=[host_path])
- if md5_checker.IsStale():
+ def CreateLink():
link = '/data/data/' + apk_package + '/lib/' + lib
target = options.target_dir + '/' + lib
RunLinkCommand(adb, target, link)
- md5_checker.Write()
+
+ record_path = '%s.%s.link.md5.stamp' % (host_path, serial_number)
+ md5_check.CallAndRecordIfStale(
+ CreateLink,
+ record_path=record_path,
+ input_paths=[host_path])
def main(argv):
diff --git a/build/android/gyp/dex.py b/build/android/gyp/dex.py
index 99834c4..84a9c63 100755
--- a/build/android/gyp/dex.py
+++ b/build/android/gyp/dex.py
@@ -17,14 +17,14 @@ def DoDex(options, paths):
dx_binary = os.path.join(options.android_sdk_root, 'platform-tools', 'dx')
dex_cmd = [dx_binary, '--dex', '--output', options.dex_path] + paths
- md5_stamp = '%s.md5' % options.dex_path
- md5_checker = md5_check.Md5Checker(
- stamp=md5_stamp, inputs=paths, command=dex_cmd)
- if md5_checker.IsStale():
- build_utils.CheckCallDie(dex_cmd, suppress_output=True)
- else:
- build_utils.Touch(options.dex_path)
- md5_checker.Write()
+ record_path = '%s.md5.stamp' % options.dex_path
+ md5_check.CallAndRecordIfStale(
+ lambda: build_utils.CheckCallDie(dex_cmd, suppress_output=True),
+ record_path=record_path,
+ input_paths=paths,
+ input_strings=dex_cmd)
+
+ build_utils.Touch(options.dex_path)
def main(argv):
diff --git a/build/android/gyp/jar.py b/build/android/gyp/jar.py
index 7618def..6d4fe12 100755
--- a/build/android/gyp/jar.py
+++ b/build/android/gyp/jar.py
@@ -28,15 +28,14 @@ def DoJar(options):
class_files_rel = [os.path.relpath(f, jar_cwd) for f in class_files]
jar_cmd = ['jar', 'cf0', jar_path] + class_files_rel
-
- md5_stamp = '%s.md5' % options.jar_path
- md5_checker = md5_check.Md5Checker(
- stamp=md5_stamp, inputs=class_files, command=jar_cmd)
- if md5_checker.IsStale():
- build_utils.CheckCallDie(jar_cmd, cwd=jar_cwd)
- else:
- build_utils.Touch(options.jar_path)
- md5_checker.Write()
+ record_path = '%s.md5.stamp' % options.jar_path
+ md5_check.CallAndRecordIfStale(
+ lambda: build_utils.CheckCallDie(jar_cmd, cwd=jar_cwd),
+ record_path=record_path,
+ input_paths=class_files,
+ input_strings=jar_cmd)
+
+ build_utils.Touch(options.jar_path)
def main(argv):
diff --git a/build/android/gyp/jar_toc.py b/build/android/gyp/jar_toc.py
index b40f43d..9db9d26 100755
--- a/build/android/gyp/jar_toc.py
+++ b/build/android/gyp/jar_toc.py
@@ -81,13 +81,13 @@ def UpdateToc(jar_path, toc_path):
def DoJarToc(options):
jar_path = options.jar_path
toc_path = options.toc_path
- md5_stamp_path = '%s.md5' % toc_path
- md5_checker = md5_check.Md5Checker(stamp=md5_stamp_path, inputs=[jar_path])
- if md5_checker.IsStale():
- UpdateToc(jar_path, toc_path)
- md5_checker.Write()
- else:
- build_utils.Touch(toc_path)
+ record_path = '%s.md5.stamp' % toc_path
+ md5_check.CallAndRecordIfStale(
+ lambda: UpdateToc(jar_path, toc_path),
+ record_path=record_path,
+ input_paths=[jar_path],
+ )
+ build_utils.Touch(toc_path)
def main(argv):
diff --git a/build/android/gyp/javac.py b/build/android/gyp/javac.py
index cbd4293..c117004 100755
--- a/build/android/gyp/javac.py
+++ b/build/android/gyp/javac.py
@@ -52,12 +52,7 @@ def DoJavac(options):
'-Xlint:deprecation',
] + java_files
- md5_stamp = '%s/javac.md5' % options.output_dir
- md5_checker = md5_check.Md5Checker(
- stamp=md5_stamp,
- inputs=java_files + jar_inputs,
- command=javac_cmd)
- if md5_checker.IsStale():
+ def Compile():
# Delete the classes directory. This ensures that all .class files in the
# output are actually from the input .java files. For example, if a .java
# file is deleted or an inner class is removed, the classes directory should
@@ -66,7 +61,14 @@ def DoJavac(options):
build_utils.MakeDirectory(output_dir)
suppress_output = not options.chromium_code
build_utils.CheckCallDie(javac_cmd, suppress_output=suppress_output)
- md5_checker.Write()
+
+ record_path = '%s/javac.md5.stamp' % options.output_dir
+ md5_check.CallAndRecordIfStale(
+ Compile,
+ record_path=record_path,
+ input_paths=java_files + jar_inputs,
+ input_strings=javac_cmd)
+
def main(argv):
parser = optparse.OptionParser()
diff --git a/build/android/gyp/push_libraries.py b/build/android/gyp/push_libraries.py
index e586d0b..70a1fcb 100755
--- a/build/android/gyp/push_libraries.py
+++ b/build/android/gyp/push_libraries.py
@@ -27,19 +27,21 @@ def DoPush(options):
adb = android_commands.AndroidCommands()
serial_number = adb.Adb().GetSerialNumber()
- needs_directory = True
+ # A list so that it is modifiable in Push below.
+ needs_directory = [True]
for lib in libraries:
device_path = os.path.join(options.device_dir, lib)
host_path = os.path.join(options.libraries_dir, lib)
- md5_stamp = '%s.%s.push.md5' % (host_path, serial_number)
- md5_checker = md5_check.Md5Checker(stamp=md5_stamp, inputs=[host_path])
- if md5_checker.IsStale():
+ def Push():
if needs_directory:
adb.RunShellCommand('mkdir ' + options.device_dir)
- needs_directory = False
+ needs_directory[:] = [] # = False
adb.PushIfNeeded(host_path, device_path)
- md5_checker.Write()
+
+ record_path = '%s.%s.push.md5.stamp' % (host_path, serial_number)
+ md5_check.CallAndRecordIfStale(
+ Push, record_path=record_path, input_paths=[host_path])
def main(argv):
diff --git a/build/android/gyp/util/md5_check.py b/build/android/gyp/util/md5_check.py
index 47f1ec9..acf707c 100644
--- a/build/android/gyp/util/md5_check.py
+++ b/build/android/gyp/util/md5_check.py
@@ -6,7 +6,24 @@ import hashlib
import os
-def UpdateMd5ForFile(md5, path, block_size=2**16):
+def CallAndRecordIfStale(
+ function, record_path=None, input_paths=[], input_strings=[]):
+ """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.
+ """
+ md5_checker = _Md5Checker(
+ record_path=record_path,
+ input_paths=input_paths,
+ input_strings=input_strings)
+ if md5_checker.IsStale():
+ function()
+ md5_checker.Write()
+
+
+def _UpdateMd5ForFile(md5, path, block_size=2**16):
with open(path, 'rb') as infile:
while True:
data = infile.read(block_size)
@@ -15,38 +32,42 @@ def UpdateMd5ForFile(md5, path, block_size=2**16):
md5.update(data)
-def UpdateMd5ForDirectory(md5, dir_path):
+def _UpdateMd5ForDirectory(md5, dir_path):
for root, _, files in os.walk(dir_path):
for f in files:
- UpdateMd5ForFile(md5, os.path.join(root, f))
+ _UpdateMd5ForFile(md5, os.path.join(root, f))
-def UpdateMd5ForPath(md5, path):
+def _UpdateMd5ForPath(md5, path):
if os.path.isdir(path):
- UpdateMd5ForDirectory(md5, path)
+ _UpdateMd5ForDirectory(md5, path)
else:
- UpdateMd5ForFile(md5, path)
+ _UpdateMd5ForFile(md5, path)
+
+class _Md5Checker(object):
+ def __init__(self, record_path=None, input_paths=[], input_strings=[]):
+ assert record_path.endswith('.stamp'), (
+ 'record paths must end in \'.stamp\' so that they are easy to find '
+ 'and delete')
-class Md5Checker(object):
- def __init__(self, stamp=None, inputs=[], command=[]):
- self.stamp = stamp
+ self.record_path = record_path
md5 = hashlib.md5()
- for i in inputs:
- UpdateMd5ForPath(md5, i)
- for s in command:
+ for i in sorted(input_paths):
+ _UpdateMd5ForPath(md5, i)
+ for s in input_strings:
md5.update(s)
self.new_digest = md5.hexdigest()
self.old_digest = ''
- if os.path.exists(stamp):
- with open(stamp, 'r') as old_stamp:
- self.old_digest = old_stamp.read()
+ if os.path.exists(self.record_path):
+ with open(self.record_path, 'r') as old_record:
+ self.old_digest = old_record.read()
def IsStale(self):
return self.old_digest != self.new_digest
def Write(self):
- with open(self.stamp, 'w') as new_stamp:
- new_stamp.write(self.new_digest)
+ with open(self.record_path, 'w') as new_record:
+ new_record.write(self.new_digest)
diff --git a/build/android/gyp/util/md5_check_test.py b/build/android/gyp/util/md5_check_test.py
new file mode 100644
index 0000000..a18942e
--- /dev/null
+++ b/build/android/gyp/util/md5_check_test.py
@@ -0,0 +1,67 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import tempfile
+import unittest
+
+import md5_check
+
+
+class TestMd5Check(unittest.TestCase):
+ def testCallAndRecordIfStale(self):
+ input_strings = ['string1', 'string2']
+ input_file1 = tempfile.NamedTemporaryFile()
+ input_file2 = tempfile.NamedTemporaryFile()
+ file1_contents = 'input file 1'
+ file2_contents = 'input file 2'
+ input_file1.write(file1_contents)
+ input_file1.flush()
+ input_file2.write(file2_contents)
+ input_file2.flush()
+ input_files = [input_file1.name, input_file2.name]
+
+ record_path = tempfile.NamedTemporaryFile(suffix='.stamp')
+
+ def CheckCallAndRecord(should_call, message):
+ self.called = False
+ def MarkCalled():
+ self.called = True
+ md5_check.CallAndRecordIfStale(
+ MarkCalled,
+ record_path=record_path.name,
+ input_paths=input_files,
+ input_strings=input_strings)
+ self.failUnlessEqual(should_call, self.called, message)
+
+ CheckCallAndRecord(True, 'should call when record doesn\'t exist')
+ CheckCallAndRecord(False, 'should not call when nothing changed')
+
+ input_file1.write('some more input')
+ input_file1.flush()
+ CheckCallAndRecord(True, 'changed input file should trigger call')
+
+ input_files = input_files[::-1]
+ CheckCallAndRecord(False, 'reordering of inputs shouldn\'t trigger call')
+
+ input_files = input_files[:1]
+ CheckCallAndRecord(True, 'removing file should trigger call')
+
+ input_files.append(input_file2.name)
+ CheckCallAndRecord(True, 'added input file should trigger call')
+
+ input_strings[0] = input_strings[0] + ' a bit longer'
+ CheckCallAndRecord(True, 'changed input string should trigger call')
+
+ input_strings = input_strings[::-1]
+ CheckCallAndRecord(True, 'reordering of string inputs should trigger call')
+
+ input_strings = input_strings[:1]
+ CheckCallAndRecord(True, 'removing a string should trigger call')
+
+ input_strings.append('a brand new string')
+ CheckCallAndRecord(True, 'added input string should trigger call')
+
+
+if __name__ == '__main__':
+ unittest.main()