Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(389)

Side by Side Diff: utils/pub/io.dart

Issue 11830017: Fix ALL the pub tests. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 170 matching lines...) Expand 10 before | Expand all | Expand 10 after
181 log.fine("Ensuring directory $path exists."); 181 log.fine("Ensuring directory $path exists.");
182 if (path == '.') return new Future.immediate(new Directory('.')); 182 if (path == '.') return new Future.immediate(new Directory('.'));
183 183
184 return dirExists(path).then((exists) { 184 return dirExists(path).then((exists) {
185 if (exists) { 185 if (exists) {
186 log.fine("Directory $path already exists."); 186 log.fine("Directory $path already exists.");
187 return new Future.immediate(new Directory(path)); 187 return new Future.immediate(new Directory(path));
188 } 188 }
189 189
190 return ensureDir(dirname(path)).then((_) { 190 return ensureDir(dirname(path)).then((_) {
191 return createDir(path) 191 return createDir(path).catchError((asyncError) {
192 .catchError((error) { 192 var error = getRealError(asyncError);
193 if (error is! DirectoryIOException) return false; 193 if (error is! DirectoryIOException) throw asyncError;
194 // Error 17 means the directory already exists (or 183 on Windows). 194 // Error 17 means the directory already exists (or 183 on Windows).
195 if (error.osError.errorCode != 17 && 195 if (error.osError.errorCode != 17 &&
196 error.osError.errorCode != 183) { 196 error.osError.errorCode != 183) {
197 log.fine("Got 'already exists' error when creating directory."); 197 log.fine("Got 'already exists' error when creating directory.");
Bob Nystrom 2013/01/09 16:49:23 This log is wrong. This "if" is for when the error
198 return false; 198 throw asyncError;
199 } 199 }
200 200
201 return _getDirectory(path); 201 return _getDirectory(path);
202 }); 202 });
203 }); 203 });
204 }); 204 });
205 } 205 }
206 206
207 /// Creates a temp directory whose name will be based on [dir] with a unique 207 /// Creates a temp directory whose name will be based on [dir] with a unique
208 /// suffix appended to it. If [dir] is not provided, a temp directory will be 208 /// suffix appended to it. If [dir] is not provided, a temp directory will be
209 /// created in a platform-dependent temporary location. Returns a [Future] that 209 /// created in a platform-dependent temporary location. Returns a [Future] that
210 /// completes when the directory is created. 210 /// completes when the directory is created.
211 Future<Directory> createTempDir([dir = '']) { 211 Future<Directory> createTempDir([dir = '']) {
212 dir = _getDirectory(dir); 212 dir = _getDirectory(dir);
(...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after
555 } 555 }
556 556
557 var completer = new Completer<String>(); 557 var completer = new Completer<String>();
558 var buffer = new StringBuffer(); 558 var buffer = new StringBuffer();
559 stream.onClosed = () => completer.complete(buffer.toString()); 559 stream.onClosed = () => completer.complete(buffer.toString());
560 stream.onData = () => buffer.add(stream.read()); 560 stream.onData = () => buffer.add(stream.read());
561 stream.onError = (e) => completer.completeError(e, stackTrace); 561 stream.onError = (e) => completer.completeError(e, stackTrace);
562 return completer.future; 562 return completer.future;
563 } 563 }
564 564
565 /// Wrap an InputStream in a ListInputStream. This eagerly drains the [source] 565 /// Wraps [stream] in a single-subscription [ByteStream] that emits the same
566 /// input stream. This is useful for spawned processes which will not exit until 566 /// data.
567 /// their output streams have been drained. 567 Stream<List<int>> wrapInputStream(InputStream stream) {
Bob Nystrom 2013/01/09 16:49:23 Type the return as a ByteStream? Also, can we hav
568 /// TODO(rnystrom): We should use this logic anywhere we spawn a process. 568 if (stream.closed) return new StreamController.singleSubscription()..close();
Bob Nystrom 2013/01/09 16:49:23 The duplicate constructor is a bit gross. How abou
569 InputStream wrapInputStream(InputStream source) { 569
570 var sink = new ListInputStream(); 570 var controller = new StreamController.singleSubscription();
571 pipeInputToInput(source, sink); 571 stream.onClosed = controller.close;
572 return sink; 572 stream.onData = () => controller.add(stream.read());
573 stream.onError = (e) => controller.signalError(new AsyncError(e));
574 return controller.stream;
575 }
576
577 // TODO(nweiz): remove this ASAP
Bob Nystrom 2013/01/09 16:49:23 Tracking bug?
578 /// Wraps [stream] in an [InputStream].
579 InputStream wrapByteStream(Stream<List<int>> stream) {
Bob Nystrom 2013/01/09 16:49:23 Maybe these method names should be more explicit.
580 var inputStream = new ListInputStream();
581 stream.listen((chunk) => inputStream.write(chunk),
582 onDone: inputStream.markEndOfStream);
583 return inputStream;
584 }
585
586 /// Wraps [stream] in a [StreamConsumer] so that [Stream]s can by piped into it
587 /// using [Stream.pipe].
588 StreamConsumer<List<int>, dynamic> wrapOutputStream(OutputStream stream) =>
Bob Nystrom 2013/01/09 16:49:23 "toStreamConsumer" ?
589 new _OutputStreamConsumer(stream);
590
591 /// A [StreamConsumer] that pipes data into an [OutputStream].
592 class _OutputStreamConsumer implements StreamConsumer<List<int>, dynamic> {
593 final OutputStream _outputStream;
594
595 _OutputStreamConsumer(this._outputStream)
596 : super();
Bob Nystrom 2013/01/09 16:49:23 Unnecessary, especially since you aren't extending
597
598 Future consume(Stream<List<int>> stream) {
599 // TODO(nweiz): we have to manually keep track of whether or not the
600 // completer has completed since the output stream could signal an error
601 // after close() has been called but before it has shut down internally. See
602 // the following TODO.
603 var completed = false;
604 var completer = new Completer();
605 stream.listen((data) => _outputStream.write(data), onDone: () {
606 _outputStream.close();
607 // TODO(nweiz): wait until _outputStream.onClosed is called once issue
608 // 7761 is fixed.
609 if (!completed) completer.complete(null);
610 completed = true;
611 });
612
613 _outputStream.onError = (e) {
614 if (!completed) completer.completeError(e);
Bob Nystrom 2013/01/09 16:49:23 Want to do that little hack to grab a stack trace
615 completed = true;
616 };
617
618 return completer.future;
619 }
573 } 620 }
574 621
575 /// Spawns and runs the process located at [executable], passing in [args]. 622 /// Spawns and runs the process located at [executable], passing in [args].
576 /// Returns a [Future] that will complete with the results of the process after 623 /// Returns a [Future] that will complete with the results of the process after
577 /// it has ended. 624 /// it has ended.
578 /// 625 ///
579 /// The spawned process will inherit its parent's environment variables. If 626 /// The spawned process will inherit its parent's environment variables. If
580 /// [environment] is provided, that will be used to augment (not replace) the 627 /// [environment] is provided, that will be used to augment (not replace) the
581 /// the inherited variables. 628 /// the inherited variables.
582 Future<PubProcessResult> runProcess(String executable, List<String> args, 629 Future<PubProcessResult> runProcess(String executable, List<String> args,
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
618 final InputStream stdout; 665 final InputStream stdout;
619 666
620 OutputStream get stdin => _process.stdin; 667 OutputStream get stdin => _process.stdin;
621 668
622 void set onExit(void callback(int exitCode)) { 669 void set onExit(void callback(int exitCode)) {
623 _process.onExit = callback; 670 _process.onExit = callback;
624 } 671 }
625 672
626 _WrappedProcess(Process process) 673 _WrappedProcess(Process process)
627 : _process = process, 674 : _process = process,
628 stderr = wrapInputStream(process.stderr), 675 stderr = _wrapInputStream(process.stderr),
629 stdout = wrapInputStream(process.stdout); 676 stdout = _wrapInputStream(process.stdout);
630 677
631 bool kill([ProcessSignal signal = ProcessSignal.SIGTERM]) => 678 bool kill([ProcessSignal signal = ProcessSignal.SIGTERM]) =>
632 _process.kill(signal); 679 _process.kill(signal);
680
681 /// Wrap an InputStream in a ListInputStream. This eagerly drains the [source]
682 /// input stream. This is useful for spawned processes which will not exit unt il
Bob Nystrom 2013/01/09 16:49:23 Long line.
683 /// their output streams have been drained.
684 /// TODO(rnystrom): We should use this logic anywhere we spawn a process.
685 static InputStream _wrapInputStream(InputStream source) {
686 var sink = new ListInputStream();
687 pipeInputToInput(source, sink);
688 return sink;
689 }
633 } 690 }
634 691
635 /// Calls [fn] with appropriately modified arguments. [fn] should have the same 692 /// Calls [fn] with appropriately modified arguments. [fn] should have the same
636 /// signature as [Process.start], except that the returned [Future] may have a 693 /// signature as [Process.start], except that the returned [Future] may have a
637 /// type other than [Process]. 694 /// type other than [Process].
638 Future _doProcess(Function fn, String executable, List<String> args, workingDir, 695 Future _doProcess(Function fn, String executable, List<String> args, workingDir,
639 Map<String, String> environment) { 696 Map<String, String> environment) {
640 // TODO(rnystrom): Should dart:io just handle this? 697 // TODO(rnystrom): Should dart:io just handle this?
641 // Spawning a process on Windows will not look for the executable in the 698 // Spawning a process on Windows will not look for the executable in the
642 // system path. So, if executable looks like it needs that (i.e. it doesn't 699 // system path. So, if executable looks like it needs that (i.e. it doesn't
(...skipping 28 matching lines...) Expand all
671 /// Note that timing out will not cancel the asynchronous operation behind 728 /// Note that timing out will not cancel the asynchronous operation behind
672 /// [input]. 729 /// [input].
673 Future timeout(Future input, int milliseconds, String description) { 730 Future timeout(Future input, int milliseconds, String description) {
674 bool completed = false; 731 bool completed = false;
675 var completer = new Completer(); 732 var completer = new Completer();
676 var timer = new Timer(milliseconds, (_) { 733 var timer = new Timer(milliseconds, (_) {
677 completed = true; 734 completed = true;
678 completer.completeError(new TimeoutException( 735 completer.completeError(new TimeoutException(
679 'Timed out while $description.')); 736 'Timed out while $description.'));
680 }); 737 });
681 input 738 input.then((value) {
682 .then((value) { 739 if (completed) return;
683 if (completed) return; 740 timer.cancel();
684 timer.cancel(); 741 completer.complete(value);
685 completer.complete(value); 742 }).catchError((e) {
686 }) 743 if (completed) return;
687 .catchError((e) { 744 timer.cancel();
688 if (completed) return; 745 completer.completeError(e.error, e.stackTrace);
689 timer.cancel(); 746 });
690 completer.completeError(e.error, e.stackTrace);
691 });
692 return completer.future; 747 return completer.future;
693 } 748 }
694 749
695 /// Creates a temporary directory and passes its path to [fn]. Once the [Future] 750 /// Creates a temporary directory and passes its path to [fn]. Once the [Future]
696 /// returned by [fn] completes, the temporary directory and all its contents 751 /// returned by [fn] completes, the temporary directory and all its contents
697 /// will be deleted. 752 /// will be deleted.
698 Future withTempDir(Future fn(String path)) { 753 Future withTempDir(Future fn(String path)) {
699 var tempDir; 754 var tempDir;
700 var future = createTempDir().then((dir) { 755 return asyncWhenComplete(createTempDir().then((dir) {
701 tempDir = dir; 756 tempDir = dir;
702 return fn(tempDir.path); 757 return fn(tempDir.path);
758 }), () {
759 log.fine('Cleaning up temp directory ${tempDir.path}.');
760 return deleteDir(tempDir);
703 }); 761 });
704 future.catchError((_) {}).then((_) {
705 log.fine('Cleaning up temp directory ${tempDir.path}.');
706 deleteDir(tempDir);
707 });
708 return future;
709 } 762 }
710 763
711 /// Tests whether or not the git command-line app is available for use. 764 /// Tests whether or not the git command-line app is available for use.
712 Future<bool> get isGitInstalled { 765 Future<bool> get isGitInstalled {
713 if (_isGitInstalledCache != null) { 766 if (_isGitInstalledCache != null) {
714 // TODO(rnystrom): The sleep is to pump the message queue. Can use 767 // TODO(rnystrom): The sleep is to pump the message queue. Can use
715 // Future.immediate() when #3356 is fixed. 768 // Future.immediate() when #3356 is fixed.
716 return sleep(0).then((_) => _isGitInstalledCache); 769 return sleep(0).then((_) => _isGitInstalledCache);
717 } 770 }
718 771
(...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after
967 Directory _getDirectory(entry) { 1020 Directory _getDirectory(entry) {
968 if (entry is Directory) return entry; 1021 if (entry is Directory) return entry;
969 return new Directory(entry); 1022 return new Directory(entry);
970 } 1023 }
971 1024
972 /// Gets a [Uri] for [uri], which can either already be one, or be a [String]. 1025 /// Gets a [Uri] for [uri], which can either already be one, or be a [String].
973 Uri _getUri(uri) { 1026 Uri _getUri(uri) {
974 if (uri is Uri) return uri; 1027 if (uri is Uri) return uri;
975 return new Uri.fromString(uri); 1028 return new Uri.fromString(uri);
976 } 1029 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698