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

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

Issue 14266003: Use the dart:io IOSink API in pub. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 8 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
« no previous file with comments | « no previous file | utils/pub/log.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 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 261 matching lines...) Expand 10 before | Expand all | Expand 10 after
272 var utilDir = path.dirname(scriptPath); 272 var utilDir = path.dirname(scriptPath);
273 while (path.basename(utilDir) != 'utils' && 273 while (path.basename(utilDir) != 'utils' &&
274 path.basename(utilDir) != 'util') { 274 path.basename(utilDir) != 'util') {
275 if (path.basename(utilDir) == '') throw 'Could not find path to pub.'; 275 if (path.basename(utilDir) == '') throw 'Could not find path to pub.';
276 utilDir = path.dirname(utilDir); 276 utilDir = path.dirname(utilDir);
277 } 277 }
278 278
279 return path.normalize(path.join(utilDir, 'pub', target)); 279 return path.normalize(path.join(utilDir, 'pub', target));
280 } 280 }
281 281
282 // TODO(nweiz): add a ByteSink wrapper to make writing strings to stdout/stderr
283 // nicer.
284
285 /// A sink that writes to standard output. Errors piped to this stream will be
286 /// surfaced to the top-level error handler.
287 // TODO: Unrequired wrapper, stdout is now an EventSink<List<int>>.
288 final EventSink<List<int>> stdoutSink = _wrapStdio(stdout, "stdout");
289
290 /// A sink that writes to standard error. Errors piped to this stream will be
291 /// surfaced to the top-level error handler.
292 // TODO: Unrequired wrapper, stdout is now an EventSink<List<int>>.
293 final EventSink<List<int>> stderrSink = _wrapStdio(stderr, "stderr");
294
295 /// Wrap the standard output or error [stream] in a [EventSink]. Any errors are
296 /// logged, and then the program is terminated. [name] is used for debugging.
297 EventSink<List<int>> _wrapStdio(IOSink sink, String name) {
298 var pair = consumerToSink(sink);
299 pair.last.catchError((e) {
300 // This log may or may not work, depending on how the stream failed. Not
301 // much we can do about that.
302 log.error("Error writing to $name", e);
303 exit(exit_codes.IO);
304 });
305 return pair.first;
306 }
307
308 /// A line-by-line stream of standard input. 282 /// A line-by-line stream of standard input.
309 final Stream<String> stdinLines = streamToLines( 283 final Stream<String> stdinLines = streamToLines(
310 new ByteStream(stdin).toStringStream()); 284 new ByteStream(stdin).toStringStream());
311 285
312 /// Displays a message and reads a yes/no confirmation from the user. Returns 286 /// Displays a message and reads a yes/no confirmation from the user. Returns
313 /// a [Future] that completes to `true` if the user confirms or `false` if they 287 /// a [Future] that completes to `true` if the user confirms or `false` if they
314 /// do not. 288 /// do not.
315 /// 289 ///
316 /// This will automatically append " (y/n)?" to the message, so [message] 290 /// This will automatically append " (y/n)?" to the message, so [message]
317 /// should just be a fragment like, "Are you sure you want to proceed". 291 /// should just be a fragment like, "Are you sure you want to proceed".
318 Future<bool> confirm(String message) { 292 Future<bool> confirm(String message) {
319 log.fine('Showing confirm message: $message'); 293 log.fine('Showing confirm message: $message');
320 stdoutSink.add("$message (y/n)? ".codeUnits); 294 stdout.write("$message (y/n)? ");
321 return streamFirst(stdinLines) 295 return streamFirst(stdinLines)
322 .then((line) => new RegExp(r"^[yY]").hasMatch(line)); 296 .then((line) => new RegExp(r"^[yY]").hasMatch(line));
323 } 297 }
324 298
325 /// Reads and discards all output from [stream]. Returns a [Future] that 299 /// Reads and discards all output from [stream]. Returns a [Future] that
326 /// completes when the stream is closed. 300 /// completes when the stream is closed.
327 Future drainStream(Stream stream) { 301 Future drainStream(Stream stream) {
328 return stream.fold(null, (x, y) {}); 302 return stream.fold(null, (x, y) {});
329 } 303 }
330 304
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after
564 538
565 if (Platform.operatingSystem == "windows") { 539 if (Platform.operatingSystem == "windows") {
566 return _extractTarGzWindows(stream, destination); 540 return _extractTarGzWindows(stream, destination);
567 } 541 }
568 542
569 return startProcess("tar", 543 return startProcess("tar",
570 ["--extract", "--gunzip", "--directory", destination]).then((process) { 544 ["--extract", "--gunzip", "--directory", destination]).then((process) {
571 // Ignore errors on process.std{out,err}. They'll be passed to 545 // Ignore errors on process.std{out,err}. They'll be passed to
572 // process.exitCode, and we don't want them being top-levelled by 546 // process.exitCode, and we don't want them being top-levelled by
573 // std{out,err}Sink. 547 // std{out,err}Sink.
574 store(process.stdout.handleError((_) {}), stdoutSink, closeSink: false); 548 store(process.stdout.handleError((_) {}), stdout, closeSink: false);
575 store(process.stderr.handleError((_) {}), stderrSink, closeSink: false); 549 store(process.stderr.handleError((_) {}), stderr, closeSink: false);
576 return Future.wait([ 550 return Future.wait([
577 store(stream, process.stdin), 551 store(stream, process.stdin),
578 process.exitCode 552 process.exitCode
579 ]); 553 ]);
580 }).then((results) { 554 }).then((results) {
581 var exitCode = results[1]; 555 var exitCode = results[1];
582 if (exitCode != 0) { 556 if (exitCode != 0) {
583 throw "Failed to extract .tar.gz stream to $destination (exit code " 557 throw "Failed to extract .tar.gz stream to $destination (exit code "
584 "$exitCode)."; 558 "$exitCode).";
585 } 559 }
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
731 const PubProcessResult(this.stdout, this.stderr, this.exitCode); 705 const PubProcessResult(this.stdout, this.stderr, this.exitCode);
732 706
733 bool get success => exitCode == 0; 707 bool get success => exitCode == 0;
734 } 708 }
735 709
736 /// Gets a [Uri] for [uri], which can either already be one, or be a [String]. 710 /// Gets a [Uri] for [uri], which can either already be one, or be a [String].
737 Uri _getUri(uri) { 711 Uri _getUri(uri) {
738 if (uri is Uri) return uri; 712 if (uri is Uri) return uri;
739 return Uri.parse(uri); 713 return Uri.parse(uri);
740 } 714 }
OLDNEW
« no previous file with comments | « no previous file | utils/pub/log.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698