Commit 292abf72 authored by Ian Hickson's avatar Ian Hickson Committed by GitHub

"flutter packages pub ..." to passthrough to dart pub (#10044)

parent 91b1a076
......@@ -13,6 +13,8 @@ class PackagesCommand extends FlutterCommand {
PackagesCommand() {
addSubcommand(new PackagesGetCommand('get', false));
addSubcommand(new PackagesGetCommand('upgrade', true));
addSubcommand(new PackagesTestCommand());
addSubcommand(new PackagesPassthroughCommand());
}
@override
......@@ -35,11 +37,6 @@ class PackagesCommand extends FlutterCommand {
}
class PackagesGetCommand extends FlutterCommand {
@override
final String name;
final bool upgrade;
PackagesGetCommand(this.name, this.upgrade) {
argParser.addFlag('offline',
negatable: false,
......@@ -47,6 +44,11 @@ class PackagesGetCommand extends FlutterCommand {
);
}
@override
final String name;
final bool upgrade;
@override
String get description {
return '${ upgrade ? "Upgrade" : "Get" } packages in a Flutter project.';
......@@ -72,9 +74,6 @@ class PackagesGetCommand extends FlutterCommand {
);
}
// TODO(ianh): If the user is using a local build, we should use the
// packages from their build instead of the cache.
await pubGet(
directory: target,
upgrade: upgrade,
......@@ -83,3 +82,47 @@ class PackagesGetCommand extends FlutterCommand {
);
}
}
class PackagesTestCommand extends FlutterCommand {
@override
String get name => 'test';
@override
String get description {
return 'Run the "test" package.\n'
'This is similar to "flutter test", but instead of hosting the tests in the\n'
'flutter environment it hosts the tests in a pure Dart environment. The main\n'
'differences are that the "dart:ui" library is not available and that tests\n'
'run faster. This is helpful for testing libraries that do not depend on any\n'
'packages from the Flutter SDK. It is equivalent to "pub run test".';
}
@override
String get invocation {
return '${runner.executableName} packages test [<tests...>]';
}
@override
Future<Null> runCommand() => pub(<String>['run', 'test']..addAll(argResults.rest));
}
class PackagesPassthroughCommand extends FlutterCommand {
PackagesPassthroughCommand();
@override
String get name => 'pub';
@override
String get description {
return 'Pass the remaining arguments to Dart\'s "pub" tool.\n'
'This runs the "pub" tool in a Flutter context.';
}
@override
String get invocation {
return '${runner.executableName} packages pub [<arguments...>]';
}
@override
Future<Null> runCommand() => pub(argResults.rest);
}
......@@ -47,19 +47,18 @@ Future<Null> pubGet({
if (!checkLastModified || _shouldRunPubGet(pubSpecYaml: pubSpecYaml, dotPackages: dotPackages)) {
final String command = upgrade ? 'upgrade' : 'get';
final Status status = logger.startProgress("Running 'flutter packages $command' in ${fs.path.basename(directory)}...",
expectSlowOperation: true);
final List<String> args = <String>[sdkBinaryName('pub'), '--verbosity=warning', command, '--no-precompile'];
final Status status = logger.startProgress(
'Running "flutter packages $command" in ${fs.path.basename(directory)}...',
expectSlowOperation: true,
);
final List<String> args = <String>['--verbosity=warning', command, '--no-precompile'];
if (offline)
args.add('--offline');
final int code = await runCommandAndStreamOutput(args,
workingDirectory: directory,
mapFunction: _filterOverrideWarnings,
environment: <String, String>{ 'FLUTTER_ROOT': Cache.flutterRoot, _pubEnvironmentKey: _getPubEnvironmentValue() }
);
try {
await pub(args, directory: directory, filter: _filterOverrideWarnings, failureMessage: 'pub $command failed');
} finally {
status.stop();
if (code != 0)
throwToolExit('pub $command failed ($code)', exitCode: code);
}
}
if (!dotPackages.existsSync())
......@@ -69,6 +68,24 @@ Future<Null> pubGet({
throwToolExit('$directory: pub did not update .packages file (pubspec.yaml file has a newer timestamp)');
}
typedef String MessageFilter(String message);
Future<Null> pub(List<String> arguments, {
String directory,
MessageFilter filter,
String failureMessage: 'pub failed'
}) async {
final List<String> command = <String>[ sdkBinaryName('pub') ]..addAll(arguments);
final int code = await runCommandAndStreamOutput(
command,
workingDirectory: directory,
mapFunction: filter,
environment: <String, String>{ 'FLUTTER_ROOT': Cache.flutterRoot, _pubEnvironmentKey: _getPubEnvironmentValue() }
);
if (code != 0)
throwToolExit('$failureMessage ($code)', exitCode: code);
}
final RegExp _analyzerWarning = new RegExp(r'^! \w+ [^ ]+ from path \.\./\.\./bin/cache/dart-sdk/lib/\w+$');
/// The console environment key used by the pub tool.
......
......@@ -6,20 +6,19 @@ import 'dart:async';
import 'package:args/command_runner.dart';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/io.dart';
import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/commands/packages.dart';
import 'package:process/process.dart';
import 'package:test/test.dart';
import '../src/common.dart';
import '../src/context.dart';
void main() {
group('packages', () {
Directory temp;
setUpAll(() {
Cache.disableLocking();
});
group('packages get/upgrade', () {
Directory temp;
setUp(() {
temp = fs.systemTempDirectory.createTempSync('flutter_tools');
......@@ -68,4 +67,104 @@ void main() {
expectExists(projectPath, '.packages');
});
});
group('packages test/pub', () {
final List<List<dynamic>> log = <List<dynamic>>[];
testUsingContext('test', () async {
log.clear();
await createTestCommandRunner(new PackagesCommand()).run(<String>['packages', 'test']);
expect(log, hasLength(1));
expect(log[0], hasLength(3));
expect(log[0][0], matches(r'dart-sdk[\\/]bin[\\/]pub'));
expect(log[0][1], 'run');
expect(log[0][2], 'test');
}, overrides: <Type, Generator>{
ProcessManager: () {
return new MockProcessManager((List<dynamic> command) {
log.add(command);
});
},
});
testUsingContext('run', () async {
log.clear();
await createTestCommandRunner(new PackagesCommand()).run(<String>['packages', '--verbose', 'pub', 'run', '--foo', 'bar']);
expect(log, hasLength(1));
expect(log[0], hasLength(4));
expect(log[0][0], matches(r'dart-sdk[\\/]bin[\\/]pub'));
expect(log[0][1], 'run');
expect(log[0][2], '--foo');
expect(log[0][3], 'bar');
}, overrides: <Type, Generator>{
ProcessManager: () {
return new MockProcessManager((List<dynamic> command) {
log.add(command);
});
},
});
});
}
typedef void StartCallback(List<dynamic> command);
class MockProcessManager implements ProcessManager {
MockProcessManager(this.onStart);
final StartCallback onStart;
@override
Future<Process> start(
List<dynamic> command, {
String workingDirectory,
Map<String, String> environment,
bool includeParentEnvironment: true,
bool runInShell: false,
ProcessStartMode mode: ProcessStartMode.NORMAL,
}) {
onStart(command);
return new Future<Process>.value(new MockProcess());
}
@override
dynamic noSuchMethod(Invocation invocation) => null;
}
class MockProcess implements Process {
@override
Stream<List<int>> get stdout => new MockStream<List<int>>();
@override
Stream<List<int>> get stderr => new MockStream<List<int>>();
@override
Future<int> get exitCode => new Future<int>.value(0);
@override
dynamic noSuchMethod(Invocation invocation) => null;
}
class MockStream<T> implements Stream<T> {
@override
Stream<S> transform<S>(StreamTransformer<T, S> streamTransformer) => new MockStream<S>();
@override
Stream<T> where(bool test(T event)) => new MockStream<T>();
@override
StreamSubscription<T> listen(void onData(T event), {Function onError, void onDone(), bool cancelOnError}) {
return new MockStreamSubscription<T>();
}
@override
dynamic noSuchMethod(Invocation invocation) => null;
}
class MockStreamSubscription<T> implements StreamSubscription<T> {
@override
Future<E> asFuture<E>([E futureValue]) => new Future<E>.value();
@override
Future<Null> cancel() => null;
@override
dynamic noSuchMethod(Invocation invocation) => null;
}
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