OLD | NEW |
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 pub.io; | 6 library pub.io; |
7 | 7 |
8 import 'dart:async'; | 8 import 'dart:async'; |
9 import 'dart:collection'; | 9 import 'dart:collection'; |
10 import 'dart:convert'; | 10 import 'dart:convert'; |
(...skipping 915 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
926 } | 926 } |
927 | 927 |
928 /// Create a .tar.gz archive from a list of entries. | 928 /// Create a .tar.gz archive from a list of entries. |
929 /// | 929 /// |
930 /// Each entry can be a [String], [Directory], or [File] object. The root of | 930 /// Each entry can be a [String], [Directory], or [File] object. The root of |
931 /// the archive is considered to be [baseDir], which defaults to the current | 931 /// the archive is considered to be [baseDir], which defaults to the current |
932 /// working directory. | 932 /// working directory. |
933 /// | 933 /// |
934 /// Returns a [ByteStream] that emits the contents of the archive. | 934 /// Returns a [ByteStream] that emits the contents of the archive. |
935 ByteStream createTarGz(List contents, {baseDir}) { | 935 ByteStream createTarGz(List contents, {baseDir}) { |
936 return new ByteStream(futureStream(new Future.sync(() { | 936 return new ByteStream(futureStream(new Future.sync(() async { |
937 var buffer = new StringBuffer(); | 937 var buffer = new StringBuffer(); |
938 buffer.write('Creating .tag.gz stream containing:\n'); | 938 buffer.write('Creating .tag.gz stream containing:\n'); |
939 contents.forEach((file) => buffer.write('$file\n')); | 939 contents.forEach((file) => buffer.write('$file\n')); |
940 log.fine(buffer.toString()); | 940 log.fine(buffer.toString()); |
941 | 941 |
942 if (baseDir == null) baseDir = path.current; | 942 if (baseDir == null) baseDir = path.current; |
943 baseDir = path.absolute(baseDir); | 943 baseDir = path.absolute(baseDir); |
944 contents = contents.map((entry) { | 944 contents = contents.map((entry) { |
945 entry = path.absolute(entry); | 945 entry = path.absolute(entry); |
946 if (!path.isWithin(baseDir, entry)) { | 946 if (!path.isWithin(baseDir, entry)) { |
947 throw new ArgumentError('Entry $entry is not inside $baseDir.'); | 947 throw new ArgumentError('Entry $entry is not inside $baseDir.'); |
948 } | 948 } |
949 return path.relative(entry, from: baseDir); | 949 return path.relative(entry, from: baseDir); |
950 }).toList(); | 950 }).toList(); |
951 | 951 |
952 if (Platform.operatingSystem != "windows") { | 952 if (Platform.operatingSystem != "windows") { |
953 var args = ["--create", "--gzip", "--directory", baseDir]; | 953 var args = [ |
954 args.addAll(contents); | 954 "--create", |
955 // TODO(nweiz): It's possible that enough command-line arguments will | 955 "--gzip", |
956 // make the process choke, so at some point we should save the arguments | 956 "--directory", |
957 // to a file and pass them in via --files-from for tar and -i@filename | 957 baseDir, |
958 // for 7zip. | 958 "--files-from", |
959 return startProcess("tar", args).then((process) => process.stdout); | 959 "/dev/stdin" |
| 960 ]; |
| 961 |
| 962 var process = await startProcess("tar", args); |
| 963 process.stdin.add(UTF8.encode(contents.join("\n"))); |
| 964 process.stdin.close(); |
| 965 return process.stdout; |
960 } | 966 } |
961 | 967 |
962 // Don't use [withTempDir] here because we don't want to delete the temp | 968 // Don't use [withTempDir] here because we don't want to delete the temp |
963 // directory until the returned stream has closed. | 969 // directory until the returned stream has closed. |
964 var tempDir = createSystemTempDir(); | 970 var tempDir = createSystemTempDir(); |
965 return new Future.sync(() { | 971 |
| 972 try { |
| 973 // Create the file containing the list of files to compress. |
| 974 var contentsPath = path.join(tempDir, "files.txt"); |
| 975 writeTextFile(contentsPath, contents.join("\n")); |
| 976 |
966 // Create the tar file. | 977 // Create the tar file. |
967 var tarFile = path.join(tempDir, "intermediate.tar"); | 978 var tarFile = path.join(tempDir, "intermediate.tar"); |
968 var args = ["a", "-w$baseDir", tarFile]; | 979 var args = ["a", "-w$baseDir", tarFile, "@$contentsPath"]; |
969 args.addAll(contents.map((entry) => '-i!$entry')); | |
970 | 980 |
971 // We're passing 'baseDir' both as '-w' and setting it as the working | 981 // We're passing 'baseDir' both as '-w' and setting it as the working |
972 // directory explicitly here intentionally. The former ensures that the | 982 // directory explicitly here intentionally. The former ensures that the |
973 // files added to the archive have the correct relative path in the | 983 // files added to the archive have the correct relative path in the |
974 // archive. The latter enables relative paths in the "-i" args to be | 984 // archive. The latter enables relative paths in the "-i" args to be |
975 // resolved. | 985 // resolved. |
976 return runProcess(pathTo7zip, args, workingDir: baseDir).then((_) { | 986 await runProcess(pathTo7zip, args, workingDir: baseDir); |
977 // GZIP it. 7zip doesn't support doing both as a single operation. | 987 |
978 // Send the output to stdout. | 988 // GZIP it. 7zip doesn't support doing both as a single operation. |
979 args = ["a", "unused", "-tgzip", "-so", tarFile]; | 989 // Send the output to stdout. |
980 return startProcess(pathTo7zip, args); | 990 args = ["a", "unused", "-tgzip", "-so", tarFile]; |
981 }).then((process) => process.stdout); | 991 return (await startProcess(pathTo7zip, args)) |
982 }).then((stream) { | 992 .stdout |
983 return stream.transform(onDoneTransformer(() => deleteEntry(tempDir))); | 993 .transform(onDoneTransformer(() => deleteEntry(tempDir))); |
984 }).catchError((e) { | 994 } catch (_) { |
985 deleteEntry(tempDir); | 995 deleteEntry(tempDir); |
986 throw e; | 996 rethrow; |
987 }); | 997 } |
988 }))); | 998 }))); |
989 } | 999 } |
990 | 1000 |
991 /// Contains the results of invoking a [Process] and waiting for it to complete. | 1001 /// Contains the results of invoking a [Process] and waiting for it to complete. |
992 class PubProcessResult { | 1002 class PubProcessResult { |
993 final List<String> stdout; | 1003 final List<String> stdout; |
994 final List<String> stderr; | 1004 final List<String> stderr; |
995 final int exitCode; | 1005 final int exitCode; |
996 | 1006 |
997 PubProcessResult(String stdout, String stderr, this.exitCode) | 1007 PubProcessResult(String stdout, String stderr, this.exitCode) |
998 : this.stdout = _toLines(stdout), | 1008 : this.stdout = _toLines(stdout), |
999 this.stderr = _toLines(stderr); | 1009 this.stderr = _toLines(stderr); |
1000 | 1010 |
1001 // TODO(rnystrom): Remove this and change to returning one string. | 1011 // TODO(rnystrom): Remove this and change to returning one string. |
1002 static List<String> _toLines(String output) { | 1012 static List<String> _toLines(String output) { |
1003 var lines = splitLines(output); | 1013 var lines = splitLines(output); |
1004 if (!lines.isEmpty && lines.last == "") lines.removeLast(); | 1014 if (!lines.isEmpty && lines.last == "") lines.removeLast(); |
1005 return lines; | 1015 return lines; |
1006 } | 1016 } |
1007 | 1017 |
1008 bool get success => exitCode == exit_codes.SUCCESS; | 1018 bool get success => exitCode == exit_codes.SUCCESS; |
1009 } | 1019 } |
1010 | 1020 |
1011 /// Gets a [Uri] for [uri], which can either already be one, or be a [String]. | 1021 /// Gets a [Uri] for [uri], which can either already be one, or be a [String]. |
1012 Uri _getUri(uri) { | 1022 Uri _getUri(uri) { |
1013 if (uri is Uri) return uri; | 1023 if (uri is Uri) return uri; |
1014 return Uri.parse(uri); | 1024 return Uri.parse(uri); |
1015 } | 1025 } |
OLD | NEW |