Commit 194a9ef3 authored by Dan Rubel's avatar Dan Rubel Committed by GitHub

implement flutter packages get/upgrade command (#5603)

* implement flutter packages get/upgrade command
* alias flutter pub
* refactor findProjectRoot for use by multiple commands

fixes https://github.com/flutter/flutter/issues/4994
parent b5f763b4
......@@ -25,6 +25,7 @@ import 'src/commands/install.dart';
import 'src/commands/listen.dart';
import 'src/commands/logs.dart';
import 'src/commands/setup.dart';
import 'src/commands/packages.dart';
import 'src/commands/precache.dart';
import 'src/commands/refresh.dart';
import 'src/commands/run.dart';
......@@ -68,6 +69,7 @@ Future<Null> main(List<String> args) async {
..addCommand(new InstallCommand())
..addCommand(new ListenCommand())
..addCommand(new LogsCommand())
..addCommand(new PackagesCommand())
..addCommand(new PrecacheCommand())
..addCommand(new RefreshCommand())
..addCommand(new RunCommand())
......
......@@ -150,3 +150,19 @@ Future<bool> _isPortAvailable(int port) async {
return false;
}
}
/// Find and return the project root directory relative to the specified
/// directory or the current working directory if none specified.
/// Return `null` if the project root could not be found
/// or if the project root is the flutter repository root.
String findProjectRoot([String directory]) {
const String kProjectRootSentinel = 'pubspec.yaml';
directory ??= Directory.current.path;
while (true) {
if (FileSystemEntity.isFileSync(path.join(directory, kProjectRootSentinel)))
return directory;
String parent = FileSystemEntity.parentOf(directory);
if (directory == parent) return null;
directory = parent;
}
}
// 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 '../base/os.dart';
import '../dart/pub.dart';
import '../globals.dart';
import '../runner/flutter_command.dart';
class PackagesCommand extends FlutterCommand {
PackagesCommand() {
addSubcommand(new PackagesGetCommand('get', false));
addSubcommand(new PackagesGetCommand('upgrade', true));
}
@override
final String name = 'packages';
@override
List<String> get aliases => const <String>['pub'];
@override
final String description = 'Commands for managing Flutter packages.';
@override
Future<int> runInProject() => new Future<int>.value(0);
}
class PackagesGetCommand extends FlutterCommand {
@override
final String name;
final bool upgrade;
PackagesGetCommand(this.name, this.upgrade);
// TODO: implement description
@override
String get description =>
(upgrade ? 'Upgrade' : 'Get') + ' packages in a Flutter project.';
@override
bool get requiresProjectRoot => false;
@override
String get invocation =>
"${runner.executableName} packages $name [<target directory>]";
@override
Future<int> runInProject() async {
if (argResults.rest.length > 1) {
printStatus('Too many arguments.');
printStatus(usage);
return 1;
}
String target = findProjectRoot(
argResults.rest.length == 1 ? argResults.rest[0] : null);
if (target == null) {
printStatus('Expected to find project root starting at ' +
(argResults.rest.length == 1
? argResults.rest[0]
: 'current working directory'));
printStatus(usage);
return 1;
}
return pubGet(directory: target, upgrade: upgrade, checkLastModified: false);
}
}
......@@ -3,10 +3,8 @@
// found in the LICENSE file.
import 'dart:async';
import 'dart:io';
import 'package:path/path.dart' as path;
import '../base/os.dart';
import '../base/process.dart';
import '../dart/pub.dart';
import '../cache.dart';
......@@ -90,20 +88,4 @@ class UpgradeCommand extends FlutterCommand {
|| _gitChangedRegex.hasMatch(line)
|| line == 'Fast-forward';
}
/// Find and return the project root directory relative to the specified
/// directory or the current working directory if none specified.
/// Return `null` if the project root could not be found
/// or if the project root is the flutter repository root.
static String findProjectRoot([String directory]) {
directory ??= Directory.current.path;
while (true) {
if (FileSystemEntity.isFileSync(path.join(directory, 'pubspec.yaml')))
return directory;
String parent = FileSystemEntity.parentOf(directory);
if (directory == parent)
return null;
directory = parent;
}
}
}
......@@ -30,6 +30,7 @@ import 'install_test.dart' as install_test;
import 'listen_test.dart' as listen_test;
import 'logs_test.dart' as logs_test;
import 'os_utils_test.dart' as os_utils_test;
import 'packages_test.dart' as packages_test;
import 'protocol_discovery_test.dart' as protocol_discovery_test;
import 'run_test.dart' as run_test;
import 'stop_test.dart' as stop_test;
......@@ -62,6 +63,7 @@ void main() {
listen_test.main();
logs_test.main();
os_utils_test.main();
packages_test.main();
protocol_discovery_test.main();
run_test.main();
stop_test.main();
......
// 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:io';
import 'package:args/command_runner.dart';
import 'package:flutter_tools/src/commands/create.dart';
import 'package:flutter_tools/src/commands/packages.dart';
import 'package:test/test.dart';
import 'src/common.dart';
import 'src/context.dart';
void main() {
group('packages', () {
Directory temp;
setUp(() {
temp = Directory.systemTemp.createTempSync('flutter_tools');
});
tearDown(() {
temp.deleteSync(recursive: true);
});
Future<Null> createProject() async {
CreateCommand command = new CreateCommand();
CommandRunner runner = createTestCommandRunner(command);
int code = await runner.run(<String>['create', '--no-pub', temp.path]);
expect(code, 0);
}
Future<Null> runCommand(String verb) async {
await createProject();
PackagesCommand command = new PackagesCommand();
CommandRunner runner = createTestCommandRunner(command);
int code = await runner.run(<String>['packages', verb, temp.path]);
expect(code, 0);
}
void expectExists(String relPath) {
expect(FileSystemEntity.isFileSync('${temp.path}/$relPath'), true);
}
// Verify that we create a project that is well-formed.
testUsingContext('get', () async {
await runCommand('get');
expectExists('lib/main.dart');
expectExists('.packages');
});
testUsingContext('upgrade', () async {
await runCommand('upgrade');
expectExists('lib/main.dart');
expectExists('.packages');
});
});
}
......@@ -6,6 +6,7 @@ import 'dart:async';
import 'dart:io';
import 'package:args/command_runner.dart';
import 'package:flutter_tools/src/base/os.dart';
import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/commands/create.dart';
import 'package:flutter_tools/src/commands/upgrade.dart';
......@@ -57,18 +58,18 @@ void main() {
await createProject();
String proj = temp.path;
expect(UpgradeCommand.findProjectRoot(proj), proj);
expect(UpgradeCommand.findProjectRoot(path.join(proj, 'lib')), proj);
expect(findProjectRoot(proj), proj);
expect(findProjectRoot(path.join(proj, 'lib')), proj);
String hello = path.join(Cache.flutterRoot, 'examples', 'hello_world');
expect(UpgradeCommand.findProjectRoot(hello), hello);
expect(UpgradeCommand.findProjectRoot(path.join(hello, 'lib')), hello);
expect(findProjectRoot(hello), hello);
expect(findProjectRoot(path.join(hello, 'lib')), hello);
});
testUsingContext('outside project', () async {
await createProject();
expect(UpgradeCommand.findProjectRoot(temp.parent.path), null);
expect(UpgradeCommand.findProjectRoot(Cache.flutterRoot), null);
expect(findProjectRoot(temp.parent.path), null);
expect(findProjectRoot(Cache.flutterRoot), 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