OLD | NEW |
---|---|
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 import 'dart:async'; | 5 import 'dart:async'; |
6 import 'dart:io'; | 6 import 'dart:io'; |
7 | 7 |
8 import 'package:args/args.dart'; | 8 import 'package:args/args.dart'; |
9 import 'package:path/path.dart' as path; | 9 import 'package:path/path.dart' as path; |
10 import 'package:stack_trace/stack_trace.dart'; | |
10 | 11 |
11 import '../lib/src/command.dart'; | 12 import '../lib/src/command.dart'; |
12 import '../lib/src/exit_codes.dart' as exit_codes; | 13 import '../lib/src/exit_codes.dart' as exit_codes; |
14 import '../lib/src/http.dart'; | |
13 import '../lib/src/io.dart'; | 15 import '../lib/src/io.dart'; |
14 import '../lib/src/log.dart' as log; | 16 import '../lib/src/log.dart' as log; |
15 import '../lib/src/sdk.dart' as sdk; | 17 import '../lib/src/sdk.dart' as sdk; |
16 import '../lib/src/utils.dart'; | 18 import '../lib/src/utils.dart'; |
17 | 19 |
18 void main(List<String> arguments) { | 20 void main(List<String> arguments) { |
19 ArgResults options; | 21 ArgResults options; |
20 | 22 |
21 try { | 23 try { |
22 options = PubCommand.pubArgParser.parse(arguments, | 24 options = PubCommand.pubArgParser.parse(arguments, |
23 allowTrailingOptions: true); | 25 allowTrailingOptions: true); |
24 } on FormatException catch (e) { | 26 } on FormatException catch (e) { |
25 log.error(e.message); | 27 log.error(e.message); |
26 log.error('Run "pub help" to see available options.'); | 28 log.error('Run "pub help" to see available options.'); |
27 flushThenExit(exit_codes.USAGE); | 29 flushThenExit(exit_codes.USAGE); |
28 return; | 30 return; |
29 } | 31 } |
30 | 32 |
31 if (options['version']) { | 33 if (options['version']) { |
32 log.message('Pub ${sdk.version}'); | 34 log.message('Pub ${sdk.version}'); |
33 return; | 35 return; |
34 } | 36 } |
35 | 37 |
36 if (options['help']) { | 38 if (options['help']) { |
37 PubCommand.printGlobalUsage(); | 39 PubCommand.printGlobalUsage(); |
38 return; | 40 return; |
39 } | 41 } |
40 | 42 |
41 if (options.command == null) { | |
42 if (options.rest.isEmpty) { | |
43 // No command was chosen. | |
44 PubCommand.printGlobalUsage(); | |
45 } else { | |
46 log.error('Could not find a command named "${options.rest[0]}".'); | |
47 log.error('Run "pub help" to see available commands.'); | |
48 flushThenExit(exit_codes.USAGE); | |
49 } | |
50 return; | |
51 } | |
52 | |
53 if (options['trace']) { | 43 if (options['trace']) { |
54 log.recordTranscript(); | 44 log.recordTranscript(); |
55 } | 45 } |
56 | 46 |
57 switch (options['verbosity']) { | 47 switch (options['verbosity']) { |
58 case 'normal': log.showNormal(); break; | 48 case 'normal': log.showNormal(); break; |
59 case 'io': log.showIO(); break; | 49 case 'io': log.showIO(); break; |
60 case 'solver': log.showSolver(); break; | 50 case 'solver': log.showSolver(); break; |
61 case 'all': log.showAll(); break; | 51 case 'all': log.showAll(); break; |
62 default: | 52 default: |
(...skipping 11 matching lines...) Expand all Loading... | |
74 var cacheDir; | 64 var cacheDir; |
75 if (Platform.environment.containsKey('PUB_CACHE')) { | 65 if (Platform.environment.containsKey('PUB_CACHE')) { |
76 cacheDir = Platform.environment['PUB_CACHE']; | 66 cacheDir = Platform.environment['PUB_CACHE']; |
77 } else if (Platform.operatingSystem == 'windows') { | 67 } else if (Platform.operatingSystem == 'windows') { |
78 var appData = Platform.environment['APPDATA']; | 68 var appData = Platform.environment['APPDATA']; |
79 cacheDir = path.join(appData, 'Pub', 'Cache'); | 69 cacheDir = path.join(appData, 'Pub', 'Cache'); |
80 } else { | 70 } else { |
81 cacheDir = '${Platform.environment['HOME']}/.pub-cache'; | 71 cacheDir = '${Platform.environment['HOME']}/.pub-cache'; |
82 } | 72 } |
83 | 73 |
84 validatePlatform().then((_) { | 74 validatePlatform().then((_) => runPub(cacheDir, options, arguments)); |
85 PubCommand.commands[options.command.name].run(cacheDir, options, arguments); | 75 } |
76 | |
77 /// Runs the appropriate pub command parsed to [options] from [arguments] using | |
nweiz
2014/02/04 01:24:29
I'm not sure what "parsed to [options] from [argum
Bob Nystrom
2014/02/06 00:06:31
Reworded.
| |
78 /// the system cache in [cacheDir]. | |
79 /// | |
80 /// Handles and correctly reports any errors that occur while running. | |
81 void runPub(String cacheDir, ArgResults options, List<String> arguments) { | |
82 handleError(error, Chain chain) { | |
nweiz
2014/02/04 01:24:29
I don't like how this is a separate named function
Bob Nystrom
2014/02/06 00:06:31
Done.
| |
83 // This is basically the top-level exception handler so that we don't | |
84 // spew a stack trace on our users. | |
85 var message; | |
86 | |
87 log.error(getErrorMessage(error)); | |
88 log.fine("Exception type: ${error.runtimeType}"); | |
89 | |
90 if (options['trace'] || !isUserFacingException(error)) { | |
91 log.error(chain.terse); | |
92 } else { | |
93 log.fine(chain.terse); | |
94 } | |
95 | |
96 if (error is ApplicationException && error.innerError != null) { | |
97 var message = "Wrapped exception: ${error.innerError}"; | |
98 if (error.innerTrace != null) message = "$message\n${error.innerTrace}"; | |
99 log.fine(message); | |
100 } | |
101 | |
102 if (options['trace']) { | |
103 log.dumpTranscript(); | |
104 } else if (!isUserFacingException(error)) { | |
105 log.error(""" | |
106 This is an unexpected error. Please run | |
107 | |
108 pub --trace ${arguments.map((arg) => "'$arg'").join(' ')} | |
109 | |
110 and include the results in a bug report on http://dartbug.com/new. | |
111 """); | |
112 } | |
113 | |
114 return flushThenExit(chooseExitCode(error)); | |
115 } | |
116 | |
117 var captureStackChains = | |
118 options['trace'] || | |
119 options['verbose'] || | |
120 options['verbosity'] == 'all'; | |
121 | |
122 captureErrors(() { | |
123 return invokeCommand(cacheDir, options); | |
nweiz
2014/02/04 01:24:29
Nit: =>
Bob Nystrom
2014/02/06 00:06:31
Done.
| |
124 }, captureStackChains: captureStackChains).catchError(handleError) | |
125 .then((_) { | |
126 // Explicitly exit on success to ensure that any dangling dart:io handles | |
127 // don't cause the process to never terminate. | |
128 return flushThenExit(exit_codes.SUCCESS); | |
86 }); | 129 }); |
87 } | 130 } |
88 | 131 |
132 /// Returns the appropriate exit code for [exception], falling back on 1 if no | |
133 /// appropriate exit code could be found. | |
134 int chooseExitCode(exception) { | |
135 if (exception is HttpException || exception is HttpException || | |
136 exception is SocketException || exception is PubHttpException) { | |
137 return exit_codes.UNAVAILABLE; | |
138 } else if (exception is FormatException) { | |
139 return exit_codes.DATA; | |
140 } else if (exception is UsageException) { | |
141 return exit_codes.USAGE; | |
142 } else { | |
143 return 1; | |
144 } | |
145 } | |
146 | |
147 /// Walks the command tree and runs the selected pub command. | |
148 Future invokeCommand(String cacheDir, ArgResults mainOptions) { | |
149 var commands = PubCommand.mainCommands; | |
150 var command; | |
151 var commandString = "pub"; | |
152 var options = mainOptions; | |
153 | |
154 while (commands.isNotEmpty) { | |
155 if (options.command == null) { | |
156 if (options.rest.isEmpty) { | |
157 if (command == null) { | |
158 // No top-level command was chosen. | |
159 PubCommand.printGlobalUsage(); | |
160 return null; | |
nweiz
2014/02/04 01:24:29
I know it works in this case, but I don't like ret
Bob Nystrom
2014/02/06 00:06:31
Done.
| |
161 } | |
162 | |
163 command.usageError('Missing subcommand for "$commandString".'); | |
164 } else { | |
165 if (command == null) { | |
166 PubCommand.commandUsageError(commands, | |
167 'Could not find a command named "${options.rest[0]}".'); | |
168 } | |
169 | |
170 command.usageError( | |
171 'Could not find a subcommand named "${options.rest[0]}" ' | |
172 'for "$commandString".'); | |
nweiz
2014/02/04 01:24:29
Nit: when writing multiline strings like this, I l
Bob Nystrom
2014/02/06 00:06:31
Moved the first line up. I think that makes it con
| |
173 } | |
174 } | |
175 | |
176 // Step into the command. | |
177 options = options.command; | |
178 command = commands[options.name]; | |
179 commands = command.subcommands; | |
180 commandString += " ${options.name}"; | |
181 | |
182 if (options['help']) { | |
183 command.printUsage(); | |
184 return null; | |
185 } | |
186 } | |
187 | |
188 // Make sure there aren't unexpected arguments. | |
189 if (!command.takesArguments && options.rest.isNotEmpty) { | |
190 command.usageError( | |
191 'Command "${options.name}" does not take any arguments.'); | |
192 } | |
193 | |
194 return syncFuture(() { | |
195 return command.run(cacheDir, options); | |
196 }).whenComplete(() { | |
197 command.cache.deleteTempDir(); | |
198 }); | |
199 } | |
200 | |
89 /// Checks that pub is running on a supported platform. If it isn't, it prints | 201 /// Checks that pub is running on a supported platform. If it isn't, it prints |
90 /// an error message and exits. Completes when the validation is done. | 202 /// an error message and exits. Completes when the validation is done. |
91 Future validatePlatform() { | 203 Future validatePlatform() { |
92 return syncFuture(() { | 204 return syncFuture(() { |
93 if (Platform.operatingSystem != 'windows') return null; | 205 if (Platform.operatingSystem != 'windows') return null; |
94 | 206 |
95 return runProcess('ver', []).then((result) { | 207 return runProcess('ver', []).then((result) { |
96 if (result.stdout.join('\n').contains('XP')) { | 208 if (result.stdout.join('\n').contains('XP')) { |
97 log.error('Sorry, but pub is not supported on Windows XP.'); | 209 log.error('Sorry, but pub is not supported on Windows XP.'); |
98 return flushThenExit(exit_codes.USAGE); | 210 return flushThenExit(exit_codes.USAGE); |
99 } | 211 } |
100 }); | 212 }); |
101 }); | 213 }); |
102 } | 214 } |
OLD | NEW |