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 /// Helper functionality to make working with IO easier. | 5 /// Helper functionality to make working with IO easier. |
6 library io; | 6 library io; |
7 | 7 |
8 import 'dart:async'; | 8 import 'dart:async'; |
9 import 'dart:io'; | 9 import 'dart:io'; |
10 import 'dart:isolate'; | 10 import 'dart:isolate'; |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
124 | 124 |
125 /// Writes [stream] to a new file at [path], which may be a [String] or a | 125 /// Writes [stream] to a new file at [path], which may be a [String] or a |
126 /// [File]. Will replace any file already at that path. Completes when the file | 126 /// [File]. Will replace any file already at that path. Completes when the file |
127 /// is done being written. | 127 /// is done being written. |
128 Future<File> createFileFromStream(InputStream stream, path) { | 128 Future<File> createFileFromStream(InputStream stream, path) { |
129 path = _getPath(path); | 129 path = _getPath(path); |
130 | 130 |
131 log.io("Creating $path from stream."); | 131 log.io("Creating $path from stream."); |
132 | 132 |
133 var completer = new Completer<File>(); | 133 var completer = new Completer<File>(); |
| 134 var completed = false; |
134 var file = new File(path); | 135 var file = new File(path); |
135 var outputStream = file.openOutputStream(); | 136 var outputStream = file.openOutputStream(); |
136 stream.pipe(outputStream); | 137 stream.pipe(outputStream); |
137 | 138 |
138 outputStream.onClosed = () { | 139 outputStream.onClosed = () { |
139 log.fine("Created $path from stream."); | 140 log.fine("Created $path from stream."); |
| 141 completed = true; |
140 completer.complete(file); | 142 completer.complete(file); |
141 }; | 143 }; |
142 | 144 |
143 // TODO(nweiz): remove this when issue 4061 is fixed. | 145 // TODO(nweiz): remove this when issue 4061 is fixed. |
144 var stackTrace; | 146 var stackTrace; |
145 try { | 147 try { |
146 throw ""; | 148 throw ""; |
147 } catch (_, localStackTrace) { | 149 } catch (_, localStackTrace) { |
148 stackTrace = localStackTrace; | 150 stackTrace = localStackTrace; |
149 } | 151 } |
150 | 152 |
151 completeError(error) { | 153 completeError(error) { |
152 if (!completer.isComplete) { | 154 if (!completed) { |
153 completer.completeException(error, stackTrace); | 155 completed = true; |
| 156 completer.completeError(error, stackTrace); |
154 } else { | 157 } else { |
155 log.fine("Got error after stream was closed: $error"); | 158 log.fine("Got error after stream was closed: $error"); |
156 } | 159 } |
157 } | 160 } |
158 | 161 |
159 stream.onError = completeError; | 162 stream.onError = completeError; |
160 outputStream.onError = completeError; | 163 outputStream.onError = completeError; |
161 | 164 |
162 return completer.future; | 165 return completer.future; |
163 } | 166 } |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
256 | 259 |
257 // TODO(nweiz): remove this when issue 4061 is fixed. | 260 // TODO(nweiz): remove this when issue 4061 is fixed. |
258 var stackTrace; | 261 var stackTrace; |
259 try { | 262 try { |
260 throw ""; | 263 throw ""; |
261 } catch (_, localStackTrace) { | 264 } catch (_, localStackTrace) { |
262 stackTrace = localStackTrace; | 265 stackTrace = localStackTrace; |
263 } | 266 } |
264 | 267 |
265 var children = []; | 268 var children = []; |
266 lister.onError = (error) => completer.completeException(error, stackTrace); | 269 lister.onError = (error) => completer.completeError(error, stackTrace); |
267 lister.onDir = (file) { | 270 lister.onDir = (file) { |
268 if (!includeHiddenFiles && basename(file).startsWith('.')) return; | 271 if (!includeHiddenFiles && basename(file).startsWith('.')) return; |
269 file = join(dir, basename(file)); | 272 file = join(dir, basename(file)); |
270 contents.add(file); | 273 contents.add(file); |
271 | 274 |
272 // TODO(nweiz): don't manually recurse once issue 7358 is fixed. Note that | 275 // TODO(nweiz): don't manually recurse once issue 7358 is fixed. Note that |
273 // once we remove the manual recursion, we'll need to explicitly filter | 276 // once we remove the manual recursion, we'll need to explicitly filter |
274 // out files in hidden directories. | 277 // out files in hidden directories. |
275 if (recursive) { | 278 if (recursive) { |
276 children.add(doList(new Directory(file), listedDirectories)); | 279 children.add(doList(new Directory(file), listedDirectories)); |
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
480 | 483 |
481 stream.onLine = () { | 484 stream.onLine = () { |
482 removeCallbacks(); | 485 removeCallbacks(); |
483 var line = stream.readLine(); | 486 var line = stream.readLine(); |
484 log.io('Read line: $line'); | 487 log.io('Read line: $line'); |
485 completer.complete(line); | 488 completer.complete(line); |
486 }; | 489 }; |
487 | 490 |
488 stream.onError = (e) { | 491 stream.onError = (e) { |
489 removeCallbacks(); | 492 removeCallbacks(); |
490 completer.completeException(e, stackTrace); | 493 completer.completeError(e, stackTrace); |
491 }; | 494 }; |
492 | 495 |
493 return completer.future; | 496 return completer.future; |
494 } | 497 } |
495 | 498 |
496 /// Takes all input from [source] and writes it to [sink]. | 499 /// Takes all input from [source] and writes it to [sink]. |
497 /// | 500 /// |
498 /// Returns a future that completes when [source] is closed. | 501 /// Returns a future that completes when [source] is closed. |
499 Future pipeInputToInput(InputStream source, ListInputStream sink) { | 502 Future pipeInputToInput(InputStream source, ListInputStream sink) { |
500 var completer = new Completer(); | 503 var completer = new Completer(); |
(...skipping 27 matching lines...) Expand all Loading... |
528 try { | 531 try { |
529 throw ""; | 532 throw ""; |
530 } catch (_, localStackTrace) { | 533 } catch (_, localStackTrace) { |
531 stackTrace = localStackTrace; | 534 stackTrace = localStackTrace; |
532 } | 535 } |
533 | 536 |
534 var completer = new Completer<List<int>>(); | 537 var completer = new Completer<List<int>>(); |
535 var buffer = <int>[]; | 538 var buffer = <int>[]; |
536 stream.onClosed = () => completer.complete(buffer); | 539 stream.onClosed = () => completer.complete(buffer); |
537 stream.onData = () => buffer.addAll(stream.read()); | 540 stream.onData = () => buffer.addAll(stream.read()); |
538 stream.onError = (e) => completer.completeException(e, stackTrace); | 541 stream.onError = (e) => completer.completeError(e, stackTrace); |
539 return completer.future; | 542 return completer.future; |
540 } | 543 } |
541 | 544 |
542 /// Buffers all input from a StringInputStream and returns it as a future. | 545 /// Buffers all input from a StringInputStream and returns it as a future. |
543 Future<String> consumeStringInputStream(StringInputStream stream) { | 546 Future<String> consumeStringInputStream(StringInputStream stream) { |
544 if (stream.closed) return new Future.immediate(''); | 547 if (stream.closed) return new Future.immediate(''); |
545 | 548 |
546 // TODO(nweiz): remove this when issue 4061 is fixed. | 549 // TODO(nweiz): remove this when issue 4061 is fixed. |
547 var stackTrace; | 550 var stackTrace; |
548 try { | 551 try { |
549 throw ""; | 552 throw ""; |
550 } catch (_, localStackTrace) { | 553 } catch (_, localStackTrace) { |
551 stackTrace = localStackTrace; | 554 stackTrace = localStackTrace; |
552 } | 555 } |
553 | 556 |
554 var completer = new Completer<String>(); | 557 var completer = new Completer<String>(); |
555 var buffer = new StringBuffer(); | 558 var buffer = new StringBuffer(); |
556 stream.onClosed = () => completer.complete(buffer.toString()); | 559 stream.onClosed = () => completer.complete(buffer.toString()); |
557 stream.onData = () => buffer.add(stream.read()); | 560 stream.onData = () => buffer.add(stream.read()); |
558 stream.onError = (e) => completer.completeException(e, stackTrace); | 561 stream.onError = (e) => completer.completeError(e, stackTrace); |
559 return completer.future; | 562 return completer.future; |
560 } | 563 } |
561 | 564 |
562 /// Wrap an InputStream in a ListInputStream. This eagerly drains the [source] | 565 /// Wrap an InputStream in a ListInputStream. This eagerly drains the [source] |
563 /// input stream. This is useful for spawned processes which will not exit until | 566 /// input stream. This is useful for spawned processes which will not exit until |
564 /// their output streams have been drained. | 567 /// their output streams have been drained. |
565 /// TODO(rnystrom): We should use this logic anywhere we spawn a process. | 568 /// TODO(rnystrom): We should use this logic anywhere we spawn a process. |
566 InputStream wrapInputStream(InputStream source) { | 569 InputStream wrapInputStream(InputStream source) { |
567 var sink = new ListInputStream(); | 570 var sink = new ListInputStream(); |
568 pipeInputToInput(source, sink); | 571 pipeInputToInput(source, sink); |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
664 /// However, if [milliseconds] pass before [input] has completed, it completes | 667 /// However, if [milliseconds] pass before [input] has completed, it completes |
665 /// with a [TimeoutException] with [description] (which should be a fragment | 668 /// with a [TimeoutException] with [description] (which should be a fragment |
666 /// describing the action that timed out). | 669 /// describing the action that timed out). |
667 /// | 670 /// |
668 /// Note that timing out will not cancel the asynchronous operation behind | 671 /// Note that timing out will not cancel the asynchronous operation behind |
669 /// [input]. | 672 /// [input]. |
670 Future timeout(Future input, int milliseconds, String description) { | 673 Future timeout(Future input, int milliseconds, String description) { |
671 bool completed = false; | 674 bool completed = false; |
672 var completer = new Completer(); | 675 var completer = new Completer(); |
673 var timer = new Timer(milliseconds, (_) { | 676 var timer = new Timer(milliseconds, (_) { |
674 completer = true; | 677 completed = true; |
675 completer.completeError(new TimeoutException( | 678 completer.completeError(new TimeoutException( |
676 'Timed out while $description.')); | 679 'Timed out while $description.')); |
677 }); | 680 }); |
678 input | 681 input |
679 .then((value) { | 682 .then((value) { |
680 if (completed) return; | 683 if (completed) return; |
681 timer.cancel(); | 684 timer.cancel(); |
682 completer.complete(value); | 685 completer.complete(value); |
683 }) | 686 }) |
684 .catchError((e) { | 687 .catchError((e) { |
(...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
964 Directory _getDirectory(entry) { | 967 Directory _getDirectory(entry) { |
965 if (entry is Directory) return entry; | 968 if (entry is Directory) return entry; |
966 return new Directory(entry); | 969 return new Directory(entry); |
967 } | 970 } |
968 | 971 |
969 /// Gets a [Uri] for [uri], which can either already be one, or be a [String]. | 972 /// Gets a [Uri] for [uri], which can either already be one, or be a [String]. |
970 Uri _getUri(uri) { | 973 Uri _getUri(uri) { |
971 if (uri is Uri) return uri; | 974 if (uri is Uri) return uri; |
972 return new Uri.fromString(uri); | 975 return new Uri.fromString(uri); |
973 } | 976 } |
OLD | NEW |