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

Side by Side Diff: mojo/tools/mopy/transitive_hash.py

Issue 728783003: Add infrastructure to run tests on android. (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Follow review Created 6 years 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 unified diff | Download patch
« no previous file with comments | « mojo/tools/mopy/memoize.py ('k') | mojo/tools/test_runner.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # Copyright 2014 The Chromium Authors. All rights reserved. 1 # Copyright 2014 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 import hashlib
6 import logging 5 import logging
7 import platform 6 import platform
8 import subprocess 7 import subprocess
9 import sys 8 import sys
10 9
11 # pylint: disable=E0611 10 # pylint: disable=E0611
12 from hashlib import sha256 11 from hashlib import sha256
13 # pylint: enable=E0611 12 # pylint: enable=E0611
14 from os.path import basename, realpath 13 from os.path import basename, realpath
15 14
15 from mopy.file_hash import file_hash
16 from mopy.memoize import memoize
17
16 _logging = logging.getLogger() 18 _logging = logging.getLogger()
17 19
18 # pylint: disable=C0301 20 @memoize
19 # Based on/taken from
20 # http://code.activestate.com/recipes/578231-probably-the-fastest-memoization- decorator-in-the-/
21 # (with cosmetic changes).
22 # pylint: enable=C0301
23 def _memoize(f):
24 """Memoization decorator for a function taking a single argument."""
25 class Memoize(dict):
26 def __missing__(self, key):
27 rv = self[key] = f(key)
28 return rv
29 return Memoize().__getitem__
30
31 @_memoize
32 def _file_hash(filename):
33 """Returns a string representing the hash of the given file."""
34 _logging.debug("Hashing %s ...", filename)
35 with open(filename, mode='rb') as f:
36 m = hashlib.sha256()
37 while True:
38 block = f.read(4096)
39 if not block:
40 break
41 m.update(block)
42 _logging.debug(" => %s", m.hexdigest())
43 return m.hexdigest()
44
45 @_memoize
46 def _get_dependencies(filename): 21 def _get_dependencies(filename):
47 """Returns a list of filenames for files that the given file depends on.""" 22 """Returns a list of filenames for files that the given file depends on."""
48 if platform.system() == 'Windows': 23 if platform.system() == 'Windows':
49 # There's no ldd on Windows. We can try to bundle or require depends, but 24 # There's no ldd on Windows. We can try to bundle or require depends, but
50 # given that we're not supporting component build this seems low priority. 25 # given that we're not supporting component build this seems low priority.
51 return [] 26 return []
52 _logging.debug("Getting dependencies for %s ...", filename) 27 _logging.debug("Getting dependencies for %s ...", filename)
53 lines = subprocess.check_output(['ldd', filename]).splitlines() 28 lines = subprocess.check_output(['ldd', filename]).splitlines()
54 rv = [] 29 rv = []
55 for line in lines: 30 for line in lines:
56 i = line.find('/') 31 i = line.find('/')
57 if i < 0: 32 if i < 0:
58 _logging.debug(" => no file found in line: %s", line) 33 _logging.debug(" => no file found in line: %s", line)
59 continue 34 continue
60 rv.append(line[i:].split(None, 1)[0]) 35 rv.append(line[i:].split(None, 1)[0])
61 _logging.debug(" => %s", rv) 36 _logging.debug(" => %s", rv)
62 return rv 37 return rv
63 38
64 def transitive_hash(filename): 39 def transitive_hash(filename):
65 """Returns a string that represents the "transitive" hash of the given 40 """Returns a string that represents the "transitive" hash of the given
66 file. The transitive hash is a hash of the file and all the shared libraries 41 file. The transitive hash is a hash of the file and all the shared libraries
67 on which it depends (done in an order-independent way).""" 42 on which it depends (done in an order-independent way)."""
68 hashes = set() 43 hashes = set()
69 to_hash = [filename] 44 to_hash = [filename]
70 while to_hash: 45 while to_hash:
71 current_filename = realpath(to_hash.pop()) 46 current_filename = realpath(to_hash.pop())
72 current_hash = _file_hash(current_filename) 47 current_hash = file_hash(current_filename)
73 if current_hash in hashes: 48 if current_hash in hashes:
74 _logging.debug("Already seen %s (%s) ...", current_filename, current_hash) 49 _logging.debug("Already seen %s (%s) ...", current_filename, current_hash)
75 continue 50 continue
76 _logging.debug("Haven't seen %s (%s) ...", current_filename, current_hash) 51 _logging.debug("Haven't seen %s (%s) ...", current_filename, current_hash)
77 hashes.add(current_hash) 52 hashes.add(current_hash)
78 to_hash.extend(_get_dependencies(current_filename)) 53 to_hash.extend(_get_dependencies(current_filename))
79 return sha256('|'.join(sorted(hashes))).hexdigest() 54 return sha256('|'.join(sorted(hashes))).hexdigest()
80 55
81 def main(argv): 56 def main(argv):
82 logging.basicConfig() 57 logging.basicConfig()
(...skipping 13 matching lines...) Expand all
96 for filename in argv[1:]: 71 for filename in argv[1:]:
97 try: 72 try:
98 print transitive_hash(filename), filename 73 print transitive_hash(filename), filename
99 except subprocess.CalledProcessError: 74 except subprocess.CalledProcessError:
100 print "ERROR", filename 75 print "ERROR", filename
101 rv = 1 76 rv = 1
102 return rv 77 return rv
103 78
104 if __name__ == '__main__': 79 if __name__ == '__main__':
105 sys.exit(main(sys.argv)) 80 sys.exit(main(sys.argv))
OLDNEW
« no previous file with comments | « mojo/tools/mopy/memoize.py ('k') | mojo/tools/test_runner.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698