OLD | NEW |
| (Empty) |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | |
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. | |
4 | |
5 library pub.command_runner; | |
6 | |
7 import 'dart:async'; | |
8 import 'dart:io'; | |
9 | |
10 import 'package:args/args.dart'; | |
11 import 'package:args/command_runner.dart'; | |
12 import 'package:http/http.dart' as http; | |
13 import 'package:stack_trace/stack_trace.dart'; | |
14 | |
15 import 'command/build.dart'; | |
16 import 'command/cache.dart'; | |
17 import 'command/deps.dart'; | |
18 import 'command/downgrade.dart'; | |
19 import 'command/get.dart'; | |
20 import 'command/global.dart'; | |
21 import 'command/lish.dart'; | |
22 import 'command/list_package_dirs.dart'; | |
23 import 'command/run.dart'; | |
24 import 'command/serve.dart'; | |
25 import 'command/upgrade.dart'; | |
26 import 'command/uploader.dart'; | |
27 import 'command/version.dart'; | |
28 import 'exceptions.dart'; | |
29 import 'exit_codes.dart' as exit_codes; | |
30 import 'http.dart'; | |
31 import 'io.dart'; | |
32 import 'log.dart' as log; | |
33 import 'sdk.dart' as sdk; | |
34 import 'solver/version_solver.dart'; | |
35 import 'utils.dart'; | |
36 | |
37 class PubCommandRunner extends CommandRunner { | |
38 String get usageFooter => | |
39 "See http://dartlang.org/tools/pub for detailed " "documentation."; | |
40 | |
41 PubCommandRunner() | |
42 : super("pub", "Pub is a package manager for Dart.") { | |
43 argParser.addFlag('version', negatable: false, help: 'Print pub version.'); | |
44 argParser.addFlag( | |
45 'trace', | |
46 help: 'Print debugging information when an error occurs.'); | |
47 argParser.addOption( | |
48 'verbosity', | |
49 help: 'Control output verbosity.', | |
50 allowed: ['normal', 'io', 'solver', 'all'], | |
51 allowedHelp: { | |
52 'normal': 'Show errors, warnings, and user messages.', | |
53 'io': 'Also show IO operations.', | |
54 'solver': 'Show steps during version resolution.', | |
55 'all': 'Show all output including internal tracing messages.' | |
56 }); | |
57 argParser.addFlag( | |
58 'verbose', | |
59 abbr: 'v', | |
60 negatable: false, | |
61 help: 'Shortcut for "--verbosity=all".'); | |
62 argParser.addFlag( | |
63 'with-prejudice', | |
64 hide: !isAprilFools, | |
65 negatable: false, | |
66 help: 'Execute commands with prejudice.'); | |
67 argParser.addFlag( | |
68 'package-symlinks', | |
69 hide: true, | |
70 negatable: true, | |
71 defaultsTo: true); | |
72 | |
73 addCommand(new BuildCommand()); | |
74 addCommand(new CacheCommand()); | |
75 addCommand(new DepsCommand()); | |
76 addCommand(new DowngradeCommand()); | |
77 addCommand(new GlobalCommand()); | |
78 addCommand(new GetCommand()); | |
79 addCommand(new ListPackageDirsCommand()); | |
80 addCommand(new LishCommand()); | |
81 addCommand(new RunCommand()); | |
82 addCommand(new ServeCommand()); | |
83 addCommand(new UpgradeCommand()); | |
84 addCommand(new UploaderCommand()); | |
85 addCommand(new VersionCommand()); | |
86 } | |
87 | |
88 Future run(List<String> arguments) { | |
89 final completer0 = new Completer(); | |
90 scheduleMicrotask(() { | |
91 try { | |
92 var options; | |
93 join0() { | |
94 new Future.value(runCommand(options)).then((x0) { | |
95 try { | |
96 x0; | |
97 completer0.complete(); | |
98 } catch (e0, s0) { | |
99 completer0.completeError(e0, s0); | |
100 } | |
101 }, onError: completer0.completeError); | |
102 } | |
103 catch0(error, s1) { | |
104 try { | |
105 if (error is UsageException) { | |
106 log.error(error.message); | |
107 new Future.value(flushThenExit(exit_codes.USAGE)).then((x1) { | |
108 try { | |
109 x1; | |
110 join0(); | |
111 } catch (e1, s2) { | |
112 completer0.completeError(e1, s2); | |
113 } | |
114 }, onError: completer0.completeError); | |
115 } else { | |
116 throw error; | |
117 } | |
118 } catch (error, s1) { | |
119 completer0.completeError(error, s1); | |
120 } | |
121 } | |
122 try { | |
123 options = super.parse(arguments); | |
124 join0(); | |
125 } catch (e2, s3) { | |
126 catch0(e2, s3); | |
127 } | |
128 } catch (e, s) { | |
129 completer0.completeError(e, s); | |
130 } | |
131 }); | |
132 return completer0.future; | |
133 } | |
134 | |
135 Future runCommand(ArgResults options) { | |
136 final completer0 = new Completer(); | |
137 scheduleMicrotask(() { | |
138 try { | |
139 log.withPrejudice = options['with-prejudice']; | |
140 join0() { | |
141 join1() { | |
142 break0() { | |
143 log.fine('Pub ${sdk.version}'); | |
144 new Future.value(_validatePlatform()).then((x0) { | |
145 try { | |
146 x0; | |
147 var captureStackChains = | |
148 options['trace'] || | |
149 options['verbose'] || | |
150 options['verbosity'] == 'all'; | |
151 join2() { | |
152 completer0.complete(); | |
153 } | |
154 catch0(error, chain) { | |
155 try { | |
156 log.exception(error, chain); | |
157 join3() { | |
158 new Future.value( | |
159 flushThenExit(_chooseExitCode(error))).then((x1) { | |
160 try { | |
161 x1; | |
162 join2(); | |
163 } catch (e0, s0) { | |
164 completer0.completeError(e0, s0); | |
165 } | |
166 }, onError: completer0.completeError); | |
167 } | |
168 if (options['trace']) { | |
169 log.dumpTranscript(); | |
170 join3(); | |
171 } else { | |
172 join4() { | |
173 join3(); | |
174 } | |
175 if (!isUserFacingException(error)) { | |
176 log.error(""" | |
177 This is an unexpected error. Please run | |
178 | |
179 pub --trace ${options.arguments.map(((arg) { | |
180 return "'$arg'"; | |
181 })).join(' ')} | |
182 | |
183 and include the results in a bug report on http://dartbug.com/new. | |
184 """); | |
185 join4(); | |
186 } else { | |
187 join4(); | |
188 } | |
189 } | |
190 } catch (error, chain) { | |
191 completer0.completeError(error, chain); | |
192 } | |
193 } | |
194 try { | |
195 new Future.value(captureErrors((() { | |
196 return super.runCommand(options); | |
197 }), captureStackChains: captureStackChains)).then((x2) { | |
198 try { | |
199 x2; | |
200 new Future.value( | |
201 flushThenExit(exit_codes.SUCCESS)).then((x3) { | |
202 try { | |
203 x3; | |
204 join2(); | |
205 } catch (e1, s1) { | |
206 catch0(e1, s1); | |
207 } | |
208 }, onError: catch0); | |
209 } catch (e2, s2) { | |
210 catch0(e2, s2); | |
211 } | |
212 }, onError: catch0); | |
213 } catch (e3, s3) { | |
214 catch0(e3, s3); | |
215 } | |
216 } catch (e4, s4) { | |
217 completer0.completeError(e4, s4); | |
218 } | |
219 }, onError: completer0.completeError); | |
220 } | |
221 switch (options['verbosity']) { | |
222 case 'normal': | |
223 log.verbosity = log.Verbosity.NORMAL; | |
224 break0(); | |
225 break; | |
226 case 'io': | |
227 log.verbosity = log.Verbosity.IO; | |
228 break0(); | |
229 break; | |
230 case 'solver': | |
231 log.verbosity = log.Verbosity.SOLVER; | |
232 break0(); | |
233 break; | |
234 case 'all': | |
235 log.verbosity = log.Verbosity.ALL; | |
236 break0(); | |
237 break; | |
238 default: | |
239 join5() { | |
240 break0(); | |
241 } | |
242 if (options['verbose']) { | |
243 log.verbosity = log.Verbosity.ALL; | |
244 join5(); | |
245 } else { | |
246 join5(); | |
247 } | |
248 break; | |
249 } | |
250 } | |
251 if (options['trace']) { | |
252 log.recordTranscript(); | |
253 join1(); | |
254 } else { | |
255 join1(); | |
256 } | |
257 } | |
258 if (options['version']) { | |
259 log.message('Pub ${sdk.version}'); | |
260 completer0.complete(null); | |
261 } else { | |
262 join0(); | |
263 } | |
264 } catch (e, s) { | |
265 completer0.completeError(e, s); | |
266 } | |
267 }); | |
268 return completer0.future; | |
269 } | |
270 | |
271 void printUsage() { | |
272 log.message(usage); | |
273 } | |
274 | |
275 /// Returns the appropriate exit code for [exception], falling back on 1 if no | |
276 /// appropriate exit code could be found. | |
277 int _chooseExitCode(exception) { | |
278 while (exception is WrappedException) exception = exception.innerError; | |
279 | |
280 if (exception is HttpException || | |
281 exception is http.ClientException || | |
282 exception is SocketException || | |
283 exception is PubHttpException || | |
284 exception is DependencyNotFoundException) { | |
285 return exit_codes.UNAVAILABLE; | |
286 } else if (exception is FormatException || exception is DataException) { | |
287 return exit_codes.DATA; | |
288 } else if (exception is UsageException) { | |
289 return exit_codes.USAGE; | |
290 } else { | |
291 return 1; | |
292 } | |
293 } | |
294 | |
295 /// Checks that pub is running on a supported platform. | |
296 /// | |
297 /// If it isn't, it prints an error message and exits. Completes when the | |
298 /// validation is done. | |
299 Future _validatePlatform() { | |
300 final completer0 = new Completer(); | |
301 scheduleMicrotask(() { | |
302 try { | |
303 join0() { | |
304 new Future.value(runProcess('ver', [])).then((x0) { | |
305 try { | |
306 var result = x0; | |
307 join1() { | |
308 completer0.complete(); | |
309 } | |
310 if (result.stdout.join('\n').contains('XP')) { | |
311 log.error('Sorry, but pub is not supported on Windows XP.'); | |
312 new Future.value(flushThenExit(exit_codes.USAGE)).then((x1) { | |
313 try { | |
314 x1; | |
315 join1(); | |
316 } catch (e0, s0) { | |
317 completer0.completeError(e0, s0); | |
318 } | |
319 }, onError: completer0.completeError); | |
320 } else { | |
321 join1(); | |
322 } | |
323 } catch (e1, s1) { | |
324 completer0.completeError(e1, s1); | |
325 } | |
326 }, onError: completer0.completeError); | |
327 } | |
328 if (Platform.operatingSystem != 'windows') { | |
329 completer0.complete(null); | |
330 } else { | |
331 join0(); | |
332 } | |
333 } catch (e, s) { | |
334 completer0.completeError(e, s); | |
335 } | |
336 }); | |
337 return completer0.future; | |
338 } | |
339 } | |
OLD | NEW |