Chromium Code Reviews| 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 353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 364 | 364 |
| 365 // Using Path.join here instead of File().fullPathSync() because the former | 365 // Using Path.join here instead of File().fullPathSync() because the former |
| 366 // does not require an actual file to exist at that path. | 366 // does not require an actual file to exist at that path. |
| 367 return new Path.fromNative(currentWorkingDir).join(new Path(path)) | 367 return new Path.fromNative(currentWorkingDir).join(new Path(path)) |
| 368 .toNativePath(); | 368 .toNativePath(); |
| 369 } | 369 } |
| 370 | 370 |
| 371 /// Resolves [path] relative to the location of pub.dart. | 371 /// Resolves [path] relative to the location of pub.dart. |
| 372 String relativeToPub(String path) { | 372 String relativeToPub(String path) { |
| 373 var scriptPath = new File(new Options().script).fullPathSync(); | 373 var scriptPath = new File(new Options().script).fullPathSync(); |
| 374 var scriptDir = new Path.fromNative(scriptPath).directoryPath; | 374 |
| 375 return scriptDir.append(path).canonicalize().toNativePath(); | 375 // Walk up until we hit the "utils" directory. This lets us figure out where |
| 376 // we are if this function is called from pub.dart, or one of the tests, | |
| 377 // which also live under "utils". | |
| 378 var utilsDir = new Path.fromNative(scriptPath).directoryPath; | |
| 379 while (utilsDir.filename != 'utils') { | |
| 380 utilsDir = utilsDir.directoryPath; | |
|
nweiz
2012/11/28 23:37:55
We should have a reasonable error message if this
Bob Nystrom
2012/11/29 00:16:11
Yeah, I'm not sure exactly how this will fail, but
| |
| 381 } | |
| 382 | |
| 383 return utilsDir.append('pub').append(path).canonicalize().toNativePath(); | |
| 376 } | 384 } |
| 377 | 385 |
| 378 /// A StringInputStream reading from stdin. | 386 /// A StringInputStream reading from stdin. |
| 379 final _stringStdin = new StringInputStream(stdin); | 387 final _stringStdin = new StringInputStream(stdin); |
| 380 | 388 |
| 381 /// Returns a single line read from a [StringInputStream]. By default, reads | 389 /// Returns a single line read from a [StringInputStream]. By default, reads |
| 382 /// from stdin. | 390 /// from stdin. |
| 383 /// | 391 /// |
| 384 /// A [StringInputStream] passed to this should have no callbacks registered. | 392 /// A [StringInputStream] passed to this should have no callbacks registered. |
| 385 Future<String> readLine([StringInputStream stream]) { | 393 Future<String> readLine([StringInputStream stream]) { |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 469 */ | 477 */ |
| 470 Future<String> httpGetString(uri) { | 478 Future<String> httpGetString(uri) { |
| 471 var future = httpGet(uri).chain((stream) => consumeInputStream(stream)) | 479 var future = httpGet(uri).chain((stream) => consumeInputStream(stream)) |
| 472 .transform((bytes) => new String.fromCharCodes(bytes)); | 480 .transform((bytes) => new String.fromCharCodes(bytes)); |
| 473 return timeout(future, HTTP_TIMEOUT, 'fetching URL "$uri"'); | 481 return timeout(future, HTTP_TIMEOUT, 'fetching URL "$uri"'); |
| 474 } | 482 } |
| 475 | 483 |
| 476 /** | 484 /** |
| 477 * Takes all input from [source] and writes it to [sink]. | 485 * Takes all input from [source] and writes it to [sink]. |
| 478 * | 486 * |
| 479 * [onClosed] is called when [source] is closed. | 487 * Returns a future that completes when [source] is closed. |
| 480 */ | 488 */ |
| 481 void pipeInputToInput(InputStream source, ListInputStream sink, | 489 Future pipeInputToInput(InputStream source, ListInputStream sink) { |
| 482 [void onClosed()]) { | 490 var completer = new Completer(); |
| 483 source.onClosed = () { | 491 source.onClosed = () { |
| 484 sink.markEndOfStream(); | 492 sink.markEndOfStream(); |
| 485 if (onClosed != null) onClosed(); | 493 completer.complete(null); |
| 486 }; | 494 }; |
| 487 source.onData = () => sink.write(source.read()); | 495 source.onData = () => sink.write(source.read()); |
| 488 // TODO(nweiz): propagate this error to the sink. See issue 3657. | 496 // TODO(nweiz): propagate this error to the sink. See issue 3657. |
| 489 source.onError = (e) { throw e; }; | 497 source.onError = (e) { throw e; }; |
| 498 return completer.future; | |
| 490 } | 499 } |
| 491 | 500 |
| 492 /** | 501 /** |
| 493 * Buffers all input from an InputStream and returns it as a future. | 502 * Buffers all input from an InputStream and returns it as a future. |
| 494 */ | 503 */ |
| 495 Future<List<int>> consumeInputStream(InputStream stream) { | 504 Future<List<int>> consumeInputStream(InputStream stream) { |
| 496 if (stream.closed) return new Future.immediate(<int>[]); | 505 if (stream.closed) return new Future.immediate(<int>[]); |
| 497 | 506 |
| 498 var completer = new Completer<List<int>>(); | 507 var completer = new Completer<List<int>>(); |
| 499 var buffer = <int>[]; | 508 var buffer = <int>[]; |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 605 completer.complete(value); | 614 completer.complete(value); |
| 606 }); | 615 }); |
| 607 return completer.future; | 616 return completer.future; |
| 608 } | 617 } |
| 609 | 618 |
| 610 /// Creates a temporary directory and passes its path to [fn]. Once the [Future] | 619 /// Creates a temporary directory and passes its path to [fn]. Once the [Future] |
| 611 /// returned by [fn] completes, the temporary directory and all its contents | 620 /// returned by [fn] completes, the temporary directory and all its contents |
| 612 /// will be deleted. | 621 /// will be deleted. |
| 613 Future withTempDir(Future fn(String path)) { | 622 Future withTempDir(Future fn(String path)) { |
| 614 var tempDir; | 623 var tempDir; |
| 615 var future = new Directory('').createTemp().chain((dir) { | 624 var future = createTempDir().chain((dir) { |
| 616 tempDir = dir; | 625 tempDir = dir; |
| 617 return fn(tempDir.path); | 626 return fn(tempDir.path); |
| 618 }); | 627 }); |
| 619 future.onComplete((_) => tempDir.delete(recursive: true)); | 628 future.onComplete((_) => tempDir.delete(recursive: true)); |
| 620 return future; | 629 return future; |
| 621 } | 630 } |
| 622 | 631 |
| 623 /// Tests whether or not the git command-line app is available for use. | 632 /// Tests whether or not the git command-line app is available for use. |
| 624 Future<bool> get isGitInstalled { | 633 Future<bool> get isGitInstalled { |
| 625 if (_isGitInstalledCache != null) { | 634 if (_isGitInstalledCache != null) { |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 718 // read from stdin instead of a file. Consider resurrecting that version if | 727 // read from stdin instead of a file. Consider resurrecting that version if |
| 719 // we can figure out why it fails. | 728 // we can figure out why it fails. |
| 720 | 729 |
| 721 // Note: This line of code gets munged by create_sdk.py to be the correct | 730 // Note: This line of code gets munged by create_sdk.py to be the correct |
| 722 // relative path to 7zip in the SDK. | 731 // relative path to 7zip in the SDK. |
| 723 var pathTo7zip = '../../third_party/7zip/7za.exe'; | 732 var pathTo7zip = '../../third_party/7zip/7za.exe'; |
| 724 var command = relativeToPub(pathTo7zip); | 733 var command = relativeToPub(pathTo7zip); |
| 725 | 734 |
| 726 var tempDir; | 735 var tempDir; |
| 727 | 736 |
| 737 // TODO(rnystrom): Use withTempDir(). | |
| 728 return createTempDir().chain((temp) { | 738 return createTempDir().chain((temp) { |
| 729 // Write the archive to a temp file. | 739 // Write the archive to a temp file. |
| 730 tempDir = temp; | 740 tempDir = temp; |
| 731 return createFileFromStream(stream, join(tempDir, 'data.tar.gz')); | 741 return createFileFromStream(stream, join(tempDir, 'data.tar.gz')); |
| 732 }).chain((_) { | 742 }).chain((_) { |
| 733 // 7zip can't unarchive from gzip -> tar -> destination all in one step | 743 // 7zip can't unarchive from gzip -> tar -> destination all in one step |
| 734 // first we un-gzip it to a tar file. | 744 // first we un-gzip it to a tar file. |
| 735 // Note: Setting the working directory instead of passing in a full file | 745 // Note: Setting the working directory instead of passing in a full file |
| 736 // path because 7zip says "A full path is not allowed here." | 746 // path because 7zip says "A full path is not allowed here." |
| 737 return runProcess(command, ['e', 'data.tar.gz'], workingDir: tempDir); | 747 return runProcess(command, ['e', 'data.tar.gz'], workingDir: tempDir); |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 806 // Create the tar file. | 816 // Create the tar file. |
| 807 var tarFile = join(tempDir, "intermediate.tar"); | 817 var tarFile = join(tempDir, "intermediate.tar"); |
| 808 var args = ["a", "-w$baseDir", tarFile]; | 818 var args = ["a", "-w$baseDir", tarFile]; |
| 809 args.addAll(contents.map((entry) => '-i!"$entry"')); | 819 args.addAll(contents.map((entry) => '-i!"$entry"')); |
| 810 | 820 |
| 811 // Note: This line of code gets munged by create_sdk.py to be the correct | 821 // Note: This line of code gets munged by create_sdk.py to be the correct |
| 812 // relative path to 7zip in the SDK. | 822 // relative path to 7zip in the SDK. |
| 813 var pathTo7zip = '../../third_party/7zip/7za.exe'; | 823 var pathTo7zip = '../../third_party/7zip/7za.exe'; |
| 814 var command = relativeToPub(pathTo7zip); | 824 var command = relativeToPub(pathTo7zip); |
| 815 | 825 |
| 816 return runProcess(command, args).chain((_) { | 826 // We're passing 'baseDir' both as '-w' and setting it as the working |
| 827 // directory explicitly here intentionally. The former ensures that the | |
| 828 // files added to the archive have the correct relative path in the archive. | |
| 829 // The latter enables relative paths in the "-i" args to be resolved. | |
| 830 return runProcess(command, args, workingDir: baseDir).chain((_) { | |
| 817 // GZIP it. 7zip doesn't support doing both as a single operation. Send | 831 // GZIP it. 7zip doesn't support doing both as a single operation. Send |
| 818 // the output to stdout. | 832 // the output to stdout. |
| 819 args = ["a", "not used", "-so", tarFile]; | 833 args = ["a", "unused", "-tgzip", "-so", tarFile]; |
| 820 return startProcess(command, args); | 834 return startProcess(command, args); |
| 821 }).transform((process) { | 835 }).chain((process) { |
| 822 pipeInputToInput(process.stdout, stream); | |
| 823 process.stderr.pipe(stderr, close: false); | 836 process.stderr.pipe(stderr, close: false); |
| 837 return pipeInputToInput(process.stdout, stream); | |
| 824 }); | 838 }); |
| 825 }); | 839 }); |
| 826 return stream; | 840 return stream; |
| 827 } | 841 } |
| 828 | 842 |
| 829 /** | 843 /** |
| 830 * Exception thrown when an HTTP operation fails. | 844 * Exception thrown when an HTTP operation fails. |
| 831 */ | 845 */ |
| 832 class PubHttpException implements Exception { | 846 class PubHttpException implements Exception { |
| 833 final int statusCode; | 847 final int statusCode; |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 893 return new Directory(entry); | 907 return new Directory(entry); |
| 894 } | 908 } |
| 895 | 909 |
| 896 /** | 910 /** |
| 897 * Gets a [Uri] for [uri], which can either already be one, or be a [String]. | 911 * Gets a [Uri] for [uri], which can either already be one, or be a [String]. |
| 898 */ | 912 */ |
| 899 Uri _getUri(uri) { | 913 Uri _getUri(uri) { |
| 900 if (uri is Uri) return uri; | 914 if (uri is Uri) return uri; |
| 901 return new Uri.fromString(uri); | 915 return new Uri.fromString(uri); |
| 902 } | 916 } |
| OLD | NEW |