blob: 2070092c56ea3db434544d3563e8e4b95264223f [file] [log] [blame]
#!/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())