1// Copyright 2018 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5import 'dart:async'; 6 7import 'package:args/args.dart'; 8import 'package:flutter_tools/src/asset.dart' hide defaultManifestPath; 9import 'package:flutter_tools/src/base/context.dart'; 10import 'package:flutter_tools/src/base/file_system.dart' as libfs; 11import 'package:flutter_tools/src/base/io.dart'; 12import 'package:flutter_tools/src/base/platform.dart'; 13import 'package:flutter_tools/src/cache.dart'; 14import 'package:flutter_tools/src/context_runner.dart'; 15import 'package:flutter_tools/src/devfs.dart'; 16import 'package:flutter_tools/src/bundle.dart'; 17import 'package:flutter_tools/src/globals.dart'; 18import 'package:flutter_tools/src/reporting/reporting.dart'; 19 20const String _kOptionPackages = 'packages'; 21const String _kOptionAsset = 'asset-dir'; 22const String _kOptionManifest = 'manifest'; 23const String _kOptionAssetManifestOut = 'asset-manifest-out'; 24const String _kOptionComponentName = 'component-name'; 25const List<String> _kRequiredOptions = <String>[ 26 _kOptionPackages, 27 _kOptionAsset, 28 _kOptionAssetManifestOut, 29 _kOptionComponentName, 30]; 31 32Future<void> main(List<String> args) { 33 return runInContext<void>(() => run(args), overrides: <Type, Generator>{ 34 Usage: () => DisabledUsage(), 35 }); 36} 37 38Future<void> writeFile(libfs.File outputFile, DevFSContent content) async { 39 outputFile.createSync(recursive: true); 40 final List<int> data = await content.contentsAsBytes(); 41 outputFile.writeAsBytesSync(data); 42} 43 44Future<void> run(List<String> args) async { 45 final ArgParser parser = ArgParser() 46 ..addOption(_kOptionPackages, help: 'The .packages file') 47 ..addOption(_kOptionAsset, 48 help: 'The directory where to put temporary files') 49 ..addOption(_kOptionManifest, help: 'The manifest file') 50 ..addOption(_kOptionAssetManifestOut) 51 ..addOption(_kOptionComponentName); 52 final ArgResults argResults = parser.parse(args); 53 if (_kRequiredOptions 54 .any((String option) => !argResults.options.contains(option))) { 55 printError('Missing option! All options must be specified.'); 56 exit(1); 57 } 58 Cache.flutterRoot = platform.environment['FLUTTER_ROOT']; 59 60 final String assetDir = argResults[_kOptionAsset]; 61 final AssetBundle assets = await buildAssets( 62 manifestPath: argResults[_kOptionManifest] ?? defaultManifestPath, 63 assetDirPath: assetDir, 64 packagesPath: argResults[_kOptionPackages], 65 includeDefaultFonts: false, 66 ); 67 68 if (assets == null) { 69 print('Unable to find assets.'); 70 exit(1); 71 } 72 73 final List<Future<void>> calls = <Future<void>>[]; 74 assets.entries.forEach((String fileName, DevFSContent content) { 75 final libfs.File outputFile = libfs.fs.file(libfs.fs.path.join(assetDir, fileName)); 76 calls.add(writeFile(outputFile, content)); 77 }); 78 await Future.wait<void>(calls); 79 80 final String outputMan = argResults[_kOptionAssetManifestOut]; 81 await writeFuchsiaManifest(assets, argResults[_kOptionAsset], outputMan, argResults[_kOptionComponentName]); 82} 83 84Future<void> writeFuchsiaManifest(AssetBundle assets, String outputBase, String fileDest, String componentName) async { 85 86 final libfs.File destFile = libfs.fs.file(fileDest); 87 await destFile.create(recursive: true); 88 final libfs.IOSink outFile = destFile.openWrite(); 89 90 for (String path in assets.entries.keys) { 91 outFile.write('data/$componentName/$path=$outputBase/$path\n'); 92 } 93 await outFile.flush(); 94 await outFile.close(); 95} 96