Commit cae053c3 authored by Ian Fischer's avatar Ian Fischer

Refactor all the commands to be Commands from the Args package. Also use...

Refactor all the commands to be Commands from the Args package.  Also use CommandRunner for the top-level command.
parent a49120c6
...@@ -2,185 +2,144 @@ ...@@ -2,185 +2,144 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:io'; import 'dart:async';
import 'package:args/args.dart'; import 'package:args/args.dart';
import 'package:args/command_runner.dart';
import 'package:logging/logging.dart'; import 'package:logging/logging.dart';
import 'package:sky_tools/src/application_package.dart';
import 'package:sky_tools/src/build.dart'; import 'package:sky_tools/src/build.dart';
import 'package:sky_tools/src/cache.dart'; import 'package:sky_tools/src/cache.dart';
import 'package:sky_tools/src/common.dart';
import 'package:sky_tools/src/init.dart'; import 'package:sky_tools/src/init.dart';
import 'package:sky_tools/src/install.dart'; import 'package:sky_tools/src/install.dart';
import 'package:sky_tools/src/run_mojo.dart'; import 'package:sky_tools/src/run_mojo.dart';
import 'package:sky_tools/src/application_package.dart';
void main(List<String> args) {
Logger.root.level = Level.WARNING;
Logger.root.onRecord.listen((LogRecord rec) {
print('${rec.level.name}: ${rec.message}');
if (rec.error != null) {
print(rec.error);
}
if (rec.stackTrace != null) {
print(rec.stackTrace);
}
});
Map<String, CommandHandler> handlers = {};
ArgParser parser = new ArgParser();
parser.addSeparator('basic options:');
parser.addFlag('help',
abbr: 'h', negatable: false, help: 'Display this help message.');
parser.addFlag('verbose',
abbr: 'v',
negatable: false,
help: 'Noisy logging, including all shell commands executed.');
parser.addFlag('very-verbose',
negatable: false,
help: 'Very noisy logging, including the output of all '
'shell commands executed.');
parser.addSeparator('build selection options:');
parser.addFlag('debug',
negatable: false,
help:
'Set this if you are building Sky locally and want to use the debug build products. '
'When set, attempts to automaticaly determine sky-src-path if sky-src-path is '
'not set. Not normally required.');
parser.addFlag('release',
negatable: false,
help:
'Set this if you are building Sky locally and want to use the release build products. '
'When set, attempts to automaticaly determine sky-src-path if sky-src-path is '
'not set. Note that release is not compatible with the listen command '
'on iOS devices and simulators. Not normally required.');
parser.addOption('sky-src-path',
help: 'Path to your Sky src directory, if you are building Sky locally. '
'Ignored if neither debug nor release is set. Not normally required.');
parser.addOption('android-debug-build-path',
help:
'Path to your Android Debug out directory, if you are building Sky locally. '
'This path is relative to sky-src-path. Not normally required.',
defaultsTo: 'out/android_Debug/');
parser.addOption('android-release-build-path',
help:
'Path to your Android Release out directory, if you are building Sky locally. '
'This path is relative to sky-src-path. Not normally required.',
defaultsTo: 'out/android_Release/');
parser.addOption('ios-debug-build-path',
help:
'Path to your iOS Debug out directory, if you are building Sky locally. '
'This path is relative to sky-src-path. Not normally required.',
defaultsTo: 'out/ios_Debug/');
parser.addOption('ios-release-build-path',
help:
'Path to your iOS Release out directory, if you are building Sky locally. '
'This path is relative to sky-src-path. Not normally required.',
defaultsTo: 'out/ios_Release/');
parser.addOption('ios-sim-debug-build-path',
help:
'Path to your iOS Simulator Debug out directory, if you are building Sky locally. '
'This path is relative to sky-src-path. Not normally required.',
defaultsTo: 'out/ios_sim_Debug/');
parser.addOption('ios-sim-release-build-path',
help:
'Path to your iOS Simulator Release out directory, if you are building Sky locally. '
'This path is relative to sky-src-path. Not normally required.',
defaultsTo: 'out/ios_sim_Release/');
parser.addSeparator('commands:');
for (CommandHandler handler in [
new BuildCommandHandler(),
new CacheCommandHandler(),
new InitCommandHandler(),
new InstallCommandHandler(),
new RunMojoCommandHandler(),
]) {
parser.addCommand(handler.name, handler.parser);
handlers[handler.name] = handler;
}
ArgResults results;
try { class FlutterCommandRunner extends CommandRunner {
results = parser.parse(args); FlutterCommandRunner() : super('flutter', 'Manage your flutter app development.') {
} catch (e) { argParser.addFlag('verbose',
_printUsage(parser, handlers, e is FormatException ? e.message : '${e}'); abbr: 'v',
exit(1); negatable: false,
help: 'Noisy logging, including all shell commands executed.');
argParser.addFlag('very-verbose',
negatable: false,
help: 'Very noisy logging, including the output of all '
'shell commands executed.');
argParser.addSeparator('Global build selection options:');
argParser.addFlag('debug',
negatable: false,
help:
'Set this if you are building Sky locally and want to use the debug build products. '
'When set, attempts to automaticaly determine sky-src-path if sky-src-path is '
'not set. Not normally required.');
argParser.addFlag('release',
negatable: false,
help:
'Set this if you are building Sky locally and want to use the release build products. '
'When set, attempts to automaticaly determine sky-src-path if sky-src-path is '
'not set. Note that release is not compatible with the listen command '
'on iOS devices and simulators. Not normally required.');
argParser.addOption('sky-src-path',
help: 'Path to your Sky src directory, if you are building Sky locally. '
'Ignored if neither debug nor release is set. Not normally required.');
argParser.addOption('android-debug-build-path',
help:
'Path to your Android Debug out directory, if you are building Sky locally. '
'This path is relative to sky-src-path. Not normally required.',
defaultsTo: 'out/android_Debug/');
argParser.addOption('android-release-build-path',
help:
'Path to your Android Release out directory, if you are building Sky locally. '
'This path is relative to sky-src-path. Not normally required.',
defaultsTo: 'out/android_Release/');
argParser.addOption('ios-debug-build-path',
help:
'Path to your iOS Debug out directory, if you are building Sky locally. '
'This path is relative to sky-src-path. Not normally required.',
defaultsTo: 'out/ios_Debug/');
argParser.addOption('ios-release-build-path',
help:
'Path to your iOS Release out directory, if you are building Sky locally. '
'This path is relative to sky-src-path. Not normally required.',
defaultsTo: 'out/ios_Release/');
argParser.addOption('ios-sim-debug-build-path',
help:
'Path to your iOS Simulator Debug out directory, if you are building Sky locally. '
'This path is relative to sky-src-path. Not normally required.',
defaultsTo: 'out/ios_sim_Debug/');
argParser.addOption('ios-sim-release-build-path',
help:
'Path to your iOS Simulator Release out directory, if you are building Sky locally. '
'This path is relative to sky-src-path. Not normally required.',
defaultsTo: 'out/ios_sim_Release/');
} }
if (results['verbose']) { Future<int> runCommand(ArgResults topLevelResults) async {
Logger.root.level = Level.INFO; if (topLevelResults['verbose']) {
} Logger.root.level = Level.INFO;
}
if (results['very-verbose']) { if (topLevelResults['very-verbose']) {
Logger.root.level = Level.FINE; Logger.root.level = Level.FINE;
} }
_setupPaths(results); _setupPaths(topLevelResults);
if (results['help']) { return super.runCommand(topLevelResults);
_printUsage(parser, handlers);
} else if (results.command != null) {
handlers[results.command.name]
.processArgResults(results.command)
.then((int code) => exit(code))
.catchError((e, stack) {
print('Error running ' + results.command.name + ': $e');
print(stack);
exit(2);
});
} else {
_printUsage(parser, handlers, 'No command specified.');
exit(1);
} }
}
void _setupPaths(ArgResults results) { void _setupPaths(ArgResults results) {
if (results['debug'] || results['release']) { if (results['debug'] || results['release']) {
if (results['sky-src-path'] == null) { if (results['sky-src-path'] == null) {
// TODO(iansf): Figure out how to get the default src path // TODO(iansf): Figure out how to get the default src path
assert(false);
}
ApplicationPackageFactory.srcPath = results['sky-src-path'];
} else {
assert(false); assert(false);
// TODO(iansf): set paths up for commands using PREBUILT binaries
// ApplicationPackageFactory.setBuildPath(BuildType.PREBUILT,
// BuildPlatform.android, results['android-debug-build-path']);
} }
ApplicationPackageFactory.srcPath = results['sky-src-path'];
} else {
assert(false);
// TODO(iansf): set paths up for commands using PREBUILT binaries
// ApplicationPackageFactory.setBuildPath(BuildType.PREBUILT,
// BuildPlatform.android, results['android-debug-build-path']);
}
if (results['debug']) { if (results['debug']) {
ApplicationPackageFactory.defaultBuildType = BuildType.debug; ApplicationPackageFactory.defaultBuildType = BuildType.debug;
ApplicationPackageFactory.setBuildPath(BuildType.debug, ApplicationPackageFactory.setBuildPath(BuildType.debug,
BuildPlatform.android, results['android-debug-build-path']); BuildPlatform.android, results['android-debug-build-path']);
ApplicationPackageFactory.setBuildPath( ApplicationPackageFactory.setBuildPath(
BuildType.debug, BuildPlatform.iOS, results['ios-debug-build-path']); BuildType.debug, BuildPlatform.iOS, results['ios-debug-build-path']);
ApplicationPackageFactory.setBuildPath(BuildType.debug, ApplicationPackageFactory.setBuildPath(BuildType.debug,
BuildPlatform.iOSSimulator, results['ios-sim-debug-build-path']); BuildPlatform.iOSSimulator, results['ios-sim-debug-build-path']);
} }
if (results['release']) { if (results['release']) {
ApplicationPackageFactory.defaultBuildType = BuildType.release; ApplicationPackageFactory.defaultBuildType = BuildType.release;
ApplicationPackageFactory.setBuildPath(BuildType.release, ApplicationPackageFactory.setBuildPath(BuildType.release,
BuildPlatform.android, results['android-release-build-path']); BuildPlatform.android, results['android-release-build-path']);
ApplicationPackageFactory.setBuildPath(BuildType.release, BuildPlatform.iOS, ApplicationPackageFactory.setBuildPath(BuildType.release, BuildPlatform.iOS,
results['ios-release-build-path']); results['ios-release-build-path']);
ApplicationPackageFactory.setBuildPath(BuildType.release, ApplicationPackageFactory.setBuildPath(BuildType.release,
BuildPlatform.iOSSimulator, results['ios-sim-release-build-path']); BuildPlatform.iOSSimulator, results['ios-sim-release-build-path']);
}
} }
} }
void _printUsage(ArgParser parser, Map<String, CommandHandler> handlers, void main(List<String> args) {
[String message]) { Logger.root.level = Level.WARNING;
if (message != null) { Logger.root.onRecord.listen((LogRecord rec) {
print('${message}\n'); print('${rec.level.name}: ${rec.message}');
} if (rec.error != null) {
print('usage: sky_tools <command> [arguments]'); print(rec.error);
print(''); }
print(parser.usage); if (rec.stackTrace != null) {
handlers.forEach((String command, CommandHandler handler) { print(rec.stackTrace);
print(' ${command.padRight(10)} ${handler.description}'); }
}); });
new FlutterCommandRunner()
..addCommand(new BuildCommand())
..addCommand(new CacheCommand())
..addCommand(new InitCommand())
..addCommand(new InstallCommand())
..addCommand(new RunMojoCommand())
..run(args);
} }
...@@ -8,11 +8,10 @@ import 'dart:async'; ...@@ -8,11 +8,10 @@ import 'dart:async';
import 'dart:io'; import 'dart:io';
import 'package:archive/archive.dart'; import 'package:archive/archive.dart';
import 'package:args/args.dart'; import 'package:args/command_runner.dart';
import 'package:yaml/yaml.dart'; import 'package:yaml/yaml.dart';
import 'artifacts.dart'; import 'artifacts.dart';
import 'common.dart';
const String _kSnapshotKey = 'snapshot_blob.bin'; const String _kSnapshotKey = 'snapshot_blob.bin';
const List<String> _kDensities = const ['drawable-xxhdpi']; const List<String> _kDensities = const ['drawable-xxhdpi'];
...@@ -127,41 +126,33 @@ Future<ArchiveFile> _createSnapshotFile(String snapshotPath) async { ...@@ -127,41 +126,33 @@ Future<ArchiveFile> _createSnapshotFile(String snapshotPath) async {
return new ArchiveFile(_kSnapshotKey, content.length, content); return new ArchiveFile(_kSnapshotKey, content.length, content);
} }
class BuildCommandHandler extends CommandHandler { class BuildCommand extends Command {
BuildCommandHandler() : super('build', 'Create a Flutter app.'); final name = 'build';
final description = 'Create a Flutter app.';
ArgParser get parser { BuildCommand() {
ArgParser parser = new ArgParser(); argParser.addOption('asset-base', defaultsTo: 'packages/material_design_icons/icons');
parser.addFlag('help', abbr: 'h', negatable: false); argParser.addOption('compiler');
parser.addOption('asset-base', defaultsTo: 'packages/material_design_icons/icons'); argParser.addOption('main', defaultsTo: 'lib/main.dart');
parser.addOption('compiler'); argParser.addOption('manifest');
parser.addOption('main', defaultsTo: 'lib/main.dart'); argParser.addOption('output-file', abbr: 'o', defaultsTo: 'app.flx');
parser.addOption('manifest'); argParser.addOption('package-root', defaultsTo: 'packages');
parser.addOption('output-file', abbr: 'o', defaultsTo: 'app.flx'); argParser.addOption('snapshot', defaultsTo: 'snapshot_blob.bin');
parser.addOption('package-root', defaultsTo: 'packages');
parser.addOption('snapshot', defaultsTo: 'snapshot_blob.bin');
return parser;
} }
@override @override
Future<int> processArgResults(ArgResults results) async { Future<int> run() async {
if (results['help']) { String manifestPath = argResults['manifest'];
print(parser.usage);
return 0;
}
String manifestPath = results['manifest'];
Map manifestDescriptor = await _loadManifest(manifestPath); Map manifestDescriptor = await _loadManifest(manifestPath);
Iterable<_Asset> assets = _parseAssets(manifestDescriptor, manifestPath); Iterable<_Asset> assets = _parseAssets(manifestDescriptor, manifestPath);
Iterable<_MaterialAsset> materialAssets = _parseMaterialAssets(manifestDescriptor); Iterable<_MaterialAsset> materialAssets = _parseMaterialAssets(manifestDescriptor);
Archive archive = new Archive(); Archive archive = new Archive();
String snapshotPath = results['snapshot']; String snapshotPath = argResults['snapshot'];
await _compileSnapshot( await _compileSnapshot(
compilerPath: results['compiler'], compilerPath: argResults['compiler'],
mainPath: results['main'], mainPath: argResults['main'],
packageRoot: results['package-root'], packageRoot: argResults['package-root'],
snapshotPath: snapshotPath); snapshotPath: snapshotPath);
archive.addFile(await _createSnapshotFile(snapshotPath)); archive.addFile(await _createSnapshotFile(snapshotPath));
...@@ -169,12 +160,12 @@ class BuildCommandHandler extends CommandHandler { ...@@ -169,12 +160,12 @@ class BuildCommandHandler extends CommandHandler {
archive.addFile(await _createFile(asset.key, asset.base)); archive.addFile(await _createFile(asset.key, asset.base));
for (_MaterialAsset asset in materialAssets) { for (_MaterialAsset asset in materialAssets) {
ArchiveFile file = await _createFile(asset.key, results['asset-base']); ArchiveFile file = await _createFile(asset.key, argResults['asset-base']);
if (file != null) if (file != null)
archive.addFile(file); archive.addFile(file);
} }
File outputFile = new File(results['output-file']); File outputFile = new File(argResults['output-file']);
await outputFile.writeAsString('#!mojo mojo:sky_viewer\n'); await outputFile.writeAsString('#!mojo mojo:sky_viewer\n');
await outputFile.writeAsBytes(new ZipEncoder().encode(archive), mode: FileMode.APPEND); await outputFile.writeAsBytes(new ZipEncoder().encode(archive), mode: FileMode.APPEND);
return 0; return 0;
......
...@@ -6,63 +6,48 @@ library sky_tools.cache; ...@@ -6,63 +6,48 @@ library sky_tools.cache;
import 'dart:async'; import 'dart:async';
import 'package:args/args.dart'; import 'package:args/command_runner.dart';
import 'package:logging/logging.dart'; import 'package:logging/logging.dart';
import 'artifacts.dart'; import 'artifacts.dart';
import 'common.dart';
final Logger _logging = new Logger('sky_tools.cache'); final Logger _logging = new Logger('sky_tools.cache');
class CacheCommandHandler extends CommandHandler { class CacheCommand extends Command {
CacheCommandHandler() : super('cache', 'Manages sky_tools\' cache of binary artifacts.'); final name = 'cache';
final description = 'Manages sky_tools\' cache of binary artifacts.';
ArgParser get parser { CacheCommand() {
ArgParser parser = new ArgParser(); addSubcommand(new _ClearCommand());
parser.addFlag('help', abbr: 'h', negatable: false); addSubcommand(new _PopulateCommand());
parser.addOption('package-root', defaultsTo: 'packages');
ArgParser clearParser = parser.addCommand('clear');
clearParser.addFlag('help', abbr: 'h', negatable: false);
ArgParser populateParser = parser.addCommand('populate');
populateParser.addFlag('help', abbr: 'h', negatable: false);
return parser;
} }
}
Future<int> _clear(String packageRoot, ArgResults results) async { class _ClearCommand extends Command {
if (results['help']) { final name = 'clear';
print('Clears all artifacts from the cache.'); final description = 'Clears all artifacts from the cache.';
print(parser.usage); _ClearCommand() {
return 0; argParser.addOption('package-root', defaultsTo: 'packages');
}
ArtifactStore artifacts = new ArtifactStore(packageRoot);
await artifacts.clear();
return 0;
} }
Future<int> _populate(String packageRoot, ArgResults results) async { @override
if (results['help']) { Future<int> run() async {
print('Populates the cache with all known artifacts.'); ArtifactStore artifacts = new ArtifactStore(argResults['package-root']);
print(parser.usage);
return 0;
}
ArtifactStore artifacts = new ArtifactStore(packageRoot);
await artifacts.populate(); await artifacts.populate();
return 0; return 0;
} }
}
class _PopulateCommand extends Command {
final name = 'populate';
final description = 'Populates the cache with all known artifacts.';
_PopulateCommand() {
argParser.addOption('package-root', defaultsTo: 'packages');
}
@override @override
Future<int> processArgResults(ArgResults results) async { Future<int> run() async {
if (results['help'] || results.command == null) { ArtifactStore artifacts = new ArtifactStore(argResults['package-root']);
print(parser.usage); await artifacts.populate();
return 0; return 0;
}
if (results.command.name == 'clear') {
return _clear(results['package-root'], results.command);
} else if (results.command.name == 'populate') {
return _populate(results['package-root'], results.command);
} else {
_logging.severe('Unknown cache command \"${results.command.name}\"');
return 2;
}
} }
} }
// Copyright 2015 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 'package:args/args.dart';
abstract class CommandHandler {
final String name;
final String description;
CommandHandler(this.name, this.description);
ArgParser get parser;
/// Returns 0 for no errors or warnings executing command, 1 for warnings, 2
/// for errors.
Future<int> processArgResults(ArgResults results);
void printUsage([String message]) {
if (message != null) {
print('${message}\n');
}
print('usage: sky_tools ${name} [arguments]');
print('');
print(parser.usage);
}
String toString() => name;
}
...@@ -9,8 +9,8 @@ import 'dart:io'; ...@@ -9,8 +9,8 @@ import 'dart:io';
import 'package:logging/logging.dart'; import 'package:logging/logging.dart';
import 'package:path/path.dart' as path; import 'package:path/path.dart' as path;
import 'process_wrapper.dart';
import 'application_package.dart'; import 'application_package.dart';
import 'process_wrapper.dart';
final Logger _logging = new Logger('sky_tools.device'); final Logger _logging = new Logger('sky_tools.device');
......
...@@ -7,41 +7,30 @@ library sky_tools.init; ...@@ -7,41 +7,30 @@ library sky_tools.init;
import 'dart:async'; import 'dart:async';
import 'dart:io'; import 'dart:io';
import 'package:args/args.dart'; import 'package:args/command_runner.dart';
import 'package:mustache4dart/mustache4dart.dart' as mustache; import 'package:mustache4dart/mustache4dart.dart' as mustache;
import 'package:path/path.dart' as p; import 'package:path/path.dart' as p;
import 'common.dart'; class InitCommand extends Command {
final name = 'init';
class InitCommandHandler extends CommandHandler { final description = 'Create a new sky project.';
InitCommandHandler() : super('init', 'Create a new sky project.'); InitCommand() {
argParser.addOption('out', abbr: 'o', help: 'The output directory.');
ArgParser get parser { argParser.addFlag('pub',
// TODO: Add a --template option for template selection when we have more than one.
ArgParser parser = new ArgParser();
parser.addFlag('help',
abbr: 'h', negatable: false, help: 'Display this help message.');
parser.addOption('out', abbr: 'o', help: 'The output directory.');
parser.addFlag('pub',
defaultsTo: true, defaultsTo: true,
help: 'Whether to run pub after the project has been created.'); help: 'Whether to run pub after the project has been created.');
return parser;
} }
@override @override
Future<int> processArgResults(ArgResults results) async { Future<int> run() async {
if (results['help']) { if (!argResults.wasParsed('out')) {
printUsage(); print('No option specified for the output directory.');
return 0; print(argParser.getUsage());
}
if (!results.wasParsed('out')) {
printUsage('No option specified for the output directory.');
return 2; return 2;
} }
// TODO: Confirm overwrite of an existing directory with the user. // TODO: Confirm overwrite of an existing directory with the user.
Directory out = new Directory(results['out']); Directory out = new Directory(argResults['out']);
new SkySimpleTemplate().generateInto(out); new SkySimpleTemplate().generateInto(out);
...@@ -58,7 +47,7 @@ Or if the Sky APK is not already on your device, run: ...@@ -58,7 +47,7 @@ Or if the Sky APK is not already on your device, run:
'''; ''';
if (results['pub']) { if (argResults['pub']) {
print("Running pub get..."); print("Running pub get...");
Process process = Process process =
await Process.start('pub', ['get'], workingDirectory: out.path); await Process.start('pub', ['get'], workingDirectory: out.path);
......
...@@ -6,32 +6,19 @@ library sky_tools.install; ...@@ -6,32 +6,19 @@ library sky_tools.install;
import 'dart:async'; import 'dart:async';
import 'package:args/args.dart'; import 'package:args/command_runner.dart';
import 'application_package.dart'; import 'application_package.dart';
import 'common.dart';
import 'device.dart'; import 'device.dart';
class InstallCommandHandler extends CommandHandler { class InstallCommand extends Command {
final name = 'install';
final description = 'Install your Flutter app on attached devices.';
AndroidDevice android = null; AndroidDevice android = null;
InstallCommandHandler([this.android]) InstallCommand([this.android]);
: super('install', 'Install your Sky app on attached devices.');
@override @override
ArgParser get parser { Future<int> run() async {
ArgParser parser = new ArgParser();
parser.addFlag('help',
abbr: 'h', negatable: false, help: 'Display this help message.');
return parser;
}
@override
Future<int> processArgResults(ArgResults results) async {
if (results['help']) {
printUsage();
return 0;
}
bool installedSomewhere = false; bool installedSomewhere = false;
Map<BuildPlatform, ApplicationPackage> packages = Map<BuildPlatform, ApplicationPackage> packages =
......
...@@ -8,26 +8,23 @@ import 'dart:async'; ...@@ -8,26 +8,23 @@ import 'dart:async';
import 'dart:io'; import 'dart:io';
import 'package:args/args.dart'; import 'package:args/args.dart';
import 'package:args/command_runner.dart';
import 'package:logging/logging.dart'; import 'package:logging/logging.dart';
import 'package:path/path.dart' as path; import 'package:path/path.dart' as path;
import 'artifacts.dart'; import 'artifacts.dart';
import 'common.dart';
import 'process.dart'; import 'process.dart';
final Logger _logging = new Logger('sky_tools.run_mojo'); final Logger _logging = new Logger('sky_tools.run_mojo');
class RunMojoCommandHandler extends CommandHandler { class RunMojoCommand extends Command {
RunMojoCommandHandler() : super('run_mojo', 'Run a Flutter app in mojo.'); final name = 'run_mojo';
final description = 'Run a Flutter app in mojo.';
ArgParser get parser { RunMojoCommand() {
ArgParser parser = new ArgParser(); argParser.addFlag('android', negatable: false, help: 'Run on an Android device');
parser.addFlag('android', negatable: false, help: 'Run on an Android device'); argParser.addOption('app', defaultsTo: 'app.flx');
parser.addFlag('help', abbr: 'h', negatable: false); argParser.addOption('mojo-path', help: 'Path to directory containing mojo_shell and services');
parser.addOption('app', defaultsTo: 'app.flx'); argParser.addOption('package-root', defaultsTo: 'packages');
parser.addOption('mojo-path', help: 'Path to directory containing mojo_shell and services');
parser.addOption('package-root', defaultsTo: 'packages');
return parser;
} }
Future<String> _makePathAbsolute(String relativePath) async { Future<String> _makePathAbsolute(String relativePath) async {
...@@ -71,22 +68,18 @@ class RunMojoCommandHandler extends CommandHandler { ...@@ -71,22 +68,18 @@ class RunMojoCommandHandler extends CommandHandler {
} }
@override @override
Future<int> processArgResults(ArgResults results) async { Future<int> run() async {
if (results['help']) { if (argResults['mojo-path'] == null) {
print(parser.usage);
return 0;
}
if (results['mojo-path'] == null) {
_logging.severe('Must specify --mojo-path to mojo_run'); _logging.severe('Must specify --mojo-path to mojo_run');
return 1; return 1;
} }
String packageRoot = results['package-root']; String packageRoot = argResults['package-root'];
ArtifactStore artifacts = new ArtifactStore(packageRoot); ArtifactStore artifacts = new ArtifactStore(packageRoot);
String appPath = await _makePathAbsolute(results['app']); String appPath = await _makePathAbsolute(argResults['app']);
if (results['android']) { if (argResults['android']) {
return _runAndroid(results, appPath, artifacts); return _runAndroid(argResults, appPath, artifacts);
} else { } else {
return _runLinux(results, appPath, artifacts); return _runLinux(argResults, appPath, artifacts);
} }
} }
} }
...@@ -4,13 +4,11 @@ ...@@ -4,13 +4,11 @@
import 'dart:io'; import 'dart:io';
import 'package:mockito/mockito.dart'; import 'package:args/command_runner.dart';
import 'package:path/path.dart' as p; import 'package:path/path.dart' as p;
import 'package:sky_tools/src/init.dart'; import 'package:sky_tools/src/init.dart';
import 'package:test/test.dart'; import 'package:test/test.dart';
import 'src/common.dart';
main() => defineTests(); main() => defineTests();
defineTests() { defineTests() {
...@@ -27,14 +25,13 @@ defineTests() { ...@@ -27,14 +25,13 @@ defineTests() {
// Verify that we create a project that is well-formed. // Verify that we create a project that is well-formed.
test('init sky-simple', () async { test('init sky-simple', () async {
InitCommandHandler handler = new InitCommandHandler(); InitCommand command = new InitCommand();
MockArgResults results = new MockArgResults(); CommandRunner runner = new CommandRunner('test_flutter', '')
when(results['help']).thenReturn(false); ..addCommand(command);
when(results['pub']).thenReturn(true); await runner.run(['init', '--out', temp.path])
when(results.wasParsed('out')).thenReturn(true); .then((int code) => expect(code, equals(0)));
when(results['out']).thenReturn(temp.path);
await handler.processArgResults(results); String path = p.join(temp.path, 'lib', 'main.dart');
String path = p.join(temp.path, 'lib/main.dart');
expect(new File(path).existsSync(), true); expect(new File(path).existsSync(), true);
ProcessResult exec = Process.runSync( ProcessResult exec = Process.runSync(
'dartanalyzer', ['--fatal-warnings', path], 'dartanalyzer', ['--fatal-warnings', path],
......
...@@ -4,9 +4,10 @@ ...@@ -4,9 +4,10 @@
library install_test; library install_test;
import 'package:args/command_runner.dart';
import 'package:mockito/mockito.dart'; import 'package:mockito/mockito.dart';
import 'package:sky_tools/src/install.dart';
import 'package:sky_tools/src/application_package.dart'; import 'package:sky_tools/src/application_package.dart';
import 'package:sky_tools/src/install.dart';
import 'package:test/test.dart'; import 'package:test/test.dart';
import 'src/common.dart'; import 'src/common.dart';
...@@ -23,12 +24,11 @@ defineTests() { ...@@ -23,12 +24,11 @@ defineTests() {
MockAndroidDevice android = new MockAndroidDevice(); MockAndroidDevice android = new MockAndroidDevice();
when(android.isConnected()).thenReturn(true); when(android.isConnected()).thenReturn(true);
when(android.installApp(any)).thenReturn(true); when(android.installApp(any)).thenReturn(true);
InstallCommandHandler handler = new InstallCommandHandler(android); InstallCommand command = new InstallCommand(android);
MockArgResults results = new MockArgResults(); CommandRunner runner = new CommandRunner('test_flutter', '')
when(results['help']).thenReturn(false); ..addCommand(command);
handler runner.run(['install'])
.processArgResults(results)
.then((int code) => expect(code, equals(0))); .then((int code) => expect(code, equals(0)));
}); });
}); });
......
...@@ -2,15 +2,9 @@ ...@@ -2,15 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'package:args/args.dart';
import 'package:mockito/mockito.dart'; import 'package:mockito/mockito.dart';
import 'package:sky_tools/src/device.dart'; import 'package:sky_tools/src/device.dart';
class MockArgResults extends Mock implements ArgResults {
@override
dynamic noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
}
class MockAndroidDevice extends Mock implements AndroidDevice { class MockAndroidDevice extends Mock implements AndroidDevice {
@override @override
dynamic noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation); dynamic noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment