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
This diff is collapsed.
......@@ -8,11 +8,10 @@ import 'dart:async';
import 'dart:io';
import 'package:archive/archive.dart';
import 'package:args/args.dart';
import 'package:args/command_runner.dart';
import 'package:yaml/yaml.dart';
import 'artifacts.dart';
import 'common.dart';
const String _kSnapshotKey = 'snapshot_blob.bin';
const List<String> _kDensities = const ['drawable-xxhdpi'];
......@@ -127,41 +126,33 @@ Future<ArchiveFile> _createSnapshotFile(String snapshotPath) async {
return new ArchiveFile(_kSnapshotKey, content.length, content);
}
class BuildCommandHandler extends CommandHandler {
BuildCommandHandler() : super('build', 'Create a Flutter app.');
ArgParser get parser {
ArgParser parser = new ArgParser();
parser.addFlag('help', abbr: 'h', negatable: false);
parser.addOption('asset-base', defaultsTo: 'packages/material_design_icons/icons');
parser.addOption('compiler');
parser.addOption('main', defaultsTo: 'lib/main.dart');
parser.addOption('manifest');
parser.addOption('output-file', abbr: 'o', defaultsTo: 'app.flx');
parser.addOption('package-root', defaultsTo: 'packages');
parser.addOption('snapshot', defaultsTo: 'snapshot_blob.bin');
return parser;
class BuildCommand extends Command {
final name = 'build';
final description = 'Create a Flutter app.';
BuildCommand() {
argParser.addOption('asset-base', defaultsTo: 'packages/material_design_icons/icons');
argParser.addOption('compiler');
argParser.addOption('main', defaultsTo: 'lib/main.dart');
argParser.addOption('manifest');
argParser.addOption('output-file', abbr: 'o', defaultsTo: 'app.flx');
argParser.addOption('package-root', defaultsTo: 'packages');
argParser.addOption('snapshot', defaultsTo: 'snapshot_blob.bin');
}
@override
Future<int> processArgResults(ArgResults results) async {
if (results['help']) {
print(parser.usage);
return 0;
}
String manifestPath = results['manifest'];
Future<int> run() async {
String manifestPath = argResults['manifest'];
Map manifestDescriptor = await _loadManifest(manifestPath);
Iterable<_Asset> assets = _parseAssets(manifestDescriptor, manifestPath);
Iterable<_MaterialAsset> materialAssets = _parseMaterialAssets(manifestDescriptor);
Archive archive = new Archive();
String snapshotPath = results['snapshot'];
String snapshotPath = argResults['snapshot'];
await _compileSnapshot(
compilerPath: results['compiler'],
mainPath: results['main'],
packageRoot: results['package-root'],
compilerPath: argResults['compiler'],
mainPath: argResults['main'],
packageRoot: argResults['package-root'],
snapshotPath: snapshotPath);
archive.addFile(await _createSnapshotFile(snapshotPath));
......@@ -169,12 +160,12 @@ class BuildCommandHandler extends CommandHandler {
archive.addFile(await _createFile(asset.key, asset.base));
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)
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.writeAsBytes(new ZipEncoder().encode(archive), mode: FileMode.APPEND);
return 0;
......
......@@ -6,63 +6,48 @@ library sky_tools.cache;
import 'dart:async';
import 'package:args/args.dart';
import 'package:args/command_runner.dart';
import 'package:logging/logging.dart';
import 'artifacts.dart';
import 'common.dart';
final Logger _logging = new Logger('sky_tools.cache');
class CacheCommandHandler extends CommandHandler {
CacheCommandHandler() : super('cache', 'Manages sky_tools\' cache of binary artifacts.');
ArgParser get parser {
ArgParser parser = new ArgParser();
parser.addFlag('help', abbr: 'h', negatable: false);
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;
class CacheCommand extends Command {
final name = 'cache';
final description = 'Manages sky_tools\' cache of binary artifacts.';
CacheCommand() {
addSubcommand(new _ClearCommand());
addSubcommand(new _PopulateCommand());
}
}
Future<int> _clear(String packageRoot, ArgResults results) async {
if (results['help']) {
print('Clears all artifacts from the cache.');
print(parser.usage);
return 0;
}
ArtifactStore artifacts = new ArtifactStore(packageRoot);
await artifacts.clear();
return 0;
class _ClearCommand extends Command {
final name = 'clear';
final description = 'Clears all artifacts from the cache.';
_ClearCommand() {
argParser.addOption('package-root', defaultsTo: 'packages');
}
Future<int> _populate(String packageRoot, ArgResults results) async {
if (results['help']) {
print('Populates the cache with all known artifacts.');
print(parser.usage);
return 0;
}
ArtifactStore artifacts = new ArtifactStore(packageRoot);
@override
Future<int> run() async {
ArtifactStore artifacts = new ArtifactStore(argResults['package-root']);
await artifacts.populate();
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
Future<int> processArgResults(ArgResults results) async {
if (results['help'] || results.command == null) {
print(parser.usage);
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;
}
Future<int> run() async {
ArtifactStore artifacts = new ArtifactStore(argResults['package-root']);
await artifacts.populate();
return 0;
}
}
// 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';
import 'package:logging/logging.dart';
import 'package:path/path.dart' as path;
import 'process_wrapper.dart';
import 'application_package.dart';
import 'process_wrapper.dart';
final Logger _logging = new Logger('sky_tools.device');
......
......@@ -7,41 +7,30 @@ library sky_tools.init;
import 'dart:async';
import 'dart:io';
import 'package:args/args.dart';
import 'package:args/command_runner.dart';
import 'package:mustache4dart/mustache4dart.dart' as mustache;
import 'package:path/path.dart' as p;
import 'common.dart';
class InitCommandHandler extends CommandHandler {
InitCommandHandler() : super('init', 'Create a new sky project.');
ArgParser get parser {
// 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',
class InitCommand extends Command {
final name = 'init';
final description = 'Create a new sky project.';
InitCommand() {
argParser.addOption('out', abbr: 'o', help: 'The output directory.');
argParser.addFlag('pub',
defaultsTo: true,
help: 'Whether to run pub after the project has been created.');
return parser;
}
@override
Future<int> processArgResults(ArgResults results) async {
if (results['help']) {
printUsage();
return 0;
}
if (!results.wasParsed('out')) {
printUsage('No option specified for the output directory.');
Future<int> run() async {
if (!argResults.wasParsed('out')) {
print('No option specified for the output directory.');
print(argParser.getUsage());
return 2;
}
// 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);
......@@ -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...");
Process process =
await Process.start('pub', ['get'], workingDirectory: out.path);
......
......@@ -6,32 +6,19 @@ library sky_tools.install;
import 'dart:async';
import 'package:args/args.dart';
import 'package:args/command_runner.dart';
import 'application_package.dart';
import 'common.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;
InstallCommandHandler([this.android])
: super('install', 'Install your Sky app on attached devices.');
InstallCommand([this.android]);
@override
ArgParser get parser {
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;
}
Future<int> run() async {
bool installedSomewhere = false;
Map<BuildPlatform, ApplicationPackage> packages =
......
......@@ -8,26 +8,23 @@ import 'dart:async';
import 'dart:io';
import 'package:args/args.dart';
import 'package:args/command_runner.dart';
import 'package:logging/logging.dart';
import 'package:path/path.dart' as path;
import 'artifacts.dart';
import 'common.dart';
import 'process.dart';
final Logger _logging = new Logger('sky_tools.run_mojo');
class RunMojoCommandHandler extends CommandHandler {
RunMojoCommandHandler() : super('run_mojo', 'Run a Flutter app in mojo.');
ArgParser get parser {
ArgParser parser = new ArgParser();
parser.addFlag('android', negatable: false, help: 'Run on an Android device');
parser.addFlag('help', abbr: 'h', negatable: false);
parser.addOption('app', defaultsTo: 'app.flx');
parser.addOption('mojo-path', help: 'Path to directory containing mojo_shell and services');
parser.addOption('package-root', defaultsTo: 'packages');
return parser;
class RunMojoCommand extends Command {
final name = 'run_mojo';
final description = 'Run a Flutter app in mojo.';
RunMojoCommand() {
argParser.addFlag('android', negatable: false, help: 'Run on an Android device');
argParser.addOption('app', defaultsTo: 'app.flx');
argParser.addOption('mojo-path', help: 'Path to directory containing mojo_shell and services');
argParser.addOption('package-root', defaultsTo: 'packages');
}
Future<String> _makePathAbsolute(String relativePath) async {
......@@ -71,22 +68,18 @@ class RunMojoCommandHandler extends CommandHandler {
}
@override
Future<int> processArgResults(ArgResults results) async {
if (results['help']) {
print(parser.usage);
return 0;
}
if (results['mojo-path'] == null) {
Future<int> run() async {
if (argResults['mojo-path'] == null) {
_logging.severe('Must specify --mojo-path to mojo_run');
return 1;
}
String packageRoot = results['package-root'];
String packageRoot = argResults['package-root'];
ArtifactStore artifacts = new ArtifactStore(packageRoot);
String appPath = await _makePathAbsolute(results['app']);
if (results['android']) {
return _runAndroid(results, appPath, artifacts);
String appPath = await _makePathAbsolute(argResults['app']);
if (argResults['android']) {
return _runAndroid(argResults, appPath, artifacts);
} else {
return _runLinux(results, appPath, artifacts);
return _runLinux(argResults, appPath, artifacts);
}
}
}
......@@ -4,13 +4,11 @@
import 'dart:io';
import 'package:mockito/mockito.dart';
import 'package:args/command_runner.dart';
import 'package:path/path.dart' as p;
import 'package:sky_tools/src/init.dart';
import 'package:test/test.dart';
import 'src/common.dart';
main() => defineTests();
defineTests() {
......@@ -27,14 +25,13 @@ defineTests() {
// Verify that we create a project that is well-formed.
test('init sky-simple', () async {
InitCommandHandler handler = new InitCommandHandler();
MockArgResults results = new MockArgResults();
when(results['help']).thenReturn(false);
when(results['pub']).thenReturn(true);
when(results.wasParsed('out')).thenReturn(true);
when(results['out']).thenReturn(temp.path);
await handler.processArgResults(results);
String path = p.join(temp.path, 'lib/main.dart');
InitCommand command = new InitCommand();
CommandRunner runner = new CommandRunner('test_flutter', '')
..addCommand(command);
await runner.run(['init', '--out', temp.path])
.then((int code) => expect(code, equals(0)));
String path = p.join(temp.path, 'lib', 'main.dart');
expect(new File(path).existsSync(), true);
ProcessResult exec = Process.runSync(
'dartanalyzer', ['--fatal-warnings', path],
......
......@@ -4,9 +4,10 @@
library install_test;
import 'package:args/command_runner.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/install.dart';
import 'package:test/test.dart';
import 'src/common.dart';
......@@ -23,12 +24,11 @@ defineTests() {
MockAndroidDevice android = new MockAndroidDevice();
when(android.isConnected()).thenReturn(true);
when(android.installApp(any)).thenReturn(true);
InstallCommandHandler handler = new InstallCommandHandler(android);
InstallCommand command = new InstallCommand(android);
MockArgResults results = new MockArgResults();
when(results['help']).thenReturn(false);
handler
.processArgResults(results)
CommandRunner runner = new CommandRunner('test_flutter', '')
..addCommand(command);
runner.run(['install'])
.then((int code) => expect(code, equals(0)));
});
});
......
......@@ -2,15 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:args/args.dart';
import 'package:mockito/mockito.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 {
@override
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