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 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 133 } | 133 } |
| 134 | 134 |
| 135 /** | 135 /** |
| 136 * Asynchronously deletes [file], which can be a [String] or a [File]. Returns a | 136 * Asynchronously deletes [file], which can be a [String] or a [File]. Returns a |
| 137 * [Future] that completes when the deletion is done. | 137 * [Future] that completes when the deletion is done. |
| 138 */ | 138 */ |
| 139 Future<File> deleteFile(file) { | 139 Future<File> deleteFile(file) { |
| 140 return new File(_getPath(file)).delete(); | 140 return new File(_getPath(file)).delete(); |
| 141 } | 141 } |
| 142 | 142 |
| 143 /// Writes [stream] to a new file at [path], which may be a [String] or a | |
| 144 /// [File]. Will replace any file already at that path. Completes when the file | |
| 145 /// is done being written. | |
| 146 Future<File> createFileFromStream(InputStream stream, path) { | |
| 147 path = _getPath(path); | |
| 148 | |
| 149 var completer = new Completer<File>(); | |
| 150 var file = new File(path); | |
| 151 var outputStream = file.openOutputStream(); | |
| 152 stream.pipe(outputStream); | |
| 153 | |
| 154 outputStream.onClosed = () { | |
| 155 completer.complete(file); | |
| 156 }; | |
| 157 | |
| 158 stream.onError = completer.completeException; | |
| 159 outputStream.onError = completer.completeException; | |
|
nweiz
2012/10/02 01:04:13
It's possible that both streams could throw errors
Bob Nystrom
2012/10/02 01:36:37
Done.
| |
| 160 | |
| 161 return completer.future; | |
| 162 } | |
| 163 | |
| 143 /** | 164 /** |
| 144 * Creates a directory [dir]. Returns a [Future] that completes when the | 165 * Creates a directory [dir]. Returns a [Future] that completes when the |
| 145 * directory is created. | 166 * directory is created. |
| 146 */ | 167 */ |
| 147 Future<Directory> createDir(dir) { | 168 Future<Directory> createDir(dir) { |
| 148 dir = _getDirectory(dir); | 169 dir = _getDirectory(dir); |
| 149 return dir.create(); | 170 return dir.create(); |
| 150 } | 171 } |
| 151 | 172 |
| 152 /** | 173 /** |
| (...skipping 474 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 627 } | 648 } |
| 628 | 649 |
| 629 Future<bool> _extractTarGzWindows(InputStream stream, String destination) { | 650 Future<bool> _extractTarGzWindows(InputStream stream, String destination) { |
| 630 // Find 7zip. | 651 // Find 7zip. |
| 631 var scriptPath = new File(new Options().script).fullPathSync(); | 652 var scriptPath = new File(new Options().script).fullPathSync(); |
| 632 var scriptDir = new Path.fromNative(scriptPath).directoryPath; | 653 var scriptDir = new Path.fromNative(scriptPath).directoryPath; |
| 633 | 654 |
| 634 // Note: This line of code gets munged by create_sdk.py to be the correct | 655 // Note: This line of code gets munged by create_sdk.py to be the correct |
| 635 // relative path to 7zip in the SDK. | 656 // relative path to 7zip in the SDK. |
| 636 var pathTo7zip = '../../third_party/7zip/7za.exe'; | 657 var pathTo7zip = '../../third_party/7zip/7za.exe'; |
| 658 var command = scriptDir.append(pathTo7zip).canonicalize().toNativePath(); | |
| 659 | |
| 660 var tempDir; | |
| 661 | |
| 662 return createTempDir().chain((temp) { | |
| 663 // Write the archive to a temp file. | |
| 664 tempDir = temp; | |
| 665 return createFileFromStream(stream, join(tempDir, 'data.tar.gz')); | |
| 666 }).chain((tarGz) { | |
| 667 // 7zip can't unarchive from gzip -> tar -> destination all in one step | |
| 668 // first we un-gzip it to a tar file. | |
| 669 // TODO(rnystrom): Setting the working directory instead of passing in | |
|
nweiz
2012/10/02 01:04:13
I don't know if this is really a TODO, since you c
Bob Nystrom
2012/10/02 01:36:37
Done.
| |
| 670 // a full file path because 7zip says "A full path is not allowed here." | |
| 671 return runProcess(command, ['e', 'data.tar.gz'], workingDir: tempDir); | |
| 672 }).chain((result) { | |
| 673 if (result.exitCode != 0) { | |
| 674 throw 'Could not un-gzip (exit code ${result.exitCode}). Error:\n' | |
| 675 '${Strings.join(result.stderr, "\n")}'; | |
| 676 } | |
| 677 | |
| 678 // Find the tar file we just created since we don't know its name. | |
| 679 return listDir(tempDir); | |
| 680 }).chain((files) { | |
| 681 var tarFile; | |
| 682 for (var file in files) { | |
| 683 if (new Path(file).extension == 'tar') { | |
| 684 tarFile = file; | |
| 685 break; | |
| 686 } | |
| 687 } | |
| 688 | |
| 689 if (tarFile == null) throw 'The gzip file did not contain a tar file.'; | |
| 690 | |
| 691 // Untar the archive into the destination directory. | |
| 692 return runProcess(command, ['x', '-o"$destination"', tarFile], | |
| 693 workingDir: tempDir); | |
| 694 }).chain((result) { | |
| 695 if (result.exitCode != 0) { | |
| 696 throw 'Could not un-tar (exit code ${result.exitCode}). Error:\n' | |
| 697 '${Strings.join(result.stderr, "\n")}'; | |
| 698 } | |
| 699 | |
| 700 // Clean up the temp directory. | |
| 701 // TODO(rnystrom): Should also delete this if anything fails. | |
| 702 return deleteDir(tempDir); | |
| 703 }).transform((_) => true); | |
| 704 } | |
| 705 | |
| 706 // TODO(rnystrom): The following is a cleaner way of extracting archives on | |
| 707 // Windows. It does everything in memory by piping streams directly together | |
| 708 // instead of writing out temp files. Unfortunately, 7zip seems to periodically | |
| 709 // fail when we invoke it from Dart and tell it to read from stdin instead of | |
| 710 // a file. Leaving this code here since it's otherwise cleaner, and maybe we | |
| 711 // can resurrect it at some point. | |
| 712 /* | |
|
nweiz
2012/10/02 01:04:13
I don't like checking in commented-out code. I fee
Bob Nystrom
2012/10/02 01:36:37
Done.
| |
| 713 Future<bool> _extractTarGzWindows(InputStream stream, String destination) { | |
| 714 // Find 7zip. | |
| 715 var scriptPath = new File(new Options().script).fullPathSync(); | |
| 716 var scriptDir = new Path.fromNative(scriptPath).directoryPath; | |
| 717 | |
| 718 // Note: This line of code gets munged by create_sdk.py to be the correct | |
| 719 // relative path to 7zip in the SDK. | |
| 720 var pathTo7zip = '../../third_party/7zip/7za.exe'; | |
| 637 | 721 |
| 638 var command = scriptDir.append(pathTo7zip).canonicalize().toNativePath(); | 722 var command = scriptDir.append(pathTo7zip).canonicalize().toNativePath(); |
| 639 | 723 |
| 640 // 7zip can't unarchive from gzip -> tar -> destination all in one step so | 724 // 7zip can't unarchive from gzip -> tar -> destination all in one step so |
| 641 // we spawn it twice and pipe them together. | 725 // we spawn it twice and pipe them together. |
| 642 var completer = new Completer<bool>(); | 726 var completer = new Completer<bool>(); |
| 643 var gzipProcess = Process.start(command, ['e', '-si', '-tgzip', '-so']); | 727 var gzipProcess = Process.start(command, ['e', '-si', '-tgzip', '-so']); |
| 644 | 728 |
| 645 // TODO(rnystrom): Even though we are quoting the destination directory here, | 729 // TODO(rnystrom): Even though we are quoting the destination directory here, |
| 646 // 7zip still seems to barf if there is a space in the path. For now we'll | 730 // 7zip still seems to barf if there is a space in the path. For now we'll |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 675 } else { | 759 } else { |
| 676 completer.complete(true); | 760 completer.complete(true); |
| 677 } | 761 } |
| 678 }; | 762 }; |
| 679 | 763 |
| 680 tarProcess.onError = completer.completeException; | 764 tarProcess.onError = completer.completeException; |
| 681 gzipProcess.onError = completer.completeException; | 765 gzipProcess.onError = completer.completeException; |
| 682 | 766 |
| 683 return completer.future; | 767 return completer.future; |
| 684 } | 768 } |
| 769 */ | |
| 685 | 770 |
| 686 /** | 771 /** |
| 687 * Exception thrown when an HTTP operation fails. | 772 * Exception thrown when an HTTP operation fails. |
| 688 */ | 773 */ |
| 689 class PubHttpException implements Exception { | 774 class PubHttpException implements Exception { |
| 690 final int statusCode; | 775 final int statusCode; |
| 691 final String reason; | 776 final String reason; |
| 692 | 777 |
| 693 const PubHttpException(this.statusCode, this.reason); | 778 const PubHttpException(this.statusCode, this.reason); |
| 694 } | 779 } |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 736 return new Directory(entry); | 821 return new Directory(entry); |
| 737 } | 822 } |
| 738 | 823 |
| 739 /** | 824 /** |
| 740 * Gets a [Uri] for [uri], which can either already be one, or be a [String]. | 825 * Gets a [Uri] for [uri], which can either already be one, or be a [String]. |
| 741 */ | 826 */ |
| 742 Uri _getUri(uri) { | 827 Uri _getUri(uri) { |
| 743 if (uri is Uri) return uri; | 828 if (uri is Uri) return uri; |
| 744 return new Uri.fromString(uri); | 829 return new Uri.fromString(uri); |
| 745 } | 830 } |
| OLD | NEW |