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

Side by Side Diff: lib/src/io.dart

Issue 2184303002: Make pub strong-mode clean. (Closed) Base URL: git@github.com:dart-lang/pub.git@master
Patch Set: Code review changes Created 4 years, 4 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
« no previous file with comments | « lib/src/global_packages.dart ('k') | lib/src/lock_file.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 /// Helper functionality to make working with IO easier. 5 /// Helper functionality to make working with IO easier.
6 import 'dart:async'; 6 import 'dart:async';
7 import 'dart:collection'; 7 import 'dart:collection';
8 import 'dart:convert'; 8 import 'dart:convert';
9 import 'dart:io'; 9 import 'dart:io';
10 10
11 import 'package:async/async.dart';
11 import 'package:path/path.dart' as path; 12 import 'package:path/path.dart' as path;
12 import 'package:pool/pool.dart'; 13 import 'package:pool/pool.dart';
13 import 'package:http/http.dart' show ByteStream; 14 import 'package:http/http.dart' show ByteStream;
14 import 'package:http_multi_server/http_multi_server.dart'; 15 import 'package:http_multi_server/http_multi_server.dart';
15 import 'package:stack_trace/stack_trace.dart'; 16 import 'package:stack_trace/stack_trace.dart';
16 17
17 import 'exit_codes.dart' as exit_codes; 18 import 'exit_codes.dart' as exit_codes;
18 import 'exceptions.dart'; 19 import 'exceptions.dart';
19 import 'error_group.dart'; 20 import 'error_group.dart';
20 import 'log.dart' as log; 21 import 'log.dart' as log;
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after
187 } 188 }
188 189
189 /// Writes [stream] to a new file at path [file]. 190 /// Writes [stream] to a new file at path [file].
190 /// 191 ///
191 /// Replaces any file already at that path. Completes when the file is done 192 /// Replaces any file already at that path. Completes when the file is done
192 /// being written. 193 /// being written.
193 Future<String> createFileFromStream(Stream<List<int>> stream, String file) { 194 Future<String> createFileFromStream(Stream<List<int>> stream, String file) {
194 // TODO(nweiz): remove extra logging when we figure out the windows bot issue. 195 // TODO(nweiz): remove extra logging when we figure out the windows bot issue.
195 log.io("Creating $file from stream."); 196 log.io("Creating $file from stream.");
196 197
197 return _descriptorPool.withResource(() { 198 return _descriptorPool.withResource/*<Future<String>>*/(() async {
198 return stream.pipe(new File(file).openWrite()).then((_) { 199 await stream.pipe(new File(file).openWrite());
199 log.fine("Created $file from stream."); 200 log.fine("Created $file from stream.");
200 return file; 201 return file;
201 });
202 }); 202 });
203 } 203 }
204 204
205 /// Copies all files in [files] to the directory [destination]. 205 /// Copies all files in [files] to the directory [destination].
206 /// 206 ///
207 /// Their locations in [destination] will be determined by their relative 207 /// Their locations in [destination] will be determined by their relative
208 /// location to [baseDir]. Any existing files at those paths will be 208 /// location to [baseDir]. Any existing files at those paths will be
209 /// overwritten. 209 /// overwritten.
210 void copyFiles(Iterable<String> files, String baseDir, String destination) { 210 void copyFiles(Iterable<String> files, String baseDir, String destination) {
211 for (var file in files) { 211 for (var file in files) {
(...skipping 420 matching lines...) Expand 10 before | Expand all | Expand 10 after
632 Future flushThenExit(int status) { 632 Future flushThenExit(int status) {
633 return Future.wait([ 633 return Future.wait([
634 stdout.close(), 634 stdout.close(),
635 stderr.close() 635 stderr.close()
636 ]).then((_) => exit(status)); 636 ]).then((_) => exit(status));
637 } 637 }
638 638
639 /// Returns a [EventSink] that pipes all data to [consumer] and a [Future] that 639 /// Returns a [EventSink] that pipes all data to [consumer] and a [Future] that
640 /// will succeed when [EventSink] is closed or fail with any errors that occur 640 /// will succeed when [EventSink] is closed or fail with any errors that occur
641 /// while writing. 641 /// while writing.
642 Pair<EventSink, Future> consumerToSink(StreamConsumer consumer) { 642 Pair<EventSink/*<T>*/, Future> consumerToSink/*<T>*/(
643 var controller = new StreamController(sync: true); 643 StreamConsumer/*<T>*/ consumer) {
644 var controller = new StreamController/*<T>*/(sync: true);
644 var done = controller.stream.pipe(consumer); 645 var done = controller.stream.pipe(consumer);
645 return new Pair<EventSink, Future>(controller.sink, done); 646 return new Pair(controller.sink, done);
646 } 647 }
647 648
648 // TODO(nweiz): remove this when issue 7786 is fixed. 649 // TODO(nweiz): remove this when issue 7786 is fixed.
649 /// Pipes all data and errors from [stream] into [sink]. 650 /// Pipes all data and errors from [stream] into [sink].
650 /// 651 ///
651 /// When [stream] is done, the returned [Future] is completed and [sink] is 652 /// When [stream] is done, the returned [Future] is completed and [sink] is
652 /// closed if [closeSink] is true. 653 /// closed if [closeSink] is true.
653 /// 654 ///
654 /// When an error occurs on [stream], that error is passed to [sink]. If 655 /// When an error occurs on [stream], that error is passed to [sink]. If
655 /// [cancelOnError] is true, [Future] will be completed successfully and no 656 /// [cancelOnError] is true, [Future] will be completed successfully and no
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
794 795
795 /// Creates a new [PubProcess] wrapping [process]. 796 /// Creates a new [PubProcess] wrapping [process].
796 PubProcess(Process process) 797 PubProcess(Process process)
797 : _process = process { 798 : _process = process {
798 var errorGroup = new ErrorGroup(); 799 var errorGroup = new ErrorGroup();
799 800
800 var pair = consumerToSink(process.stdin); 801 var pair = consumerToSink(process.stdin);
801 _stdin = pair.first; 802 _stdin = pair.first;
802 _stdinClosed = errorGroup.registerFuture(pair.last); 803 _stdinClosed = errorGroup.registerFuture(pair.last);
803 804
804 _stdout = new ByteStream( 805 _stdout = new ByteStream(errorGroup.registerStream(process.stdout));
805 errorGroup.registerStream(process.stdout)); 806 _stderr = new ByteStream(errorGroup.registerStream(process.stderr));
806 _stderr = new ByteStream(
807 errorGroup.registerStream(process.stderr));
808 807
809 var exitCodeCompleter = new Completer(); 808 var exitCodeCompleter = new Completer<int>();
810 _exitCode = errorGroup.registerFuture(exitCodeCompleter.future); 809 _exitCode = errorGroup.registerFuture(exitCodeCompleter.future);
811 _process.exitCode.then((code) => exitCodeCompleter.complete(code)); 810 _process.exitCode.then((code) => exitCodeCompleter.complete(code));
812 } 811 }
813 812
814 /// Sends [signal] to the underlying process. 813 /// Sends [signal] to the underlying process.
815 bool kill([ProcessSignal signal = ProcessSignal.SIGTERM]) => 814 bool kill([ProcessSignal signal = ProcessSignal.SIGTERM]) =>
816 _process.kill(signal); 815 _process.kill(signal);
817 } 816 }
818 817
819 /// Calls [fn] with appropriately modified arguments. 818 /// Calls [fn] with appropriately modified arguments.
820 /// 819 ///
821 /// [fn] should have the same signature as [Process.start], except that the 820 /// [fn] should have the same signature as [Process.start], except that the
822 /// returned value may have any return type. 821 /// returned value may have any return type.
823 _doProcess(Function fn, String executable, List<String> args, 822 _doProcess(Function fn, String executable, List<String> args,
824 {String workingDir, Map<String, String> environment, 823 {String workingDir, Map<String, String> environment,
825 bool runInShell: false}) { 824 bool runInShell: false}) {
826 // TODO(rnystrom): Should dart:io just handle this? 825 // TODO(rnystrom): Should dart:io just handle this?
827 // Spawning a process on Windows will not look for the executable in the 826 // Spawning a process on Windows will not look for the executable in the
828 // system path. So, if executable looks like it needs that (i.e. it doesn't 827 // system path. So, if executable looks like it needs that (i.e. it doesn't
829 // have any path separators in it), then spawn it through a shell. 828 // have any path separators in it), then spawn it through a shell.
830 if ((Platform.operatingSystem == "windows") && 829 if ((Platform.operatingSystem == "windows") &&
831 (executable.indexOf('\\') == -1)) { 830 (executable.indexOf('\\') == -1)) {
832 args = flatten(["/c", executable, args]); 831 args = ["/c", executable]..addAll(args);
833 executable = "cmd"; 832 executable = "cmd";
834 } 833 }
835 834
836 log.process(executable, args, workingDir == null ? '.' : workingDir); 835 log.process(executable, args, workingDir == null ? '.' : workingDir);
837 836
838 return fn(executable, args, 837 return fn(executable, args,
839 workingDirectory: workingDir, 838 workingDirectory: workingDir,
840 environment: environment, 839 environment: environment,
841 runInShell: runInShell); 840 runInShell: runInShell);
842 } 841 }
843 842
844 /// Updates [path]'s modification time. 843 /// Updates [path]'s modification time.
845 void touch(String path) { 844 void touch(String path) {
846 var file = new File(path).openSync(mode: FileMode.APPEND); 845 var file = new File(path).openSync(mode: FileMode.APPEND);
847 var originalLength = file.lengthSync(); 846 var originalLength = file.lengthSync();
848 file.writeByteSync(0); 847 file.writeByteSync(0);
849 file.truncateSync(originalLength); 848 file.truncateSync(originalLength);
850 file.closeSync(); 849 file.closeSync();
851 } 850 }
852 851
853 /// Creates a temporary directory and passes its path to [fn]. 852 /// Creates a temporary directory and passes its path to [fn].
854 /// 853 ///
855 /// Once the [Future] returned by [fn] completes, the temporary directory and 854 /// Once the [Future] returned by [fn] completes, the temporary directory and
856 /// all its contents are deleted. [fn] can also return `null`, in which case 855 /// all its contents are deleted. [fn] can also return `null`, in which case
857 /// the temporary directory is deleted immediately afterwards. 856 /// the temporary directory is deleted immediately afterwards.
858 /// 857 ///
859 /// Returns a future that completes to the value that the future returned from 858 /// Returns a future that completes to the value that the future returned from
860 /// [fn] completes to. 859 /// [fn] completes to.
861 Future withTempDir(Future fn(String path)) { 860 Future/*<T>*/ withTempDir/*<T>*/(Future/*<T>*/ fn(String path)) async {
862 return new Future.sync(() { 861 var tempDir = createSystemTempDir();
863 var tempDir = createSystemTempDir(); 862 try {
864 return new Future.sync(() => fn(tempDir)) 863 return await fn(tempDir);
865 .whenComplete(() => deleteEntry(tempDir)); 864 } finally {
866 }); 865 deleteEntry(tempDir);
866 }
867 } 867 }
868 868
869 /// Binds an [HttpServer] to [host] and [port]. 869 /// Binds an [HttpServer] to [host] and [port].
870 /// 870 ///
871 /// If [host] is "localhost", this will automatically listen on both the IPv4 871 /// If [host] is "localhost", this will automatically listen on both the IPv4
872 /// and IPv6 loopback addresses. 872 /// and IPv6 loopback addresses.
873 Future<HttpServer> bindServer(String host, int port) async { 873 Future<HttpServer> bindServer(String host, int port) async {
874 var server = host == 'localhost' 874 var server = host == 'localhost'
875 ? await HttpMultiServer.loopback(port) 875 ? await HttpMultiServer.loopback(port)
876 : await HttpServer.bind(host, port); 876 : await HttpServer.bind(host, port);
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
988 }); 988 });
989 } 989 }
990 990
991 /// Create a .tar.gz archive from a list of entries. 991 /// Create a .tar.gz archive from a list of entries.
992 /// 992 ///
993 /// Each entry can be a [String], [Directory], or [File] object. The root of 993 /// Each entry can be a [String], [Directory], or [File] object. The root of
994 /// the archive is considered to be [baseDir], which defaults to the current 994 /// the archive is considered to be [baseDir], which defaults to the current
995 /// working directory. 995 /// working directory.
996 /// 996 ///
997 /// Returns a [ByteStream] that emits the contents of the archive. 997 /// Returns a [ByteStream] that emits the contents of the archive.
998 ByteStream createTarGz(List contents, {baseDir}) { 998 ByteStream createTarGz(List contents, {String baseDir}) {
999 return new ByteStream(futureStream(new Future.sync(() async { 999 return new ByteStream(StreamCompleter.fromFuture(new Future.sync(() async {
1000 var buffer = new StringBuffer(); 1000 var buffer = new StringBuffer();
1001 buffer.write('Creating .tag.gz stream containing:\n'); 1001 buffer.write('Creating .tag.gz stream containing:\n');
1002 contents.forEach((file) => buffer.write('$file\n')); 1002 contents.forEach((file) => buffer.write('$file\n'));
1003 log.fine(buffer.toString()); 1003 log.fine(buffer.toString());
1004 1004
1005 if (baseDir == null) baseDir = path.current; 1005 if (baseDir == null) baseDir = path.current;
1006 baseDir = path.absolute(baseDir); 1006 baseDir = path.absolute(baseDir);
1007 contents = contents.map((entry) { 1007 contents = contents.map((entry) {
1008 entry = path.absolute(entry); 1008 entry = path.absolute(entry);
1009 if (!path.isWithin(baseDir, entry)) { 1009 if (!path.isWithin(baseDir, entry)) {
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
1076 1076
1077 // TODO(rnystrom): Remove this and change to returning one string. 1077 // TODO(rnystrom): Remove this and change to returning one string.
1078 static List<String> _toLines(String output) { 1078 static List<String> _toLines(String output) {
1079 var lines = splitLines(output); 1079 var lines = splitLines(output);
1080 if (!lines.isEmpty && lines.last == "") lines.removeLast(); 1080 if (!lines.isEmpty && lines.last == "") lines.removeLast();
1081 return lines; 1081 return lines;
1082 } 1082 }
1083 1083
1084 bool get success => exitCode == exit_codes.SUCCESS; 1084 bool get success => exitCode == exit_codes.SUCCESS;
1085 } 1085 }
OLDNEW
« no previous file with comments | « lib/src/global_packages.dart ('k') | lib/src/lock_file.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698