#!/usr/bin/env python3 # # Copyright 2013 The Flutter 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 Fuchsia FAR Archive from an asset manifest. """ import argparse import collections import json import os import subprocess import sys from gather_flutter_runner_artifacts import CreateMetaPackage # Generates the manifest and returns the file. def GenerateManifest(package_dir): full_paths = [] for root, dirs, files in os.walk(package_dir): for f in files: common_prefix = os.path.commonprefix([root, package_dir]) rel_path = os.path.relpath(os.path.join(root, f), common_prefix) from_package = os.path.abspath(os.path.join(package_dir, rel_path)) assert from_package, 'Failed to create from_package for %s' % os.path.join(root, f) full_paths.append('%s=%s' % (rel_path, from_package)) parent_dir = os.path.abspath(os.path.join(package_dir, os.pardir)) manifest_file_name = os.path.basename(package_dir) + '.manifest' manifest_path = os.path.join(parent_dir, manifest_file_name) with open(manifest_path, 'w') as f: for item in full_paths: f.write("%s\n" % item) return manifest_path def CreateFarPackage(pm_bin, package_dir, signing_key, dst_dir, api_level): manifest_path = GenerateManifest(package_dir) pm_command_base = [ pm_bin, '-m', manifest_path, '-k', signing_key, '-o', dst_dir, '--api-level', api_level ] # Build the package subprocess.check_output(pm_command_base + ['build']) # Archive the package subprocess.check_output(pm_command_base + ['archive']) return 0 def main(): parser = argparse.ArgumentParser() parser.add_argument('--pm-bin', dest='pm_bin', action='store', required=True) parser.add_argument('--package-dir', dest='package_dir', action='store', required=True) parser.add_argument('--manifest-file', dest='manifest_file', action='store', required=False) parser.add_argument( '--manifest-json-file', dest='manifest_json_file', action='store', required=True ) parser.add_argument('--far-name', dest='far_name', action='store', required=False) parser.add_argument('--api-level', dest='api_level', action='store', required=False) args = parser.parse_args() assert os.path.exists(args.pm_bin) assert os.path.exists(args.package_dir) pkg_dir = args.package_dir if not os.path.exists(os.path.join(pkg_dir, 'meta', 'package')): CreateMetaPackage(pkg_dir, args.far_name) output_dir = os.path.abspath(pkg_dir + '_out') if not os.path.exists(output_dir): os.makedirs(output_dir) manifest_file = None if args.manifest_file is not None: assert os.path.exists(args.manifest_file) manifest_file = args.manifest_file else: manifest_file = GenerateManifest(args.package_dir) pm_command_base = [ args.pm_bin, '-o', output_dir, '-n', args.far_name, '-m', manifest_file, ] # Build and then archive the package # Use check_output so if anything goes wrong we get the output. try: build_command = ['build', '--output-package-manifest', args.manifest_json_file] if args.api_level is not None: build_command = ['--api-level', args.api_level] + build_command archive_command = [ 'archive', '--output=' + os.path.join(os.path.dirname(output_dir), args.far_name + "-0") ] pm_commands = [build_command, archive_command] for pm_command in pm_commands: subprocess.check_output(pm_command_base + pm_command) except subprocess.CalledProcessError as e: print('==================== Manifest contents =========================================') with open(manifest_file, 'r') as manifest: sys.stdout.write(manifest.read()) print('==================== End manifest contents =====================================') meta_contents_path = os.path.join(output_dir, 'meta', 'contents') if os.path.exists(meta_contents_path): print('==================== meta/contents =============================================') with open(meta_contents_path, 'r') as meta_contents: sys.stdout.write(meta_contents.read()) print('==================== End meta/contents =========================================') raise return 0 if __name__ == '__main__': sys.exit(main())