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 * Helper functionality to make working with IO easier. | 6 * Helper functionality to make working with IO easier. |
7 */ | 7 */ |
8 #library('io'); | 8 #library('io'); |
9 | 9 |
10 #import('dart:io'); | 10 #import('dart:io'); |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
121 return opened.writeString(contents).chain((ignore) { | 121 return opened.writeString(contents).chain((ignore) { |
122 return opened.close().transform((ignore) => file); | 122 return opened.close().transform((ignore) => file); |
123 }); | 123 }); |
124 }); | 124 }); |
125 } | 125 } |
126 | 126 |
127 /** | 127 /** |
128 * Asynchronously deletes [file], which can be a [String] or a [File]. Returns a | 128 * Asynchronously deletes [file], which can be a [String] or a [File]. Returns a |
129 * [Future] that completes when the deletion is done. | 129 * [Future] that completes when the deletion is done. |
130 */ | 130 */ |
131 Future<Directory> deleteFile(file) { | 131 Future<File> deleteFile(file) { |
132 return new File(_getPath(file)).delete(); | 132 return new File(_getPath(file)).delete(); |
133 } | 133 } |
134 | 134 |
135 /** | 135 /** |
136 * Creates a directory [dir]. Returns a [Future] that completes when the | 136 * Creates a directory [dir]. Returns a [Future] that completes when the |
137 * directory is created. | 137 * directory is created. |
138 */ | 138 */ |
139 Future<Directory> createDir(dir) { | 139 Future<Directory> createDir(dir) { |
140 dir = _getDirectory(dir); | 140 dir = _getDirectory(dir); |
141 return dir.create(); | 141 return dir.create(); |
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
302 "HTTP request for $uri failed with status ${response.statusCode}"); | 302 "HTTP request for $uri failed with status ${response.statusCode}"); |
303 } | 303 } |
304 | 304 |
305 pipeInputToInput(response.inputStream, resultStream); | 305 pipeInputToInput(response.inputStream, resultStream); |
306 }; | 306 }; |
307 | 307 |
308 return resultStream; | 308 return resultStream; |
309 } | 309 } |
310 | 310 |
311 /** | 311 /** |
312 * Opens an input stream for a HTTP GET request to [uri], which may be a | |
313 * [String] or [Uri]. Completes with the result of the request as a String. | |
314 */ | |
315 Future<String> httpGetString(uri) { | |
nweiz
2012/09/04 19:29:25
Why is this method different than httpGet? Is it j
Bob Nystrom
2012/09/04 22:14:46
Yup.
| |
316 uri = _getUri(uri); | |
317 | |
318 var completer = new Completer<String>(); | |
319 var client = new HttpClient(); | |
320 var connection = client.getUrl(uri); | |
321 | |
322 connection.onError = (e) { | |
323 // Show a friendly error if the URL couldn't be resolved. | |
324 if ((e is SocketIOException) && (e.osError.errorCode == 8)) { | |
nweiz
2012/09/04 19:29:25
I don't like these unnecessary parens. I don't thi
Bob Nystrom
2012/09/04 22:14:46
Done.
| |
325 e = 'Could not resolve URL "${uri.origin}".'; | |
326 } | |
327 | |
328 completer.completeException(e); | |
329 }; | |
nweiz
2012/09/04 19:29:25
Shouldn't you call client.shutdown here, too?
Bob Nystrom
2012/09/04 22:14:46
Done.
| |
330 | |
331 connection.onResponse = (response) { | |
332 if (response.statusCode >= 400) { | |
333 client.shutdown(); | |
334 completer.completeException( | |
335 new HttpException(response.statusCode, response.reasonPhrase)); | |
336 return; | |
337 } | |
338 | |
339 var resultStream = new ListInputStream(); | |
340 var buffer = <int>[]; | |
341 | |
342 response.inputStream.onClosed = () { | |
343 // Make sure we aren't closing in response to an error in which case | |
344 // we will have already completed with that exception. | |
nweiz
2012/09/04 19:29:25
onClosed and onError should be mutually exclusive.
Bob Nystrom
2012/09/04 22:14:46
They didn't seem to be. Without this check, I get
nweiz
2012/09/04 22:38:18
I believe that's a bug according to https://docs.g
Bob Nystrom
2012/09/04 23:01:20
The pub tests seem to pass without the check, so I
| |
345 if (!completer.future.isComplete) { | |
346 client.shutdown(); | |
347 completer.complete(new String.fromCharCodes(buffer)); | |
348 } | |
349 }; | |
350 | |
351 response.inputStream.onData = () { | |
352 buffer.addAll(response.inputStream.read()); | |
353 }; | |
354 | |
355 response.inputStream.onError = (e) => completer.completeException(e); | |
356 }; | |
357 | |
358 return completer.future; | |
359 } | |
360 | |
361 /** | |
312 * Takes all input from [source] and writes it to [sink]. | 362 * Takes all input from [source] and writes it to [sink]. |
313 * | 363 * |
314 * [onClosed] is called when [source] is closed. | 364 * [onClosed] is called when [source] is closed. |
315 */ | 365 */ |
316 void pipeInputToInput(InputStream source, ListInputStream sink, | 366 void pipeInputToInput(InputStream source, ListInputStream sink, |
317 [void onClosed()]) { | 367 [void onClosed()]) { |
318 source.onClosed = () { | 368 source.onClosed = () { |
319 sink.markEndOfStream(); | 369 sink.markEndOfStream(); |
320 if (onClosed != null) onClosed(); | 370 if (onClosed != null) onClosed(); |
321 }; | 371 }; |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
444 stream.pipe(process.stdin); | 494 stream.pipe(process.stdin); |
445 process.stdout.pipe(stdout, close: false); | 495 process.stdout.pipe(stdout, close: false); |
446 process.stderr.pipe(stderr, close: false); | 496 process.stderr.pipe(stderr, close: false); |
447 | 497 |
448 process.onExit = completer.complete; | 498 process.onExit = completer.complete; |
449 process.onError = completer.completeException; | 499 process.onError = completer.completeException; |
450 return completer.future.transform((exitCode) => exitCode == 0); | 500 return completer.future.transform((exitCode) => exitCode == 0); |
451 } | 501 } |
452 | 502 |
453 /** | 503 /** |
504 * Exception thrown when an HTTP operation fails. | |
505 */ | |
506 class HttpException implements Exception { | |
507 final int statusCode; | |
508 final String reason; | |
509 | |
510 const HttpException(this.statusCode, this.reason); | |
511 } | |
512 | |
513 /** | |
454 * Contains the results of invoking a [Process] and waiting for it to complete. | 514 * Contains the results of invoking a [Process] and waiting for it to complete. |
455 */ | 515 */ |
456 class PubProcessResult { | 516 class PubProcessResult { |
457 final List<String> stdout; | 517 final List<String> stdout; |
458 final List<String> stderr; | 518 final List<String> stderr; |
459 final int exitCode; | 519 final int exitCode; |
460 | 520 |
461 const PubProcessResult(this.stdout, this.stderr, this.exitCode); | 521 const PubProcessResult(this.stdout, this.stderr, this.exitCode); |
462 | 522 |
463 bool get success => exitCode == 0; | 523 bool get success => exitCode == 0; |
(...skipping 20 matching lines...) Expand all Loading... | |
484 return new Directory(entry); | 544 return new Directory(entry); |
485 } | 545 } |
486 | 546 |
487 /** | 547 /** |
488 * Gets a [Uri] for [uri], which can either already be one, or be a [String]. | 548 * Gets a [Uri] for [uri], which can either already be one, or be a [String]. |
489 */ | 549 */ |
490 Uri _getUri(uri) { | 550 Uri _getUri(uri) { |
491 if (uri is Uri) return uri; | 551 if (uri is Uri) return uri; |
492 return new Uri.fromString(uri); | 552 return new Uri.fromString(uri); |
493 } | 553 } |
OLD | NEW |