Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 /** | 5 /** |
| 6 * The main entrypoint for the pub command line application. | 6 * The main entrypoint for the pub command line application. |
| 7 */ | 7 */ |
| 8 #library('pub'); | 8 #library('pub'); |
| 9 | 9 |
| 10 #import('../../lib/args/args.dart'); | 10 #import('../../lib/args/args.dart'); |
| 11 #import('dart:io'); | 11 #import('dart:io'); |
| 12 #import('io.dart'); | 12 #import('io.dart'); |
| 13 #import('command_help.dart'); | |
| 13 #import('command_install.dart'); | 14 #import('command_install.dart'); |
| 14 #import('command_list.dart'); | 15 #import('command_list.dart'); |
| 15 #import('command_update.dart'); | 16 #import('command_update.dart'); |
| 16 #import('command_version.dart'); | 17 #import('command_version.dart'); |
| 17 #import('entrypoint.dart'); | 18 #import('entrypoint.dart'); |
| 18 #import('git_source.dart'); | 19 #import('git_source.dart'); |
| 19 #import('package.dart'); | 20 #import('package.dart'); |
| 20 #import('pubspec.dart'); | 21 #import('pubspec.dart'); |
| 21 #import('repo_source.dart'); | 22 #import('repo_source.dart'); |
| 22 #import('sdk_source.dart'); | 23 #import('sdk_source.dart'); |
| 23 #import('source.dart'); | 24 #import('source.dart'); |
| 24 #import('source_registry.dart'); | 25 #import('source_registry.dart'); |
| 25 #import('system_cache.dart'); | 26 #import('system_cache.dart'); |
| 26 #import('utils.dart'); | 27 #import('utils.dart'); |
| 27 #import('version.dart'); | 28 #import('version.dart'); |
| 28 | 29 |
| 29 Version get pubVersion() => new Version(0, 0, 0); | 30 Version get pubVersion() => new Version(0, 0, 0); |
| 30 | 31 |
| 31 main() { | 32 /** |
| 32 // TODO(rnystrom): In addition to explicit "help" and "version" commands, | 33 * The commands that Pub understands. |
| 33 // should also add special-case support for --help and --version arguments to | 34 */ |
| 34 // be consistent with other Unix apps. | 35 Map<String, PubCommand> get pubCommands() => { |
| 35 var commands = { | 36 'help': new HelpCommand(), |
| 36 'list': new ListCommand(), | 37 'list': new ListCommand(), |
| 37 'install': new InstallCommand(), | 38 'install': new InstallCommand(), |
| 38 'update': new UpdateCommand(), | 39 'update': new UpdateCommand(), |
| 39 'version': new VersionCommand() | 40 'version': new VersionCommand() |
| 40 }; | 41 }; |
| 41 | 42 |
| 43 /** | |
| 44 * The parser for arguments that are global to Pub rather than specific to a | |
| 45 * single command. | |
| 46 */ | |
| 47 ArgParser get pubArgParser() { | |
| 42 var parser = new ArgParser(); | 48 var parser = new ArgParser(); |
| 43 parser.addFlag('help', abbr: 'h', negatable: false, | 49 parser.addFlag('help', abbr: 'h', negatable: false, |
| 44 help: 'Prints this usage information'); | 50 help: 'Prints this usage information'); |
| 45 parser.addFlag('version', negatable: false, | 51 parser.addFlag('version', negatable: false, |
| 46 help: 'Prints the version of Pub'); | 52 help: 'Prints the version of Pub'); |
| 47 parser.addFlag('trace', help: 'Prints a stack trace when an error occurs'); | 53 parser.addFlag('trace', help: 'Prints a stack trace when an error occurs'); |
| 54 return parser; | |
| 55 } | |
| 48 | 56 |
| 57 main() { | |
| 49 var globalOptions; | 58 var globalOptions; |
| 50 try { | 59 try { |
| 51 globalOptions = parser.parse(new Options().arguments); | 60 globalOptions = pubArgParser.parse(new Options().arguments); |
| 52 } catch (ArgFormatException e) { | 61 } catch (ArgFormatException e) { |
| 53 printUsage(parser, commands, description: e.message); | 62 printUsage(description: e.message); |
| 54 return; | 63 return; |
| 55 } | 64 } |
| 56 | 65 |
| 57 if (globalOptions['version']) { | 66 if (globalOptions['version']) { |
| 58 printVersion(); | 67 printVersion(); |
| 59 return; | 68 return; |
| 60 } | 69 } |
| 61 | 70 |
| 62 if (globalOptions['help'] || globalOptions.rest.isEmpty()) { | 71 if (globalOptions['help'] || globalOptions.rest.isEmpty()) { |
| 63 printUsage(parser, commands); | 72 printUsage(); |
| 64 return; | 73 return; |
| 65 } | 74 } |
| 66 | 75 |
| 67 // TODO(nweiz): Have a fallback for this this out automatically once 1145 is | 76 // TODO(nweiz): Have a fallback for this this out automatically once 1145 is |
| 68 // fixed. | 77 // fixed. |
| 69 var sdkDir = Platform.environment['DART_SDK']; | 78 var sdkDir = Platform.environment['DART_SDK']; |
| 70 var cacheDir; | 79 var cacheDir; |
| 71 if (Platform.environment.containsKey('PUB_CACHE')) { | 80 if (Platform.environment.containsKey('PUB_CACHE')) { |
| 72 cacheDir = Platform.environment['PUB_CACHE']; | 81 cacheDir = Platform.environment['PUB_CACHE']; |
| 73 } else { | 82 } else { |
| 74 // TODO(nweiz): Choose a better default for Windows. | 83 // TODO(nweiz): Choose a better default for Windows. |
| 75 cacheDir = '${Platform.environment['HOME']}/.pub-cache'; | 84 cacheDir = '${Platform.environment['HOME']}/.pub-cache'; |
| 76 } | 85 } |
| 77 | 86 |
| 78 var cache = new SystemCache(cacheDir); | 87 var cache = new SystemCache(cacheDir); |
| 79 cache.register(new SdkSource(sdkDir)); | 88 cache.register(new SdkSource(sdkDir)); |
| 80 cache.register(new GitSource()); | 89 cache.register(new GitSource()); |
| 81 cache.register(new RepoSource()); | 90 cache.register(new RepoSource()); |
| 82 // TODO(nweiz): Make 'repo' the default once pub.dartlang.org exists | 91 // TODO(nweiz): Make 'repo' the default once pub.dartlang.org exists |
| 83 cache.sources.setDefault('sdk'); | 92 cache.sources.setDefault('sdk'); |
| 84 | 93 |
| 85 // Select the command. | 94 // Select the command. |
| 86 var command = commands[globalOptions.rest[0]]; | 95 var command = pubCommands[globalOptions.rest[0]]; |
| 87 if (command == null) { | 96 if (command == null) { |
| 88 printError('Unknown command "${globalOptions.rest[0]}".'); | 97 printError('Unknown command "${globalOptions.rest[0]}".'); |
| 89 printError('Run "pub help" to see available commands.'); | 98 printError('Run "pub help" to see available commands.'); |
| 90 exit(64); // See http://www.freebsd.org/cgi/man.cgi?query=sysexits. | 99 exit(64); // See http://www.freebsd.org/cgi/man.cgi?query=sysexits. |
| 91 return; | 100 return; |
| 92 } | 101 } |
| 93 | 102 |
| 94 var commandArgs = | 103 var commandArgs = |
| 95 globalOptions.rest.getRange(1, globalOptions.rest.length - 1); | 104 globalOptions.rest.getRange(1, globalOptions.rest.length - 1); |
| 96 command.run(cache, globalOptions, commandArgs); | 105 command.run(cache, globalOptions, commandArgs); |
| 97 } | 106 } |
| 98 | 107 |
| 99 /** Displays usage information for the app. */ | 108 /** Displays usage information for the app. */ |
| 100 void printUsage(ArgParser parser, Map<String, PubCommand> commands, | 109 void printUsage([String description = 'Pub is a package manager for Dart.']) { |
| 101 [String description = 'Pub is a package manager for Dart.']) { | |
| 102 print(description); | 110 print(description); |
| 103 print(''); | 111 print(''); |
| 104 print('Usage: pub command [arguments]'); | 112 print('Usage: pub command [arguments]'); |
| 105 print(''); | 113 print(''); |
| 106 print('Global options:'); | 114 print('Global options:'); |
| 107 print(parser.getUsage()); | 115 print(pubArgParser.getUsage()); |
| 108 print(''); | 116 print(''); |
| 109 print('The commands are:'); | 117 print('The commands are:'); |
| 110 | 118 |
| 111 // Show the commands sorted. | 119 // Show the commands sorted. |
| 112 // TODO(rnystrom): A sorted map would be nice. | 120 // TODO(rnystrom): A sorted map would be nice. |
| 113 int length = 0; | 121 int length = 0; |
| 114 var names = <String>[]; | 122 var names = <String>[]; |
| 115 for (var command in commands.getKeys()) { | 123 for (var command in pubCommands.getKeys()) { |
| 116 length = Math.max(length, command.length); | 124 length = Math.max(length, command.length); |
| 117 names.add(command); | 125 names.add(command); |
| 118 } | 126 } |
| 119 | 127 |
| 120 names.sort((a, b) => a.compareTo(b)); | 128 names.sort((a, b) => a.compareTo(b)); |
| 121 | 129 |
| 122 for (var name in names) { | 130 for (var name in names) { |
| 123 print(' ${padRight(name, length)} ${commands[name].description}'); | 131 print(' ${padRight(name, length)} ${pubCommands[name].description}'); |
| 124 } | 132 } |
| 125 | 133 |
| 126 print(''); | 134 print(''); |
| 127 print('Use "pub help [command]" for more information about a command.'); | 135 print('Use "pub help [command]" for more information about a command.'); |
| 128 } | 136 } |
| 129 | 137 |
| 130 void printVersion() { | 138 void printVersion() { |
| 131 print('Pub $pubVersion'); | 139 print('Pub $pubVersion'); |
| 132 } | 140 } |
| 133 | 141 |
| 134 class PubCommand { | 142 class PubCommand { |
| 135 SystemCache cache; | 143 SystemCache cache; |
| 144 ArgResults globalOptions; | |
| 145 ArgResults commandOptions; | |
| 136 | 146 |
| 137 Entrypoint entrypoint; | 147 Entrypoint entrypoint; |
| 138 | 148 |
| 149 /** | |
| 150 * A one-line description of this command. | |
| 151 */ | |
| 139 abstract String get description(); | 152 abstract String get description(); |
| 140 | 153 |
| 141 void run(SystemCache cache_, ArgResults globalOptions, | 154 /** |
| 155 * How to invoke this command (e.g. `"pub install [package]"`). | |
| 156 */ | |
| 157 abstract String get usage(); | |
| 158 | |
| 159 /** | |
| 160 * Override this to define command-specific options. The results will be made | |
| 161 * available in [commandOptions]. | |
| 162 */ | |
| 163 ArgParser get commandParser() => new ArgParser(); | |
| 164 | |
| 165 void run(SystemCache cache_, ArgResults globalOptions_, | |
| 142 List<String> commandArgs) { | 166 List<String> commandArgs) { |
| 143 cache = cache_; | 167 cache = cache_; |
| 168 globalOptions = globalOptions_; | |
| 144 | 169 |
| 145 // TODO(rnystrom): Each command should define the arguments it expects and | 170 try { |
| 146 // we can handle them generically here. | 171 commandOptions = commandParser.parse(commandArgs); |
| 172 } catch (ArgFormatException e) { | |
| 173 this.printUsage(description: e.message); | |
| 174 return; | |
| 175 } | |
| 147 | 176 |
| 148 handleError(error, trace) { | 177 handleError(error, trace) { |
| 149 // This is basically the top-level exception handler so that we don't | 178 // This is basically the top-level exception handler so that we don't |
| 150 // spew a stack trace on our users. | 179 // spew a stack trace on our users. |
| 151 // TODO(rnystrom): Add --trace flag so stack traces can be enabled for | 180 // TODO(rnystrom): Add --trace flag so stack traces can be enabled for |
| 152 // debugging. | 181 // debugging. |
| 153 var message = error.toString(); | 182 var message = error.toString(); |
| 154 | 183 |
| 155 // TODO(rnystrom): The default exception implementation class puts | 184 // TODO(rnystrom): The default exception implementation class puts |
| 156 // "Exception:" in the output, so strip that off. | 185 // "Exception:" in the output, so strip that off. |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 183 }); | 212 }); |
| 184 future.handleException((e) => handleError(e, future.stackTrace)); | 213 future.handleException((e) => handleError(e, future.stackTrace)); |
| 185 } | 214 } |
| 186 | 215 |
| 187 /** | 216 /** |
| 188 * Override this to perform the specific command. Return a future that | 217 * Override this to perform the specific command. Return a future that |
| 189 * completes when the command is done or fails if the command fails. If the | 218 * completes when the command is done or fails if the command fails. If the |
| 190 * command is synchronous, it may return `null`. | 219 * command is synchronous, it may return `null`. |
| 191 */ | 220 */ |
| 192 abstract Future onRun(); | 221 abstract Future onRun(); |
| 222 | |
| 223 /** Displays usage information for this command. */ | |
| 224 void printUsage([String description=null]) { | |
|
Jennifer Messerly
2012/07/19 01:00:51
nit: you can do [String description] since the =nu
nweiz
2012/07/19 18:09:16
Done.
| |
| 225 if (description == null) description = this.description; | |
| 226 print(description); | |
| 227 print(''); | |
| 228 print('Usage: $usage'); | |
| 229 | |
| 230 var commandUsage = commandParser.getUsage(); | |
| 231 if (!commandUsage.isEmpty()) { | |
| 232 print(''); | |
| 233 print(commandUsage); | |
| 234 } | |
| 235 } | |
| 193 } | 236 } |
| OLD | NEW |