blob: ece26c341519d671a20a7fb429b692fa5e2d469a [file] [log] [blame]
#!/usr/bin/env python
# Copyright 2017 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.
import argparse
import json
import os
import sys
from sdk_common import Atom, AtomId, detect_category_violations, detect_collisions, gather_dependencies
def main():
parser = argparse.ArgumentParser()
parser.add_argument('--domain',
help='Name of the domain the element belongs to',
required=True)
name_group = parser.add_mutually_exclusive_group(required=True)
name_group.add_argument('--name',
help='Name of the element')
name_group.add_argument('--name-file',
help='Path to the file containing the name of the element')
parser.add_argument('--out',
help='Path to the output file',
required=True)
parser.add_argument('--base',
help='Path to the element\'s source directory',
required=True)
parser.add_argument('--deps',
help='List of manifest paths for dependencies',
nargs='*')
parser.add_argument('--package-deps',
help='List of manifest paths for runtime dependencies',
nargs='*')
parser.add_argument('--files',
help='A source=destination mapping',
nargs='*')
parser.add_argument('--file-manifest',
help='A file containing source=destination mappings',
required=False)
parser.add_argument('--tags',
help='List of tags for the included elements',
nargs='*')
parser.add_argument('--gn-label',
help='GN label of the atom',
required=True)
parser.add_argument('--category',
help='Publication level',
required=True)
args = parser.parse_args()
if args.name:
name = args.name
else:
with open(args.name_file, 'r') as name_file:
name = name_file.read()
# Gather the definitions of other atoms this atom depends on.
(deps, atoms) = gather_dependencies(args.deps)
(_, package_atoms) = gather_dependencies(args.package_deps)
all_atoms = atoms
all_atoms.update(package_atoms)
# Build the list of files making up this atom.
files = []
has_packaged_files = False
base = os.path.realpath(args.base)
mappings = args.files
if args.file_manifest:
with open(args.file_manifest, 'r') as manifest_file:
additional_mappings = [l.strip() for l in manifest_file.readlines()]
mappings.extend(additional_mappings)
for mapping in mappings:
mode, pair = mapping.split(':', 1)
is_packaged = (mode == 'packaged')
destination, source = pair.split('=', 1)
real_source = os.path.realpath(source)
if not os.path.exists(real_source):
raise Exception('Missing source file: %s' % real_source)
if destination:
if destination.find('..') != -1:
raise Exception('Destination for %s cannot contain "..": %s.' %
(source, destination))
else:
if not real_source.startswith(base):
raise Exception('Destination for %s must be given as it is not'
' under source directory %s' % (source, base))
destination = os.path.relpath(real_source, base)
if os.path.isabs(destination):
raise Exception('Destination cannot be absolute: %s' % destination)
files.append({
'source': real_source,
'destination': destination,
'packaged': is_packaged
})
has_packaged_files = has_packaged_files or is_packaged
id = {
'domain': args.domain,
'name': name,
}
all_package_deps = set()
if has_packaged_files:
all_package_deps.add(AtomId(id))
for atom in all_atoms:
all_package_deps.update(atom.package_deps)
tags = dict(map(lambda t: t.split(':', 1), args.tags))
tags['domain'] = args.domain
all_atoms.update([Atom({
'id': id,
'gn-label': args.gn_label,
'category': args.category,
'tags': tags,
'deps': map(lambda i: i.json, sorted(list(deps))),
'package-deps': map(lambda i: i.json, sorted(list(all_package_deps))),
'files': files,
})])
if detect_collisions(all_atoms):
print('Name collisions detected!')
return 1
if detect_category_violations(args.category, all_atoms):
print('Publication level violations detected!')
return 1
manifest = {
'ids': [id],
'atoms': map(lambda a: a.json, sorted(list(all_atoms))),
}
with open(os.path.abspath(args.out), 'w') as out:
json.dump(manifest, out, indent=2, sort_keys=True)
if __name__ == '__main__':
sys.exit(main())