blob: 85708f9d27a07c4740b2ee70fb2726d4adc37192 [file] [log] [blame]
# 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())