blob: 5fdeab237dbbcede898cc713dc1569dc7a993cb5 [file] [log] [blame]
#!/usr/bin/env python3.8
# Copyright 2021 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 depfile import DepFile
from typing import Dict, Optional
def main():
parser = argparse.ArgumentParser(
description=
'Create a flat list of files included in the images. This is used to inform infrastructure what files to upload'
)
parser.add_argument(
'--product-config', type=argparse.FileType('r'), required=True)
parser.add_argument(
'--images-config', type=argparse.FileType('r'), required=True)
parser.add_argument(
'--partitions-config', type=argparse.FileType('r'), required=True)
parser.add_argument('--sources', type=str, nargs='*')
parser.add_argument('--output', type=argparse.FileType('w'), required=True)
parser.add_argument('--depfile', type=argparse.FileType('w'), required=True)
args = parser.parse_args()
# The files to put in the output with source mapped to destination.
file_mapping = {}
# Add a file or directory path to one of the lists, relative to CWD.
# The destination is the path when placed inside "built/artifacts".
# If the path is prefixed with ../../, the prefix is removed.
def add_source(source):
# Absolute paths are not portable out-of-tree, therefore if a file is
# using an absolute path we throw an error.
if os.path.isabs(source):
raise Exception("Absolute paths are not allowed", source)
source = os.path.relpath(source, os.getcwd())
prefix = "../../"
if source.startswith(prefix):
destination = source[len(prefix):]
else:
destination = os.path.join("built/artifacts", source)
file_mapping[source] = destination
# Add a package and all the included blobs.
manifests_for_depfile = []
def add_package(entry: Dict):
manifest = entry["manifest"]
manifests_for_depfile.append(manifest)
add_source(manifest)
with open(manifest, 'r') as f:
manifest = json.load(f)
for blob in manifest.get("blobs", []):
add_source(blob["source_path"])
config_data: Optional[Dict[str, str]] = entry.get("config_data")
if config_data:
for (_dest, source) in config_data.items():
add_source(source)
# Add the product config.
add_source(args.product_config.name)
product_config = json.load(args.product_config)
if "product" in product_config:
product = product_config["product"]
if "packages" in product:
packages = product["packages"]
for package in packages.get("base", []):
add_package(package)
for package in packages.get("cache", []):
add_package(package)
# Add the images config.
add_source(args.images_config.name)
images = json.load(args.images_config).get("images", [])
for image in images:
if image["type"] == "vbmeta":
add_source(image["key"])
add_source(image["key_metadata"])
if "additional_descriptor_files" in image:
for descriptor in image["additional_descriptor_files"]:
add_source(descriptor)
elif image["type"] == "zbi":
if "postprocessing_script" in image:
add_source(image["postprocessing_script"]["path"])
# Add the partitions config.
add_source(args.partitions_config.name)
partitions_config = json.load(args.partitions_config)
for cred in partitions_config.get("unlock_credentials", []):
add_source(cred)
for part in partitions_config.get("bootloader_partitions", []):
add_source(part["image"])
for part in partitions_config.get("bootstrap_partitions", []):
add_source(part["image"])
# Add any additional sources to copy.
for source in args.sources:
add_source(source)
# Convert the map into a list of maps.
files = []
for src, dest in file_mapping.items():
files.append({
"source": src,
"destination": dest,
})
# Write a depfile with any opened package manifests.
if manifests_for_depfile:
depfile = DepFile(args.output.name)
depfile.update(manifests_for_depfile)
depfile.write_to(args.depfile)
# Write the list.
json.dump(files, args.output, indent=2)
if __name__ == '__main__':
sys.exit(main())