|  | #!/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()) |