| // Copyright 2016 The Chromium 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:async'; |
| import 'dart:convert'; |
| import 'dart:io'; |
| |
| import 'package:args/args.dart'; |
| import 'package:path/path.dart' as path; |
| |
| import 'package:flutter_devicelab/framework/manifest.dart'; |
| import 'package:flutter_devicelab/framework/runner.dart'; |
| import 'package:flutter_devicelab/framework/utils.dart'; |
| |
| List<String> _taskNames = <String>[]; |
| |
| /// Runs tasks. |
| /// |
| /// The tasks are chosen depending on the command-line options |
| /// (see [_argParser]). |
| Future<void> main(List<String> rawArgs) async { |
| ArgResults args; |
| try { |
| args = _argParser.parse(rawArgs); |
| } on FormatException catch (error) { |
| stderr.writeln('${error.message}\n'); |
| stderr.writeln('Usage:\n'); |
| stderr.writeln(_argParser.usage); |
| exitCode = 1; |
| return; |
| } |
| |
| if (!args.wasParsed('task')) { |
| if (args.wasParsed('stage')) { |
| final String stageName = args['stage']; |
| final List<ManifestTask> tasks = loadTaskManifest().tasks; |
| for (ManifestTask task in tasks) { |
| if (task.stage == stageName) |
| _taskNames.add(task.name); |
| } |
| } else if (args.wasParsed('all')) { |
| final List<ManifestTask> tasks = loadTaskManifest().tasks; |
| for (ManifestTask task in tasks) { |
| _taskNames.add(task.name); |
| } |
| } |
| } |
| |
| if (_taskNames.isEmpty) { |
| stderr.writeln('Failed to find tasks to run based on supplied options.'); |
| exitCode = 1; |
| return; |
| } |
| |
| final bool silent = args['silent']; |
| final String localEngine = args['local-engine']; |
| final String localEngineSrcPath = args['local-engine-src-path']; |
| |
| for (String taskName in _taskNames) { |
| section('Running task "$taskName"'); |
| final Map<String, dynamic> result = await runTask( |
| taskName, |
| silent: silent, |
| localEngine: localEngine, |
| localEngineSrcPath: localEngineSrcPath, |
| ); |
| |
| if (!result['success']) |
| exitCode = 1; |
| |
| print('Task result:'); |
| print(const JsonEncoder.withIndent(' ').convert(result)); |
| section('Finished task "$taskName"'); |
| } |
| } |
| |
| /// Command-line options for the `run.dart` command. |
| final ArgParser _argParser = ArgParser() |
| ..addMultiOption( |
| 'task', |
| abbr: 't', |
| splitCommas: true, |
| help: 'Either:\n' |
| ' - the name of a task defined in manifest.yaml. Example: complex_layout__start_up.\n' |
| ' - the path to a Dart file corresponding to a task, which resides in bin/tasks. Example: bin/tasks/complex_layout__start_up.dart.\n' |
| '\n' |
| 'This option may be repeated to specify multiple tasks.', |
| callback: (List<String> value) { |
| for (String nameOrPath in value) { |
| final List<String> fragments = path.split(nameOrPath); |
| final bool isDartFile = fragments.last.endsWith('.dart'); |
| |
| if (fragments.length == 1 && !isDartFile) { |
| // Not a path |
| _taskNames.add(nameOrPath); |
| } else if (!isDartFile || fragments.length != 3 || !_listsEqual(<String>['bin', 'tasks'], fragments.take(2).toList())) { |
| // Unsupported executable location |
| throw FormatException('Invalid value for option -t (--task): $nameOrPath'); |
| } else { |
| _taskNames.add(path.withoutExtension(fragments.last)); |
| } |
| } |
| }, |
| ) |
| ..addOption( |
| 'stage', |
| abbr: 's', |
| help: 'Name of the stage. Runs all tasks for that stage. ' |
| 'The tasks and their stages are read from manifest.yaml.', |
| ) |
| ..addFlag( |
| 'all', |
| abbr: 'a', |
| help: 'Runs all tasks defined in manifest.yaml.', |
| ) |
| ..addMultiOption( |
| 'test', |
| hide: true, |
| splitCommas: true, |
| callback: (List<String> value) { |
| if (value.isNotEmpty) { |
| throw const FormatException( |
| 'Invalid option --test. Did you mean --task (-t)?', |
| ); |
| } |
| }, |
| ) |
| ..addFlag( |
| 'silent', |
| negatable: true, |
| defaultsTo: false, |
| ) |
| ..addOption( |
| 'local-engine', |
| help: 'Name of a build output within the engine out directory, if you are ' |
| 'building Flutter locally. Use this to select a specific version of ' |
| 'the engine if you have built multiple engine targets. This path is ' |
| 'relative to --local-engine-src-path/out.', |
| ) |
| ..addOption( |
| 'local-engine-src-path', |
| help: 'Path to your engine src directory, if you are building Flutter ' |
| 'locally. Defaults to \$FLUTTER_ENGINE if set, or tries to guess at ' |
| 'the location based on the value of the --flutter-root option.', |
| ); |
| |
| bool _listsEqual(List<dynamic> a, List<dynamic> b) { |
| if (a.length != b.length) |
| return false; |
| |
| for (int i = 0; i < a.length; i++) { |
| if (a[i] != b[i]) |
| return false; |
| } |
| |
| return true; |
| } |