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

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

Issue 12255016: Get rid of old redundant methods in io.dart. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 10 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 | « utils/pub/entrypoint.dart ('k') | utils/pub/oauth2.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) 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 /// 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';
11 import 'dart:json'; 11 import 'dart:json';
12 import 'dart:uri'; 12 import 'dart:uri';
13 13
14 import '../../pkg/path/lib/path.dart' as path; 14 import '../../pkg/path/lib/path.dart' as path;
15 import '../../pkg/http/lib/http.dart' show ByteStream; 15 import '../../pkg/http/lib/http.dart' show ByteStream;
16 import 'error_group.dart'; 16 import 'error_group.dart';
17 import 'exit_codes.dart' as exit_codes; 17 import 'exit_codes.dart' as exit_codes;
18 import 'log.dart' as log; 18 import 'log.dart' as log;
19 import 'utils.dart'; 19 import 'utils.dart';
20 20
21 export '../../pkg/http/lib/http.dart' show ByteStream; 21 export '../../pkg/http/lib/http.dart' show ByteStream;
22 22
23 final NEWLINE_PATTERN = new RegExp("\r\n?|\n\r?"); 23 final NEWLINE_PATTERN = new RegExp("\r\n?|\n\r?");
24 24
25 /// Joins a number of path string parts into a single path. Handles 25 /// Joins a number of path string parts into a single path. Handles
26 /// platform-specific path separators. Parts can be [String], [Directory], or 26 /// platform-specific path separators. Parts can be [String], [Directory], or
27 /// [File] objects. 27 /// [File] objects.
28 String join(part1, [part2, part3, part4, part5, part6, part7, part8]) { 28 String join(part1, [part2, part3, part4, part5, part6, part7, part8]) {
nweiz 2013/02/14 00:10:37 Can we get rid of this?
Bob Nystrom 2013/02/14 01:14:19 That will be a bit more invasive, so I figured I'd
29 var parts = [part1, part2, part3, part4, part5, part6, part7, part8] 29 var parts = [part1, part2, part3, part4, part5, part6, part7, part8]
30 .map((part) => part == null ? null : _getPath(part)).toList(); 30 .map((part) => part == null ? null : _getPath(part)).toList();
31 31
32 return path.join(parts[0], parts[1], parts[2], parts[3], parts[4], parts[5], 32 return path.join(parts[0], parts[1], parts[2], parts[3], parts[4], parts[5],
33 parts[6], parts[7]); 33 parts[6], parts[7]);
34 } 34 }
35 35
36 /// Gets the basename, the file name without any leading directory path, for
37 /// [file], which can either be a [String], [File], or [Directory].
38 String basename(file) => path.basename(_getPath(file));
39
40 /// Gets the the leading directory path for [file], which can either be a
41 /// [String], [File], or [Directory].
42 String dirname(file) => path.dirname(_getPath(file));
43
44 /// Splits [entry] into its individual components. 36 /// Splits [entry] into its individual components.
45 List<String> splitPath(entry) => path.split(_getPath(entry)); 37 List<String> splitPath(entry) => path.split(_getPath(entry));
nweiz 2013/02/14 00:10:37 Can we get rid of this?
Bob Nystrom 2013/02/14 01:14:19 Done.
46 38
47 /// Returns whether or not [entry] is nested somewhere within [dir]. This just 39 /// Returns whether or not [entry] is nested somewhere within [dir]. This just
48 /// performs a path comparison; it doesn't look at the actual filesystem. 40 /// performs a path comparison; it doesn't look at the actual filesystem.
49 bool isBeneath(entry, dir) { 41 bool isBeneath(entry, dir) {
nweiz 2013/02/14 00:10:37 Since this just calls path methods now, we should
Bob Nystrom 2013/02/14 01:14:19 Done.
50 var relative = relativeTo(entry, dir); 42 var relative = path.relative(entry, from: dir);
51 return !path.isAbsolute(relative) && splitPath(relative)[0] != '..'; 43 return !path.isAbsolute(relative) && splitPath(relative)[0] != '..';
52 } 44 }
53 45
54 /// Returns the path to [target] from [base].
55 String relativeTo(target, base) => path.relative(target, from: base);
56
57 /// Determines if [path], which can be a [String] file path, a [File], or a 46 /// Determines if [path], which can be a [String] file path, a [File], or a
58 /// [Directory] exists on the file system. 47 /// [Directory] exists on the file system.
59 bool entryExists(path) => fileExists(path) || dirExists(path); 48 bool entryExists(path) => fileExists(path) || dirExists(path);
60 49
61 /// Determines if [file], which can be a [String] file path or a [File], exists 50 /// Determines if [file], which can be a [String] file path or a [File], exists
62 /// on the file system. 51 /// on the file system.
63 bool fileExists(file) => _getFile(file).existsSync(); 52 bool fileExists(file) => _getFile(file).existsSync();
64 53
65 /// Reads the contents of the text file [file], which can either be a [String] 54 /// Reads the contents of the text file [file], which can either be a [String]
66 /// or a [File]. 55 /// or a [File].
(...skipping 19 matching lines...) Expand all
86 75
87 // Sanity check: don't spew a huge file. 76 // Sanity check: don't spew a huge file.
88 log.io("Writing ${contents.length} characters to text file $path."); 77 log.io("Writing ${contents.length} characters to text file $path.");
89 if (!dontLogContents && contents.length < 1024 * 1024) { 78 if (!dontLogContents && contents.length < 1024 * 1024) {
90 log.fine("Contents:\n$contents"); 79 log.fine("Contents:\n$contents");
91 } 80 }
92 81
93 return file..writeAsStringSync(contents); 82 return file..writeAsStringSync(contents);
94 } 83 }
95 84
96 /// Deletes [file], which can be a [String] or a [File]. Returns a [Future] 85 /// Deletes [file], which can be a [String] or a [File].
97 /// that completes when the deletion is done.
98 File deleteFile(file) => _getFile(file)..delete(); 86 File deleteFile(file) => _getFile(file)..delete();
99 87
100 /// Creates [file] (which can either be a [String] or a [File]), and writes 88 /// Creates [file] (which can either be a [String] or a [File]), and writes
101 /// [contents] to it. 89 /// [contents] to it.
102 File writeBinaryFile(file, List<int> contents) { 90 File writeBinaryFile(file, List<int> contents) {
103 var path = _getPath(file); 91 var path = _getPath(file);
104 file = new File(path); 92 file = new File(path);
105 93
106 log.io("Writing ${contents.length} bytes to binary file $path."); 94 log.io("Writing ${contents.length} bytes to binary file $path.");
107 file.openSync(FileMode.WRITE) 95 file.openSync(FileMode.WRITE)
(...skipping 13 matching lines...) Expand all
121 109
122 var file = new File(path); 110 var file = new File(path);
123 return stream.pipe(wrapOutputStream(file.openOutputStream())).then((_) { 111 return stream.pipe(wrapOutputStream(file.openOutputStream())).then((_) {
124 log.fine("Created $path from stream."); 112 log.fine("Created $path from stream.");
125 }); 113 });
126 } 114 }
127 115
128 /// Creates a directory [dir]. 116 /// Creates a directory [dir].
129 Directory createDir(dir) => _getDirectory(dir)..createSync(); 117 Directory createDir(dir) => _getDirectory(dir)..createSync();
130 118
131 /// Ensures that [path] and all its parent directories exist. If they don't 119 /// Ensures that [dirPath] and all its parent directories exist. If they don't
132 /// exist, creates them. 120 /// exist, creates them.
133 Directory ensureDir(path) { 121 Directory ensureDir(dirPath) {
134 path = _getPath(path); 122 dirPath = _getPath(dirPath);
135 123
136 log.fine("Ensuring directory $path exists."); 124 log.fine("Ensuring directory $dirPath exists.");
137 var dir = new Directory(path); 125 var dir = new Directory(dirPath);
138 if (path == '.' || dirExists(path)) return dir; 126 if (dirPath == '.' || dirExists(dirPath)) return dir;
139 127
140 ensureDir(dirname(path)); 128 ensureDir(path.dirname(dirPath));
141 129
142 try { 130 try {
143 createDir(dir); 131 createDir(dir);
144 } on DirectoryIOException catch (ex) { 132 } on DirectoryIOException catch (ex) {
145 // Error 17 means the directory already exists (or 183 on Windows). 133 // Error 17 means the directory already exists (or 183 on Windows).
146 if (ex.osError.errorCode == 17 || ex.osError.errorCode == 183) { 134 if (ex.osError.errorCode == 17 || ex.osError.errorCode == 183) {
147 log.fine("Got 'already exists' error when creating directory."); 135 log.fine("Got 'already exists' error when creating directory.");
148 } else { 136 } else {
149 throw ex; 137 throw ex;
150 } 138 }
151 } 139 }
152 140
153 return dir; 141 return dir;
154 } 142 }
155 143
156 /// Creates a temp directory whose name will be based on [dir] with a unique 144 /// Creates a temp directory whose name will be based on [dir] with a unique
157 /// suffix appended to it. If [dir] is not provided, a temp directory will be 145 /// suffix appended to it. If [dir] is not provided, a temp directory will be
158 /// created in a platform-dependent temporary location. Returns a [Future] that 146 /// created in a platform-dependent temporary location. Returns the path of the
159 /// completes when the directory is created. 147 /// created directory.
160 Directory createTempDir([dir = '']) { 148 String createTempDir([dir = '']) {
161 var tempDir = _getDirectory(dir).createTempSync(); 149 var tempDir = _getDirectory(dir).createTempSync();
162 log.io("Created temp directory ${tempDir.path}"); 150 log.io("Created temp directory ${tempDir.path}");
163 return tempDir; 151 return tempDir.path;
164 } 152 }
165 153
166 /// Asynchronously recursively deletes [dir], which can be a [String] or a 154 /// Asynchronously recursively deletes [dir], which can be a [String] or a
167 /// [Directory]. Returns a [Future] that completes when the deletion is done. 155 /// [Directory]. Returns a [Future] that completes when the deletion is done.
168 Future<Directory> deleteDir(dir) { 156 Future<Directory> deleteDir(dir) {
169 dir = _getDirectory(dir); 157 dir = _getDirectory(dir);
170 158
171 return _attemptRetryable(() => log.ioAsync("delete directory ${dir.path}", 159 return _attemptRetryable(() => log.ioAsync("delete directory ${dir.path}",
172 dir.delete(recursive: true))); 160 dir.delete(recursive: true)));
173 } 161 }
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
211 var stackTrace; 199 var stackTrace;
212 try { 200 try {
213 throw ""; 201 throw "";
214 } catch (_, localStackTrace) { 202 } catch (_, localStackTrace) {
215 stackTrace = localStackTrace; 203 stackTrace = localStackTrace;
216 } 204 }
217 205
218 var children = []; 206 var children = [];
219 lister.onError = (error) => completer.completeError(error, stackTrace); 207 lister.onError = (error) => completer.completeError(error, stackTrace);
220 lister.onDir = (file) { 208 lister.onDir = (file) {
221 if (!includeHiddenFiles && basename(file).startsWith('.')) return; 209 if (!includeHiddenFiles && path.basename(file).startsWith('.')) return;
222 file = join(dir, basename(file)); 210 file = join(dir, path.basename(file));
223 contents.add(file); 211 contents.add(file);
224 // TODO(nweiz): don't manually recurse once issue 7358 is fixed. Note that 212 // TODO(nweiz): don't manually recurse once issue 7358 is fixed. Note that
225 // once we remove the manual recursion, we'll need to explicitly filter 213 // once we remove the manual recursion, we'll need to explicitly filter
226 // out files in hidden directories. 214 // out files in hidden directories.
227 if (recursive) { 215 if (recursive) {
228 children.add(doList(new Directory(file), listedDirectories)); 216 children.add(doList(new Directory(file), listedDirectories));
229 } 217 }
230 }; 218 };
231 219
232 lister.onFile = (file) { 220 lister.onFile = (file) {
233 if (!includeHiddenFiles && basename(file).startsWith('.')) return; 221 if (!includeHiddenFiles && path.basename(file).startsWith('.')) return;
234 contents.add(join(dir, basename(file))); 222 contents.add(join(dir, path.basename(file)));
235 }; 223 };
236 224
237 return completer.future.then((contents) { 225 return completer.future.then((contents) {
238 return Future.wait(children).then((childContents) { 226 return Future.wait(children).then((childContents) {
239 contents.addAll(flatten(childContents)); 227 contents.addAll(flatten(childContents));
240 return contents; 228 return contents;
241 }); 229 });
242 }); 230 });
243 } 231 }
244 232
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
354 // code in bin or web. 342 // code in bin or web.
355 if (!isSelfLink) { 343 if (!isSelfLink) {
356 log.warning('Warning: Package "$name" does not have a "lib" directory so ' 344 log.warning('Warning: Package "$name" does not have a "lib" directory so '
357 'you will not be able to import any libraries from it.'); 345 'you will not be able to import any libraries from it.');
358 } 346 }
359 347
360 return _getFile(to); 348 return _getFile(to);
361 }); 349 });
362 } 350 }
363 351
364 /// Given [entry] which may be a [String], [File], or [Directory] relative to
365 /// the current working directory, returns its full canonicalized path.
366 String getFullPath(entry) => path.absolute(_getPath(entry));
367
368 /// Returns whether or not [entry] is an absolute path.
369 bool isAbsolute(entry) => path.isAbsolute(_getPath(entry));
370
371 /// Resolves [target] relative to the location of pub.dart. 352 /// Resolves [target] relative to the location of pub.dart.
372 String relativeToPub(String target) { 353 String relativeToPub(String target) {
373 var scriptPath = new File(new Options().script).fullPathSync(); 354 var scriptPath = new File(new Options().script).fullPathSync();
374 355
375 // Walk up until we hit the "util(s)" directory. This lets us figure out where 356 // Walk up until we hit the "util(s)" directory. This lets us figure out where
376 // we are if this function is called from pub.dart, or one of the tests, 357 // we are if this function is called from pub.dart, or one of the tests,
377 // which also live under "utils", or from the SDK where pub is in "util". 358 // which also live under "utils", or from the SDK where pub is in "util".
378 var utilDir = dirname(scriptPath); 359 var utilDir = path.dirname(scriptPath);
379 while (basename(utilDir) != 'utils' && basename(utilDir) != 'util') { 360 while (path.basename(utilDir) != 'utils' &&
380 if (basename(utilDir) == '') throw 'Could not find path to pub.'; 361 path.basename(utilDir) != 'util') {
381 utilDir = dirname(utilDir); 362 if (path.basename(utilDir) == '') throw 'Could not find path to pub.';
363 utilDir = path.dirname(utilDir);
382 } 364 }
383 365
384 return path.normalize(join(utilDir, 'pub', target)); 366 return path.normalize(join(utilDir, 'pub', target));
385 } 367 }
386 368
387 // TODO(nweiz): add a ByteSink wrapper to make writing strings to stdout/stderr 369 // TODO(nweiz): add a ByteSink wrapper to make writing strings to stdout/stderr
388 // nicer. 370 // nicer.
389 371
390 /// A sink that writes to standard output. Errors piped to this stream will be 372 /// A sink that writes to standard output. Errors piped to this stream will be
391 /// surfaced to the top-level error handler. 373 /// surfaced to the top-level error handler.
(...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after
721 703
722 /// Creates a temporary directory and passes its path to [fn]. Once the [Future] 704 /// Creates a temporary directory and passes its path to [fn]. Once the [Future]
723 /// returned by [fn] completes, the temporary directory and all its contents 705 /// returned by [fn] completes, the temporary directory and all its contents
724 /// will be deleted. 706 /// will be deleted.
725 /// 707 ///
726 /// Returns a future that completes to the value that the future returned from 708 /// Returns a future that completes to the value that the future returned from
727 /// [fn] completes to. 709 /// [fn] completes to.
728 Future withTempDir(Future fn(String path)) { 710 Future withTempDir(Future fn(String path)) {
729 return defer(() { 711 return defer(() {
730 var tempDir = createTempDir(); 712 var tempDir = createTempDir();
731 return fn(tempDir.path).whenComplete(() { 713 return fn(tempDir).whenComplete(() {
732 return deleteDir(tempDir); 714 return deleteDir(tempDir);
733 }); 715 });
734 }); 716 });
735 } 717 }
736 718
737 /// Extracts a `.tar.gz` file from [stream] to [destination], which can be a 719 /// Extracts a `.tar.gz` file from [stream] to [destination], which can be a
738 /// directory or a path. Returns whether or not the extraction was successful. 720 /// directory or a path. Returns whether or not the extraction was successful.
739 Future<bool> extractTarGz(Stream<List<int>> stream, destination) { 721 Future<bool> extractTarGz(Stream<List<int>> stream, destination) {
740 destination = _getPath(destination); 722 destination = _getPath(destination);
741 723
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
828 var buffer = new StringBuffer(); 810 var buffer = new StringBuffer();
829 buffer.add('Creating .tag.gz stream containing:\n'); 811 buffer.add('Creating .tag.gz stream containing:\n');
830 contents.forEach((file) => buffer.add('$file\n')); 812 contents.forEach((file) => buffer.add('$file\n'));
831 log.fine(buffer.toString()); 813 log.fine(buffer.toString());
832 814
833 // TODO(nweiz): Propagate errors to the returned stream (including non-zero 815 // TODO(nweiz): Propagate errors to the returned stream (including non-zero
834 // exit codes). See issue 3657. 816 // exit codes). See issue 3657.
835 var controller = new StreamController<List<int>>(); 817 var controller = new StreamController<List<int>>();
836 818
837 if (baseDir == null) baseDir = path.current; 819 if (baseDir == null) baseDir = path.current;
838 baseDir = getFullPath(baseDir); 820 baseDir = path.absolute(baseDir);
839 contents = contents.map((entry) { 821 contents = contents.map((entry) {
840 entry = getFullPath(entry); 822 entry = path.absolute(_getPath(entry));
841 if (!isBeneath(entry, baseDir)) { 823 if (!isBeneath(entry, baseDir)) {
842 throw 'Entry $entry is not inside $baseDir.'; 824 throw 'Entry $entry is not inside $baseDir.';
843 } 825 }
844 return relativeTo(entry, baseDir); 826 return path.relative(entry, from: baseDir);
845 }).toList(); 827 }).toList();
846 828
847 if (Platform.operatingSystem != "windows") { 829 if (Platform.operatingSystem != "windows") {
848 var args = ["--create", "--gzip", "--directory", baseDir]; 830 var args = ["--create", "--gzip", "--directory", baseDir];
849 args.addAll(contents.map(_getPath)); 831 args.addAll(contents.map(_getPath));
850 // TODO(nweiz): It's possible that enough command-line arguments will make 832 // TODO(nweiz): It's possible that enough command-line arguments will make
851 // the process choke, so at some point we should save the arguments to a 833 // the process choke, so at some point we should save the arguments to a
852 // file and pass them in via --files-from for tar and -i@filename for 7zip. 834 // file and pass them in via --files-from for tar and -i@filename for 7zip.
853 startProcess("tar", args).then((process) { 835 startProcess("tar", args).then((process) {
854 store(process.stdout, controller); 836 store(process.stdout, controller);
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
941 Directory _getDirectory(entry) { 923 Directory _getDirectory(entry) {
942 if (entry is Directory) return entry; 924 if (entry is Directory) return entry;
943 return new Directory(entry); 925 return new Directory(entry);
944 } 926 }
945 927
946 /// Gets a [Uri] for [uri], which can either already be one, or be a [String]. 928 /// Gets a [Uri] for [uri], which can either already be one, or be a [String].
947 Uri _getUri(uri) { 929 Uri _getUri(uri) {
948 if (uri is Uri) return uri; 930 if (uri is Uri) return uri;
949 return Uri.parse(uri); 931 return Uri.parse(uri);
950 } 932 }
OLDNEW
« no previous file with comments | « utils/pub/entrypoint.dart ('k') | utils/pub/oauth2.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698