| // 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/common.dart'; |
| import '../base/os.dart'; |
| import '../cache.dart'; |
| import '../dart/pub.dart'; |
| import '../project.dart'; |
| import '../reporting/reporting.dart'; |
| import '../runner/flutter_command.dart'; |
| |
| class PackagesCommand extends FlutterCommand { |
| PackagesCommand() { |
| addSubcommand(PackagesGetCommand('get', false)); |
| addSubcommand(PackagesGetCommand('upgrade', true)); |
| addSubcommand(PackagesTestCommand()); |
| addSubcommand(PackagesPublishCommand()); |
| addSubcommand(PackagesForwardCommand('downgrade', 'Downgrade packages in a Flutter project', requiresPubspec: true)); |
| addSubcommand(PackagesForwardCommand('deps', 'Print package dependencies', requiresPubspec: true)); |
| addSubcommand(PackagesForwardCommand('run', 'Run an executable from a package', requiresPubspec: true)); |
| addSubcommand(PackagesForwardCommand('cache', 'Work with the Pub system cache')); |
| addSubcommand(PackagesForwardCommand('version', 'Print Pub version')); |
| addSubcommand(PackagesForwardCommand('uploader', 'Manage uploaders for a package on pub.dev')); |
| addSubcommand(PackagesForwardCommand('global', 'Work with Pub global packages')); |
| addSubcommand(PackagesPassthroughCommand()); |
| } |
| |
| @override |
| final String name = 'pub'; |
| |
| @override |
| List<String> get aliases => const <String>['packages']; |
| |
| @override |
| final String description = 'Commands for managing Flutter packages.'; |
| |
| @override |
| Future<Set<DevelopmentArtifact>> get requiredArtifacts async => const <DevelopmentArtifact>{ |
| DevelopmentArtifact.universal, |
| }; |
| |
| @override |
| Future<FlutterCommandResult> runCommand() async => null; |
| } |
| |
| class PackagesGetCommand extends FlutterCommand { |
| PackagesGetCommand(this.name, this.upgrade) { |
| requiresPubspecYaml(); |
| argParser.addFlag('offline', |
| negatable: false, |
| help: 'Use cached packages instead of accessing the network.', |
| ); |
| } |
| |
| @override |
| final String name; |
| |
| final bool upgrade; |
| |
| @override |
| String get description { |
| return '${ upgrade ? "Upgrade" : "Get" } packages in a Flutter project.'; |
| } |
| |
| @override |
| String get invocation { |
| return '${runner.executableName} pub $name [<target directory>]'; |
| } |
| |
| @override |
| Future<Map<CustomDimensions, String>> get usageValues async { |
| final Map<CustomDimensions, String> usageValues = <CustomDimensions, String>{}; |
| final String workingDirectory = argResults.rest.length == 1 ? argResults.rest[0] : null; |
| final String target = findProjectRoot(workingDirectory); |
| if (target == null) { |
| return usageValues; |
| } |
| final FlutterProject rootProject = FlutterProject.fromPath(target); |
| final bool hasPlugins = rootProject.flutterPluginsFile.existsSync(); |
| if (hasPlugins) { |
| final int numberOfPlugins = (rootProject.flutterPluginsFile.readAsLinesSync()).length; |
| usageValues[CustomDimensions.commandPackagesNumberPlugins] = '$numberOfPlugins'; |
| } else { |
| usageValues[CustomDimensions.commandPackagesNumberPlugins] = '0'; |
| } |
| usageValues[CustomDimensions.commandPackagesProjectModule] = '${rootProject.isModule}'; |
| return usageValues; |
| } |
| |
| Future<void> _runPubGet(String directory) async { |
| final Stopwatch pubGetTimer = Stopwatch()..start(); |
| try { |
| await pubGet(context: PubContext.pubGet, |
| directory: directory, |
| upgrade: upgrade , |
| offline: argResults['offline'], |
| checkLastModified: false, |
| ); |
| pubGetTimer.stop(); |
| PubGetEvent(success: true).send(); |
| flutterUsage.sendTiming('packages-pub-get', 'success', pubGetTimer.elapsed); |
| } catch (_) { |
| pubGetTimer.stop(); |
| PubGetEvent(success: false).send(); |
| flutterUsage.sendTiming('packages-pub-get', 'failure', pubGetTimer.elapsed); |
| rethrow; |
| } |
| } |
| |
| @override |
| Future<FlutterCommandResult> runCommand() async { |
| if (argResults.rest.length > 1) |
| throwToolExit('Too many arguments.\n$usage'); |
| |
| final String workingDirectory = argResults.rest.length == 1 ? argResults.rest[0] : null; |
| final String target = findProjectRoot(workingDirectory); |
| if (target == null) { |
| throwToolExit( |
| 'Expected to find project root in ' |
| '${ workingDirectory ?? "current working directory" }.' |
| ); |
| } |
| |
| await _runPubGet(target); |
| final FlutterProject rootProject = FlutterProject.fromPath(target); |
| await rootProject.ensureReadyForPlatformSpecificTooling(checkProjects: true); |
| |
| // Get/upgrade packages in example app as well |
| if (rootProject.hasExampleApp) { |
| final FlutterProject exampleProject = rootProject.example; |
| await _runPubGet(exampleProject.directory.path); |
| await exampleProject.ensureReadyForPlatformSpecificTooling(checkProjects: true); |
| } |
| |
| return null; |
| } |
| } |
| |
| class PackagesTestCommand extends FlutterCommand { |
| PackagesTestCommand() { |
| requiresPubspecYaml(); |
| } |
| |
| @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 ' |
| 'flutter environment it hosts the tests in a pure Dart environment. The main ' |
| 'differences are that the "dart:ui" library is not available and that tests ' |
| 'run faster. This is helpful for testing libraries that do not depend on any ' |
| 'packages from the Flutter SDK. It is equivalent to "pub run test".'; |
| } |
| |
| @override |
| String get invocation { |
| return '${runner.executableName} pub test [<tests...>]'; |
| } |
| |
| @override |
| Future<FlutterCommandResult> runCommand() async { |
| Cache.releaseLockEarly(); |
| await pub(<String>['run', 'test', ...argResults.rest], context: PubContext.runTest, retry: false); |
| return null; |
| } |
| } |
| |
| class PackagesPublishCommand extends FlutterCommand { |
| PackagesPublishCommand() { |
| requiresPubspecYaml(); |
| argParser.addFlag('dry-run', |
| abbr: 'n', |
| negatable: false, |
| help: 'Validate but do not publish the package.', |
| ); |
| argParser.addFlag('force', |
| abbr: 'f', |
| negatable: false, |
| help: 'Publish without confirmation if there are no errors.', |
| ); |
| } |
| |
| @override |
| String get name => 'publish'; |
| |
| @override |
| String get description { |
| return 'Publish the current package to pub.dev'; |
| } |
| |
| @override |
| String get invocation { |
| return '${runner.executableName} pub publish [--dry-run]'; |
| } |
| |
| @override |
| Future<FlutterCommandResult> runCommand() async { |
| final List<String> args = <String>[ |
| ...argResults.rest, |
| if (argResults['dry-run']) '--dry-run', |
| if (argResults['force']) '--force', |
| ]; |
| Cache.releaseLockEarly(); |
| await pubInteractively(<String>['publish', ...args]); |
| return null; |
| } |
| } |
| |
| class PackagesForwardCommand extends FlutterCommand { |
| PackagesForwardCommand(this._commandName, this._description, {bool requiresPubspec = false}) { |
| if (requiresPubspec) { |
| requiresPubspecYaml(); |
| } |
| } |
| final String _commandName; |
| final String _description; |
| |
| @override |
| String get name => _commandName; |
| |
| @override |
| String get description { |
| return '$_description.\n' |
| 'This runs the "pub" tool in a Flutter context.'; |
| } |
| |
| @override |
| String get invocation { |
| return '${runner.executableName} pub $_commandName [<arguments...>]'; |
| } |
| |
| @override |
| Future<FlutterCommandResult> runCommand() async { |
| Cache.releaseLockEarly(); |
| await pubInteractively(<String>[_commandName, ...argResults.rest]); |
| return null; |
| } |
| |
| } |
| |
| class PackagesPassthroughCommand extends FlutterCommand { |
| PackagesPassthroughCommand() { |
| requiresPubspecYaml(); |
| } |
| |
| @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<FlutterCommandResult> runCommand() async { |
| Cache.releaseLockEarly(); |
| await pubInteractively(argResults.rest); |
| return null; |
| } |
| } |