Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 #!/usr/bin/env python | |
| 2 # Copyright 2015 The Chromium Authors. All rights reserved. | |
| 3 # Use of this source code is governed by a BSD-style license that can be | |
| 4 # found in the LICENSE file. | |
| 5 | |
| 6 """Checks that released mojom.dart files in the source tree are up to date""" | |
| 7 | |
| 8 import os | |
| 9 import subprocess | |
| 10 import sys | |
| 11 | |
| 12 SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) | |
| 13 SRC_DIR = os.path.dirname( | |
| 14 os.path.dirname( | |
| 15 os.path.dirname( | |
| 16 os.path.dirname(SCRIPT_DIR)))) | |
| 17 | |
| 18 PACKAGES_DIR = os.path.join(SRC_DIR, 'mojo', 'dart', 'packages') | |
| 19 | |
| 20 # Script that calculates mojom output paths. | |
| 21 DART_OUTPUTS_SCRIPT = os.path.join(SRC_DIR, | |
| 22 'mojo', | |
| 23 'public', | |
| 24 'tools', | |
| 25 'bindings', | |
| 26 'mojom_list_dart_outputs.py') | |
| 27 | |
| 28 # Runs command line in args from cwd. Returns the output as a string. | |
| 29 def run(cwd, args): | |
| 30 return subprocess.check_output(args, cwd=cwd) | |
| 31 | |
| 32 | |
| 33 def _print_regenerate_message(package): | |
| 34 print('*** Dart Generated Bindings Check Failed:') | |
|
jamesr
2015/11/17 01:35:07
this is a good place to use python's """, i.e.
pr
Cutch
2015/11/17 18:17:15
Done.
| |
| 35 print('You must regenerate bindings for %s.' % package) | |
| 36 print('From the src directory, run:') | |
| 37 print('$ dart mojo/dart/packages/mojom/bin/mojom.dart gen -m mojo/public ' + | |
| 38 '-r mojo/ --output mojo/dart/packages/'); | |
| 39 | |
| 40 | |
| 41 # Returns a map from package name to source directory. | |
| 42 def _build_package_map(): | |
| 43 packages = {} | |
| 44 for package in os.listdir(PACKAGES_DIR): | |
| 45 package_path = os.path.join(PACKAGES_DIR, package) | |
| 46 # Skip everything but directories. | |
| 47 if not os.path.isdir(package_path): | |
| 48 continue | |
| 49 packages[package] = package_path | |
| 50 return packages | |
| 51 | |
| 52 | |
| 53 # Returns a list of paths to .mojom files vended by package_name. | |
| 54 def _find_mojoms_for_package(package_name): | |
| 55 # Run git grep for all .mojom files with DartPackage="package_name" | |
| 56 try: | |
| 57 output = run(SRC_DIR, ['git', | |
| 58 'grep', | |
| 59 '--name-only', | |
| 60 'DartPackage="' + package_name + '"', | |
| 61 '--', | |
| 62 '*.mojom']) | |
| 63 except subprocess.CalledProcessError as e: | |
| 64 # git grep exits with code 1 if nothing was found. | |
| 65 if e.returncode == 1: | |
| 66 return [] | |
| 67 | |
| 68 # Process output | |
| 69 mojoms = [] | |
| 70 for line in output.splitlines(): | |
| 71 line = line.strip() | |
| 72 # Skip empty lines. | |
| 73 if not line: | |
| 74 continue | |
| 75 mojoms.append(line) | |
| 76 return mojoms | |
| 77 | |
| 78 | |
| 79 # Return the list of expected mojom.dart files for a package. | |
| 80 def _expected_mojom_darts_for_package(mojoms): | |
| 81 output = run(SRC_DIR, ['python', | |
| 82 DART_OUTPUTS_SCRIPT, | |
| 83 '--mojoms'] + mojoms) | |
| 84 mojom_darts = [] | |
| 85 for line in output.splitlines(): | |
| 86 line = line.strip() | |
| 87 # Skip empty lines. | |
| 88 if not line: | |
| 89 continue | |
| 90 mojom_darts.append(line) | |
| 91 return mojom_darts | |
| 92 | |
| 93 | |
| 94 # Returns a map indexed by output mojom.dart name with the value of | |
| 95 # the modification time of the .mojom file in the source tree. | |
| 96 def _build_expected_map(mojoms, mojom_darts): | |
| 97 assert(len(mojom_darts) == len(mojoms)) | |
| 98 expected = {} | |
| 99 for i in range(0, len(mojoms)): | |
| 100 mojom_path = os.path.join(SRC_DIR, mojoms[i]) | |
| 101 expected[mojom_darts[i]] = os.path.getmtime(mojom_path) | |
| 102 return expected | |
| 103 | |
| 104 | |
| 105 # Returns a map indexed by output mojom.dart name with the value of | |
| 106 # the modification time of the .mojom.dart file in the source tree. | |
| 107 def _build_current_map(package): | |
| 108 current = {} | |
| 109 package_path = os.path.join(PACKAGES_DIR, package) | |
| 110 for directory, _, files in os.walk(package_path): | |
| 111 for filename in files: | |
| 112 if filename.endswith('.mojom.dart'): | |
| 113 path = os.path.abspath(os.path.join(directory, filename)) | |
| 114 relpath = os.path.relpath(path, start=PACKAGES_DIR) | |
| 115 current[relpath] = os.path.getmtime(path) | |
| 116 return current | |
| 117 | |
| 118 | |
| 119 # Checks if a mojom.dart file we expected in the source tree isn't there. | |
| 120 def _check_new(package, expected, current): | |
| 121 checkFailure = False | |
| 122 for mojom_dart in expected: | |
| 123 if not current.get(mojom_dart): | |
| 124 print("Package %s missing %s" % (package, mojom_dart)) | |
| 125 checkFailure = True | |
| 126 return checkFailure | |
| 127 | |
| 128 | |
| 129 # Checks if a mojom.dart file exists without an associated .mojom file. | |
| 130 def _check_delete(package, expected, current): | |
| 131 checkFailure = False | |
| 132 for mojom_dart in current: | |
| 133 if not expected.get(mojom_dart): | |
| 134 print("Package %s no longer has %s." % (package, mojom_dart)) | |
| 135 print("Delete %s", os.path.join(PACKAGES_DIR, mojom_dart)) | |
| 136 checkFailure = True | |
| 137 return checkFailure | |
| 138 | |
| 139 | |
| 140 # Checks if a .mojom.dart file is older than the associated .mojom file. | |
| 141 # TODO(johnmccutchan): Handle the case where someone edited a .mojom.dart file | |
| 142 # directly instead of through the bindings generation script. | |
| 143 def _check_stale(package, expected, current): | |
| 144 checkFailure = False | |
| 145 for mojom_dart in expected: | |
|
jamesr
2015/11/17 01:35:07
the mix of hacker_style and camelCase is confusing
Cutch
2015/11/17 18:17:15
Done. I was switching between Dart and Python yest
| |
| 146 # Missing mojom.dart file in source tree case handled by _check_new. | |
| 147 source_mtime = expected[mojom_dart] | |
| 148 if not current.get(mojom_dart): | |
| 149 continue | |
| 150 generated_mtime = current[mojom_dart] | |
| 151 if generated_mtime < source_mtime: | |
| 152 print("Package %s has old %s" % (package, mojom_dart)) | |
| 153 checkFailure = True | |
| 154 return checkFailure | |
| 155 | |
| 156 | |
| 157 # Returns True if any checks fail. | |
| 158 def _check(package, expected, current): | |
| 159 checkFailure = False | |
| 160 if _check_new(package, expected, current): | |
| 161 checkFailure = True | |
| 162 if _check_stale(package, expected, current): | |
| 163 checkFailure = True | |
| 164 if _check_delete(package, expected, current): | |
| 165 checkFailure = True | |
| 166 # No check failures. | |
| 167 return checkFailure | |
| 168 | |
| 169 def main(): | |
| 170 packages = _build_package_map() | |
| 171 checkFailed = False | |
| 172 for package in packages: | |
| 173 mojoms = _find_mojoms_for_package(package) | |
| 174 if not mojoms: | |
| 175 continue | |
| 176 mojom_darts = _expected_mojom_darts_for_package(mojoms) | |
| 177 # We only feed in mojom files with DartPackage annotations, therefore, we | |
| 178 # should have a 1:1 mapping from mojoms[i] to mojom_darts[i]. | |
| 179 assert(len(mojom_darts) == len(mojoms)) | |
| 180 expected = _build_expected_map(mojoms, mojom_darts) | |
| 181 current = _build_current_map(package) | |
| 182 if _check(package, expected, current): | |
| 183 _print_regenerate_message(package) | |
| 184 checkFailed = True | |
| 185 if checkFailed: | |
| 186 sys.exit(2) | |
| 187 print('OK.') | |
| 188 sys.exit(0) | |
| 189 | |
| 190 if __name__ == '__main__': | |
| 191 sys.exit(main()) | |
| OLD | NEW |