| #!/usr/bin/env python2.7 | |
| # Copyright 2020 The Fuchsia Authors. All rights reserved. | |
| # Use of this source code is governed by a BSD-style license that can be | |
| # found in the LICENSE file. | |
| '''Converts instances of //build/package.gni to use the `binaries` parameter | |
| instead of the deprecated `binary`. | |
| ''' | |
| import argparse | |
| import fileinput | |
| import os | |
| import re | |
| import sys | |
| from common import fx_format | |
| def main(): | |
| parser = argparse.ArgumentParser(description=__doc__) | |
| parser.add_argument( | |
| '--base', | |
| help='Path to the directory in which files will be fixed', | |
| required=True) | |
| args = parser.parse_args() | |
| # Fix manifest files. | |
| manifest_paths = [] | |
| for root, _, files in os.walk(args.base): | |
| for file in files: | |
| name, extension = os.path.splitext(file) | |
| if extension != '.cmx': | |
| continue | |
| file_path = os.path.join(root, file) | |
| with open(file_path, 'r') as manifest_file: | |
| contents = manifest_file.read() | |
| if '"bin/app"' not in contents: | |
| continue | |
| contents = contents.replace('"bin/app"', '"bin/' + name + '"') | |
| with open(file_path, 'w') as manifest_file: | |
| manifest_file.write(contents) | |
| manifest_paths.append(file_path) | |
| # Fix build files. | |
| build_changes = {} # file path --> list of affected binaries | |
| for root, _, files in os.walk(args.base): | |
| for file in files: | |
| if file != 'BUILD.gn': | |
| continue | |
| file_path = os.path.join(root, file) | |
| found_reference = False | |
| for line in fileinput.FileInput(file_path, inplace=True): | |
| match = re.match('^(\s*)binary = "([^"]+)"\s*$', line) | |
| if match: | |
| found_reference = True | |
| line = match.group( | |
| 1) + 'binaries = [{ name = "' + match.group(2) + '" }]' | |
| build_changes.setdefault(file_path, | |
| []).append(match.group(2)) | |
| sys.stdout.write(line) | |
| if found_reference: | |
| fx_format(file_path) | |
| # Cross-reference the two lists of modified files and attempt to identify | |
| # issues. | |
| print('-----------------------------') | |
| print('Updated %d component manifest files' % len(manifest_paths)) | |
| print( | |
| 'Updated %d references in %d build files' % ( | |
| sum([len(v) for v in build_changes.values()], | |
| 0), len(build_changes.keys()))) | |
| print('') | |
| # First off, build a list of manifest files we expect to see given the | |
| # changes made to build files. | |
| expected_manifest_paths = [] | |
| matched_manifest_paths = [] | |
| for build_file, binaries in sorted(build_changes.iteritems()): | |
| base_dir = os.path.dirname(build_file) | |
| for binary in binaries: | |
| manifest = os.path.join(base_dir, 'meta', binary + '.cmx') | |
| if manifest in manifest_paths: | |
| # We found a manifest exactly where we expected it: great! | |
| manifest_paths.remove(manifest) | |
| matched_manifest_paths.append(manifest) | |
| continue | |
| if '_' in binary: | |
| # Since '_' is technically not allowed in package URIs, some | |
| # manifest files are renamed by turning '_' into '-'. | |
| alternate_manifest = os.path.join( | |
| base_dir, 'meta', | |
| binary.replace('_', '-') + '.cmx') | |
| if alternate_manifest in manifest_paths: | |
| manifest_paths.remove(alternate_manifest) | |
| matched_manifest_paths.append(alternate_manifest) | |
| continue | |
| expected_manifest_paths.append(manifest) | |
| print('-----------------------------') | |
| print( | |
| 'After exact matches: %d references, %d manifest files unmatched' % | |
| (len(expected_manifest_paths), len(manifest_paths))) | |
| print('Matches:') | |
| for path in matched_manifest_paths: | |
| print(path) | |
| print('') | |
| # Second step is to look at manifests with the same file name as what we | |
| # would expect AND under the same directory. | |
| print('-----------------------------') | |
| print('Likely matches') | |
| for potential_path in list(expected_manifest_paths): | |
| base_dir = os.path.dirname(os.path.dirname(potential_path)) | |
| name = os.path.basename(potential_path) | |
| for path in list(manifest_paths): | |
| if os.path.commonprefix([ | |
| base_dir, path | |
| ]) == base_dir and os.path.basename(path) == name: | |
| expected_manifest_paths.remove(potential_path) | |
| manifest_paths.remove(path) | |
| print('[---] ' + potential_path) | |
| print('[+++] ' + path) | |
| break | |
| print('') | |
| print('-----------------------------') | |
| print( | |
| 'Leftovers: %d references, %d manifest files' % | |
| (len(expected_manifest_paths), len(manifest_paths))) | |
| combined = [(p, '---') for p in expected_manifest_paths] + [ | |
| (p, '+++') for p in manifest_paths | |
| ] | |
| for path, type in sorted(combined): | |
| print('[%s] %s' % (type, path)) | |
| return 0 | |
| if __name__ == '__main__': | |
| sys.exit(main()) |