Index: sdk/lib/_internal/pub_generated/lib/src/command.dart |
diff --git a/sdk/lib/_internal/pub_generated/lib/src/command.dart b/sdk/lib/_internal/pub_generated/lib/src/command.dart |
index c000ccd780cab2c96dfc7805853229f55162af3b..9ac3674ea3726c15ddff43f4d59079c3c55db9e2 100644 |
--- a/sdk/lib/_internal/pub_generated/lib/src/command.dart |
+++ b/sdk/lib/_internal/pub_generated/lib/src/command.dart |
@@ -1,8 +1,15 @@ |
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
+// for details. All rights reserved. Use of this source code is governed by a |
+// BSD-style license that can be found in the LICENSE file. |
+ |
library pub.command; |
+ |
import 'dart:async'; |
import 'dart:math' as math; |
+ |
import 'package:args/args.dart'; |
import 'package:path/path.dart' as path; |
+ |
import 'command/build.dart'; |
import 'command/cache.dart'; |
import 'command/deps.dart'; |
@@ -23,10 +30,22 @@ import 'log.dart' as log; |
import 'global_packages.dart'; |
import 'system_cache.dart'; |
import 'utils.dart'; |
+ |
+/// The base class for commands for the pub executable. |
+/// |
+/// A command may either be a "leaf" command or it may be a parent for a set |
+/// of subcommands. Only leaf commands are ever actually invoked. If a command |
+/// has subcommands, then one of those must always be chosen. |
abstract class PubCommand { |
+ /// The commands that pub understands. |
static final Map<String, PubCommand> mainCommands = _initCommands(); |
+ |
+ /// The top-level [ArgParser] used to parse the pub command line. |
static final pubArgParser = _initArgParser(); |
+ |
+ /// Displays usage information for the app. |
static void printGlobalUsage() { |
+ // Build up a buffer so it shows up as a single log entry. |
var buffer = new StringBuffer(); |
buffer.writeln('Pub is a package manager for Dart.'); |
buffer.writeln(); |
@@ -41,21 +60,35 @@ abstract class PubCommand { |
'Run "pub help [command]" for more information about a command.'); |
buffer.writeln( |
'See http://dartlang.org/tools/pub for detailed documentation.'); |
+ |
log.message(buffer); |
} |
+ |
+ /// Fails with a usage error [message] when trying to select from one of |
+ /// [commands]. |
static void usageErrorWithCommands(Map<String, PubCommand> commands, |
String message) { |
throw new UsageException(message, _listCommands(commands)); |
} |
+ |
+ /// Writes [commands] in a nicely formatted list to [buffer]. |
static String _listCommands(Map<String, PubCommand> commands) { |
+ // If there are no subcommands, do nothing. |
if (commands.isEmpty) return ""; |
+ |
+ // Don't include aliases. |
var names = |
commands.keys.where((name) => !commands[name].aliases.contains(name)); |
+ |
+ // Filter out hidden ones, unless they are all hidden. |
var visible = names.where((name) => !commands[name].hidden); |
if (visible.isNotEmpty) names = visible; |
+ |
+ // Show the commands alphabetically. |
names = ordered(names); |
var length = names.map((name) => name.length).reduce(math.max); |
var isSubcommand = commands != mainCommands; |
+ |
var buffer = new StringBuffer(); |
buffer.writeln('Available ${isSubcommand ? "sub" : ""}commands:'); |
for (var name in names) { |
@@ -63,17 +96,30 @@ abstract class PubCommand { |
' ${padRight(name, length)} ' |
'${commands[name].description.split("\n").first}'); |
} |
+ |
return buffer.toString(); |
} |
+ |
SystemCache get cache => _cache; |
SystemCache _cache; |
+ |
GlobalPackages get globals => _globals; |
GlobalPackages _globals; |
+ |
+ /// The parsed options for the pub executable. |
ArgResults get globalOptions => _globalOptions; |
ArgResults _globalOptions; |
+ |
+ /// The parsed options for this command. |
ArgResults get commandOptions => _commandOptions; |
ArgResults _commandOptions; |
+ |
+ /// Gets the [Entrypoint] package for the current working directory. |
+ /// |
+ /// This will load the pubspec and fail with an error if the current directory |
+ /// is not a package. |
Entrypoint get entrypoint { |
+ // Lazy load it. |
if (_entrypoint == null) { |
_entrypoint = new Entrypoint( |
path.current, |
@@ -82,47 +128,113 @@ abstract class PubCommand { |
} |
return _entrypoint; |
} |
+ |
Entrypoint _entrypoint; |
+ |
+ /// A one-line description of this command. |
String get description; |
+ |
+ /// If the command is undocumented and should not appear in command listings, |
+ /// this will be `true`. |
bool get hidden { |
+ // Leaf commands are visible by default. |
if (subcommands.isEmpty) return false; |
+ |
+ // Otherwise, a command is hidden if all of its subcommands are. |
return subcommands.values.every((subcommand) => subcommand.hidden); |
} |
+ |
+ /// How to invoke this command (e.g. `"pub get [package]"`). |
String get usage; |
+ |
+ /// The URL for web documentation for this command. |
String get docUrl => null; |
+ |
+ /// Whether or not this command takes arguments in addition to options. |
+ /// |
+ /// If false, pub will exit with an error if arguments are provided. This |
+ /// only needs to be set in leaf commands. |
bool get takesArguments => false; |
+ |
+ /// Override this and return `false` to disallow trailing options from being |
+ /// parsed after a non-option argument is parsed. |
bool get allowTrailingOptions => true; |
+ |
+ /// Alternate names for this command. |
+ /// |
+ /// These names won't be used in the documentation, but they will work when |
+ /// invoked on the command line. |
final aliases = const <String>[]; |
+ |
+ /// The [ArgParser] for this command. |
ArgParser get commandParser => _commandParser; |
ArgParser _commandParser; |
+ |
+ /// Subcommands exposed by this command. |
+ /// |
+ /// If empty, then this command has no subcommands. Otherwise, a subcommand |
+ /// must be specified by the user. In that case, this command's [onRun] will |
+ /// not be called and the subcommand's will. |
final subcommands = <String, PubCommand>{}; |
+ |
+ /// Override this to use offline-only sources instead of hitting the network. |
+ /// |
+ /// This will only be called before the [SystemCache] is created. After that, |
+ /// it has no effect. This only needs to be set in leaf commands. |
bool get isOffline => false; |
+ |
PubCommand() { |
_commandParser = new ArgParser(allowTrailingOptions: allowTrailingOptions); |
+ |
+ // Allow "--help" after a command to get command help. |
commandParser.addFlag( |
'help', |
abbr: 'h', |
negatable: false, |
help: 'Print usage information for this command.'); |
} |
+ |
+ /// Runs this command using a system cache at [cacheDir] with [globalOptions] |
+ /// and [options]. |
Future run(String cacheDir, ArgResults globalOptions, ArgResults options) { |
_globalOptions = globalOptions; |
_commandOptions = options; |
+ |
_cache = new SystemCache.withSources(cacheDir, isOffline: isOffline); |
_globals = new GlobalPackages(_cache); |
+ |
return new Future.sync(onRun); |
} |
+ |
+ /// Override this to perform the specific command. |
+ /// |
+ /// Return a future that completes when the command is done or fails if the |
+ /// command fails. If the command is synchronous, it may return `null`. Only |
+ /// leaf command should override this. |
Future onRun() { |
+ // Leaf commands should override this and non-leaf commands should never |
+ // call it. |
assert(false); |
return null; |
} |
+ |
+ /// Displays usage information for this command. |
+ /// |
+ /// If [description] is omitted, defaults to the command's description. |
void printUsage([String description]) { |
if (description == null) description = this.description; |
log.message('$description\n\n${_getUsage()}'); |
} |
+ |
+ /// Throw a [UsageException] for a usage error of this command with |
+ /// [message]. |
void usageError(String message) { |
throw new UsageException(message, _getUsage()); |
} |
+ |
+ /// Parses a user-supplied integer [intString] named [name]. |
+ /// |
+ /// If the parsing fails, prints a usage message and exits. |
int parseInt(String intString, String name) { |
try { |
return int.parse(intString); |
@@ -130,26 +242,33 @@ abstract class PubCommand { |
usageError('Could not parse $name "$intString".'); |
} |
} |
+ |
+ /// Generates a string of usage information for this command. |
String _getUsage() { |
var buffer = new StringBuffer(); |
buffer.write('Usage: $usage'); |
+ |
var commandUsage = commandParser.getUsage(); |
if (!commandUsage.isEmpty) { |
buffer.writeln(); |
buffer.writeln(commandUsage); |
} |
+ |
if (subcommands.isNotEmpty) { |
buffer.writeln(); |
buffer.write(_listCommands(subcommands)); |
} |
+ |
buffer.writeln(); |
buffer.writeln('Run "pub help" to see global options.'); |
if (docUrl != null) { |
buffer.writeln("See $docUrl for detailed documentation."); |
} |
+ |
return buffer.toString(); |
} |
} |
+ |
_initCommands() { |
var commands = { |
'build': new BuildCommand(), |
@@ -167,15 +286,21 @@ _initCommands() { |
'uploader': new UploaderCommand(), |
'version': new VersionCommand() |
}; |
+ |
for (var command in commands.values.toList()) { |
for (var alias in command.aliases) { |
commands[alias] = command; |
} |
} |
+ |
return commands; |
} |
+ |
+/// Creates the top-level [ArgParser] used to parse the pub command line. |
ArgParser _initArgParser() { |
var argParser = new ArgParser(allowTrailingOptions: true); |
+ |
+ // Add the global options. |
argParser.addFlag( |
'help', |
abbr: 'h', |
@@ -210,13 +335,20 @@ ArgParser _initArgParser() { |
hide: true, |
negatable: true, |
defaultsTo: true); |
+ |
+ // Register the commands. |
PubCommand.mainCommands.forEach((name, command) { |
_registerCommand(name, command, argParser); |
}); |
+ |
return argParser; |
} |
+ |
+/// Registers a [command] with [name] on [parser]. |
void _registerCommand(String name, PubCommand command, ArgParser parser) { |
parser.addCommand(name, command.commandParser); |
+ |
+ // Recursively wire up any subcommands. |
command.subcommands.forEach((name, subcommand) { |
_registerCommand(name, subcommand, command.commandParser); |
}); |