| # 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. |
| """Generate a package_manifest.json file based on meta.far and blob directory.""" |
| |
| import argparse |
| import json |
| import os |
| import subprocess |
| import sys |
| |
| CONTENTS_FILE_RELATIVE_PATH = 'meta/contents' |
| PACKAGE_FILE_RELATIVE_PATH = 'meta/package' |
| |
| |
| def read_file_from_meta_far(far_tool, meta_far_path, file): |
| """Invokes the far tool to extract the meta_far.""" |
| args = [far_tool, 'cat', '--archive=' + meta_far_path, '--file=' + file] |
| return subprocess.run( |
| args, check=True, capture_output=True, text=True).stdout |
| |
| |
| def parse_args(): |
| """Parses arguments.""" |
| parser = argparse.ArgumentParser() |
| parser.add_argument('--far-tool', help='Path to far tool', required=True) |
| parser.add_argument( |
| '--meta-far-file', help='Path to meta.far file', required=True) |
| parser.add_argument( |
| '--blob-manifest', help='Path to blob manifest file', required=True) |
| parser.add_argument( |
| '--output-file', help='Path to output manifest file', required=True) |
| return parser.parse_args() |
| |
| |
| def generate_manifest(source_map, args): |
| package_manifest = {'version': '1'} |
| meta_package = read_file_from_meta_far(args.far_tool, args.meta_far_file, |
| PACKAGE_FILE_RELATIVE_PATH) |
| package = json.loads(meta_package) |
| package_manifest['package'] = package |
| blobs = [] |
| meta_content = read_file_from_meta_far(args.far_tool, args.meta_far_file, |
| CONTENTS_FILE_RELATIVE_PATH) |
| |
| # Include the meta.far file at the 'meta/' path |
| meta_far_merkle = None |
| for k in source_map: |
| if source_map[k] == args.meta_far_file: |
| meta_far_merkle = k |
| if not meta_far_merkle: |
| raise ValueError('meta far merkle not found in blob manifest') |
| blobs.append({ |
| 'source_path': args.meta_far_file, |
| 'path': 'meta/', |
| 'merkle': meta_far_merkle, |
| 'size': os.path.getsize(args.meta_far_file), |
| }) |
| |
| # Add the rest of the blobs to the manifest. |
| for content in meta_content.split('\n'): |
| content = content.strip() |
| if not len(content): |
| continue |
| blob_entry = content.split('=') |
| blob_path = blob_entry[0] |
| merkle = blob_entry[1] |
| if merkle not in source_map: |
| raise ValueError( |
| 'No matching merkle in blob manifest file,' |
| ' blob_path = {}, merkle = {}', blob_path, merkle) |
| source_path = source_map[merkle] |
| size = os.path.getsize(source_path) |
| blob_map = { |
| 'source_path': source_path, |
| 'path': blob_path, |
| 'merkle': merkle, |
| 'size': size, |
| } |
| blobs.append(blob_map) |
| |
| package_manifest['blobs'] = blobs |
| with open(args.output_file, 'w') as manifest_file: |
| json.dump(package_manifest, manifest_file, indent=4) |
| |
| |
| def generate_source_map(blob_manifest): |
| source_map = {} |
| with open(blob_manifest, 'r') as blob_manifest: |
| for content in blob_manifest.readlines(): |
| blob_entry = content.strip().split('=') |
| merkle = blob_entry[0] |
| source_path = blob_entry[1] |
| source_map[merkle] = source_path |
| return source_map |
| |
| |
| def main(): |
| """Main for the package_manifest generation tool.""" |
| args = parse_args() |
| outdir = os.path.dirname(args.output_file) |
| os.makedirs(outdir, exist_ok=True) |
| source_map = generate_source_map(args.blob_manifest) |
| generate_manifest(source_map, args) |
| |
| |
| if __name__ == '__main__': |
| sys.exit(main()) |