OLD | NEW |
1 # Copyright 2013 The Chromium Authors. All rights reserved. | 1 # Copyright 2013 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 | 5 import hashlib |
6 import os | 6 import os |
7 | 7 |
8 | 8 |
9 def UpdateMd5ForFile(md5, path, block_size=2**16): | 9 def CallAndRecordIfStale( |
| 10 function, record_path=None, input_paths=[], input_strings=[]): |
| 11 """Calls function if the md5sum of the input paths/strings has changed. |
| 12 |
| 13 The md5sum of the inputs is compared with the one stored in record_path. If |
| 14 this has changed (or the record doesn't exist), function will be called and |
| 15 the new md5sum will be recorded. |
| 16 """ |
| 17 md5_checker = _Md5Checker( |
| 18 record_path=record_path, |
| 19 input_paths=input_paths, |
| 20 input_strings=input_strings) |
| 21 if md5_checker.IsStale(): |
| 22 function() |
| 23 md5_checker.Write() |
| 24 |
| 25 |
| 26 def _UpdateMd5ForFile(md5, path, block_size=2**16): |
10 with open(path, 'rb') as infile: | 27 with open(path, 'rb') as infile: |
11 while True: | 28 while True: |
12 data = infile.read(block_size) | 29 data = infile.read(block_size) |
13 if not data: | 30 if not data: |
14 break | 31 break |
15 md5.update(data) | 32 md5.update(data) |
16 | 33 |
17 | 34 |
18 def UpdateMd5ForDirectory(md5, dir_path): | 35 def _UpdateMd5ForDirectory(md5, dir_path): |
19 for root, _, files in os.walk(dir_path): | 36 for root, _, files in os.walk(dir_path): |
20 for f in files: | 37 for f in files: |
21 UpdateMd5ForFile(md5, os.path.join(root, f)) | 38 _UpdateMd5ForFile(md5, os.path.join(root, f)) |
22 | 39 |
23 | 40 |
24 def UpdateMd5ForPath(md5, path): | 41 def _UpdateMd5ForPath(md5, path): |
25 if os.path.isdir(path): | 42 if os.path.isdir(path): |
26 UpdateMd5ForDirectory(md5, path) | 43 _UpdateMd5ForDirectory(md5, path) |
27 else: | 44 else: |
28 UpdateMd5ForFile(md5, path) | 45 _UpdateMd5ForFile(md5, path) |
29 | 46 |
30 | 47 |
31 class Md5Checker(object): | 48 class _Md5Checker(object): |
32 def __init__(self, stamp=None, inputs=[], command=[]): | 49 def __init__(self, record_path=None, input_paths=[], input_strings=[]): |
33 self.stamp = stamp | 50 assert record_path.endswith('.stamp'), ( |
| 51 'record paths must end in \'.stamp\' so that they are easy to find ' |
| 52 'and delete') |
| 53 |
| 54 self.record_path = record_path |
34 | 55 |
35 md5 = hashlib.md5() | 56 md5 = hashlib.md5() |
36 for i in inputs: | 57 for i in sorted(input_paths): |
37 UpdateMd5ForPath(md5, i) | 58 _UpdateMd5ForPath(md5, i) |
38 for s in command: | 59 for s in input_strings: |
39 md5.update(s) | 60 md5.update(s) |
40 self.new_digest = md5.hexdigest() | 61 self.new_digest = md5.hexdigest() |
41 | 62 |
42 self.old_digest = '' | 63 self.old_digest = '' |
43 if os.path.exists(stamp): | 64 if os.path.exists(self.record_path): |
44 with open(stamp, 'r') as old_stamp: | 65 with open(self.record_path, 'r') as old_record: |
45 self.old_digest = old_stamp.read() | 66 self.old_digest = old_record.read() |
46 | 67 |
47 def IsStale(self): | 68 def IsStale(self): |
48 return self.old_digest != self.new_digest | 69 return self.old_digest != self.new_digest |
49 | 70 |
50 def Write(self): | 71 def Write(self): |
51 with open(self.stamp, 'w') as new_stamp: | 72 with open(self.record_path, 'w') as new_record: |
52 new_stamp.write(self.new_digest) | 73 new_record.write(self.new_digest) |
OLD | NEW |