| // Copyright 2019 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 "dart:io"; |
| |
| import "package:args/args.dart"; |
| |
| main(List<String> args) async { |
| final parser = new ArgParser(); |
| parser.addOption("far-tool", help: "Path to `far` tool"); |
| parser.addOption("archive", help: "Path to the far archive to extract from"); |
| parser.addOption("out-dir", help: "Path to output directory"); |
| final usage = """ |
| Usage: extract_far.dart [options] {paths} |
| |
| Options: |
| ${parser.usage}; |
| """; |
| |
| ArgResults options; |
| try { |
| options = parser.parse(args); |
| if (options["far-tool"] == null) { |
| throw new Exception("Must specify --far-tool"); |
| } |
| if (options["archive"] == null) { |
| throw new Exception("Must specify --archive"); |
| } |
| if (options["out-dir"] == null) { |
| throw new Exception("Must specify --out-dir"); |
| } |
| } catch (e) { |
| print('ERROR: $e\n'); |
| print(usage); |
| exitCode = 1; |
| return; |
| } |
| run(options); |
| } |
| |
| run(ArgResults options) async { |
| final far = options["far-tool"]; |
| |
| extract(String archive, String file, String output) async { |
| await new File(output).parent.create(recursive: true); |
| final args = ["extract-file", "--archive=$archive", "--file=$file", "--output=$output"]; |
| final result = await Process.run(far, args); |
| if (result.exitCode != 0) { |
| print(result.stdout); |
| print(result.stderr); |
| throw "Command failed: $far $args"; |
| } |
| } |
| |
| final outerArchive = options["archive"]; |
| final outDir = options["out-dir"]; |
| |
| final innerArchive = "$outDir/meta.far"; |
| await extract(outerArchive, "meta.far", innerArchive); |
| |
| final manifest = "$outDir/meta/contents"; |
| await extract(innerArchive, "meta/contents", manifest); |
| |
| final blobNames = new Map<String, String>(); |
| for (final line in await new File(manifest).readAsLines()) { |
| final pivot = line.lastIndexOf("="); |
| blobNames[line.substring(0, pivot)] = line.substring(pivot + 1, line.length); |
| } |
| |
| for (final path in options.rest) { |
| final blobName = blobNames[path]; |
| if (blobName == null) { |
| print("Archive contents: "); |
| for (final key in blobNames.keys) { |
| print(key); |
| } |
| throw "$outerArchive does not contain $path"; |
| } |
| await extract(outerArchive, blobName, "$outDir/$path"); |
| } |
| } |