| 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('pub_io'); | 8 #library('pub_io'); |
| 9 | 9 |
| 10 #import('dart:io'); | 10 #import('dart:io'); |
| 11 | 11 |
| 12 #import('../lib/file_system.dart', prefix: 'fs'); | 12 #import('../lib/file_system.dart', prefix: 'fs'); |
| 13 | 13 |
| 14 /** Gets the current working directory. */ |
| 15 String get workingDir() => new File('.').fullPathSync(); |
| 16 |
| 14 /** | 17 /** |
| 15 * Joins a number of path string parts into a single path. Handles | 18 * Joins a number of path string parts into a single path. Handles |
| 16 * platform-specific path separators. Parts can be [String], [Directory], or | 19 * platform-specific path separators. Parts can be [String], [Directory], or |
| 17 * [File] objects. | 20 * [File] objects. |
| 18 */ | 21 */ |
| 19 String join(part1, [part2, part3, part4]) { | 22 String join(part1, [part2, part3, part4]) { |
| 20 final parts = _getPath(part1).split('/'); | 23 final parts = _getPath(part1).split('/'); |
| 21 | 24 |
| 22 for (final part in [part2, part3, part4]) { | 25 for (final part in [part2, part3, part4]) { |
| 23 if (part == null) continue; | 26 if (part == null) continue; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 40 | 43 |
| 41 /** | 44 /** |
| 42 * Gets the basename, the file name without any leading directory path, for | 45 * Gets the basename, the file name without any leading directory path, for |
| 43 * [file], which can either be a [String], [File], or [Directory]. | 46 * [file], which can either be a [String], [File], or [Directory]. |
| 44 */ | 47 */ |
| 45 String basename(file) { | 48 String basename(file) { |
| 46 return fs.basename(_getPath(file)); | 49 return fs.basename(_getPath(file)); |
| 47 } | 50 } |
| 48 | 51 |
| 49 /** | 52 /** |
| 53 * Asynchronously determines if [file], which can be a [String] file path or a |
| 54 * [File], exists on the file system. Returns a [Future] that completes with |
| 55 * the result. |
| 56 */ |
| 57 Future<bool> fileExists(file) { |
| 58 final completer = new Completer<bool>(); |
| 59 |
| 60 file = new File(_getPath(file)); |
| 61 file.onError = (error) => completer.completeException(error); |
| 62 file.exists((exists) => completer.complete(exists)); |
| 63 |
| 64 return completer.future; |
| 65 } |
| 66 |
| 67 /** |
| 50 * Reads the contents of the text file [file], which can either be a [String] or | 68 * Reads the contents of the text file [file], which can either be a [String] or |
| 51 * a [File]. | 69 * a [File]. |
| 52 */ | 70 */ |
| 53 Future<String> readTextFile(file) { | 71 Future<String> readTextFile(file) { |
| 54 file = new File(_getPath(file)); | 72 file = new File(_getPath(file)); |
| 55 final completer = new Completer<String>(); | 73 final completer = new Completer<String>(); |
| 56 file.onError = (error) => completer.completeException(error); | 74 file.onError = (error) => completer.completeException(error); |
| 57 file.readAsText(Encoding.UTF_8, (text) => completer.complete(text)); | 75 file.readAsText(Encoding.UTF_8, (text) => completer.complete(text)); |
| 58 | 76 |
| 59 return completer.future; | 77 return completer.future; |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 103 dir.createTemp(() => completer.complete(dir)); | 121 dir.createTemp(() => completer.complete(dir)); |
| 104 | 122 |
| 105 return completer.future; | 123 return completer.future; |
| 106 } | 124 } |
| 107 | 125 |
| 108 /** | 126 /** |
| 109 * Asynchronously recursively deletes [dir], which can be a [String] or a | 127 * Asynchronously recursively deletes [dir], which can be a [String] or a |
| 110 * [Directory]. Returns a [Future] that completes when the deletion is done. | 128 * [Directory]. Returns a [Future] that completes when the deletion is done. |
| 111 */ | 129 */ |
| 112 Future<Directory> deleteDir(dir) { | 130 Future<Directory> deleteDir(dir) { |
| 131 // TODO(rnystrom): Hack! Temporary! Right now, dart:io's Directory delete |
| 132 // method can't handle directories with symlinks, which is exactly what pub |
| 133 // creates and deletes. Instead, we'll just shell out to 'rm'. Remove this |
| 134 // when dartbug.com/2646 is fixed. |
| 135 dir = _getDirectory(dir); |
| 136 |
| 137 // Sanity check! |
| 138 if (dir.path == '/' || |
| 139 dir.path == '.' || |
| 140 dir.path == '..' || |
| 141 dir.path == '~' || |
| 142 dir.path == '*') throw "(O.o) I don't think you want to do that!"; |
| 143 |
| 144 return runProcess('rm', ['-rf', dir.path]).transform((result) => dir); |
| 145 // End hack! |
| 146 |
| 147 // Real code: |
| 148 /* |
| 113 final completer = new Completer<Directory>(); | 149 final completer = new Completer<Directory>(); |
| 114 dir = _getDirectory(dir); | 150 dir = _getDirectory(dir); |
| 115 dir.onError = (error) => completer.completeException(error); | 151 dir.onError = (error) => completer.completeException(error); |
| 116 dir.deleteRecursively(() => completer.complete(dir)); | 152 dir.deleteRecursively(() => completer.complete(dir)); |
| 117 | 153 |
| 118 return completer.future; | 154 return completer.future; |
| 155 */ |
| 119 } | 156 } |
| 120 | 157 |
| 121 /** | 158 /** |
| 122 * Asynchronously lists the contents of [dir], which can be a [String] directory | 159 * Asynchronously lists the contents of [dir], which can be a [String] directory |
| 123 * path or a [Directory]. If [recursive] is `true`, lists subdirectory contents | 160 * path or a [Directory]. If [recursive] is `true`, lists subdirectory contents |
| 124 * (defaults to `false`). If [includeSpecialFiles] is `true`, includes | 161 * (defaults to `false`). If [includeSpecialFiles] is `true`, includes |
| 125 * hidden `.DS_Store` files (defaults to `false`, other hidden files may be | 162 * hidden `.DS_Store` files (defaults to `false`, other hidden files may be |
| 126 * omitted later). | 163 * omitted later). |
| 127 */ | 164 */ |
| 128 Future<List<String>> listDir(dir, | 165 Future<List<String>> listDir(dir, |
| (...skipping 17 matching lines...) Expand all Loading... |
| 146 } | 183 } |
| 147 contents.add(file); | 184 contents.add(file); |
| 148 }; | 185 }; |
| 149 | 186 |
| 150 dir.list(recursive: recursive); | 187 dir.list(recursive: recursive); |
| 151 | 188 |
| 152 return completer.future; | 189 return completer.future; |
| 153 } | 190 } |
| 154 | 191 |
| 155 /** | 192 /** |
| 193 * Asynchronously determines if [dir], which can be a [String] directory path |
| 194 * or a [Directory], exists on the file system. Returns a [Future] that |
| 195 * completes with the result. |
| 196 */ |
| 197 Future<bool> dirExists(dir) { |
| 198 final completer = new Completer<bool>(); |
| 199 |
| 200 dir = _getDirectory(dir); |
| 201 dir.onError = (error) => completer.completeException(error); |
| 202 dir.exists((exists) => completer.complete(exists)); |
| 203 |
| 204 return completer.future; |
| 205 } |
| 206 |
| 207 /** |
| 208 * "Cleans" [dir]. If that directory already exists, it will be deleted. Then a |
| 209 * new empty directory will be created. Returns a [Future] that completes when |
| 210 * the new clean directory is created. |
| 211 */ |
| 212 Future<Directory> cleanDir(dir) { |
| 213 return dirExists(dir).chain((exists) { |
| 214 if (exists) { |
| 215 // Delete it first. |
| 216 return deleteDir(dir).chain((_) => createDir(dir)); |
| 217 } else { |
| 218 // Just create it. |
| 219 return createDir(dir); |
| 220 } |
| 221 }); |
| 222 } |
| 223 |
| 224 /** |
| 225 * Creates a new symlink that creates an alias from [from] to [to], both of |
| 226 * which can be a [String], [File], or [Directory]. Returns a [Future] which |
| 227 * completes to the symlink file (i.e. [to]). |
| 228 */ |
| 229 Future<File> createSymlink(from, to) { |
| 230 // TODO(rnystrom): What should this do on Windows? |
| 231 from = _getPath(from); |
| 232 to = _getPath(to); |
| 233 |
| 234 return runProcess('ln', ['-s', from, to]).transform((result) { |
| 235 // TODO(rnystrom): Check exit code and output? |
| 236 return new File(to); |
| 237 }); |
| 238 } |
| 239 |
| 240 /** |
| 241 * Given [entry] which may be a [String], [File], or [Directory] relative to |
| 242 * the current working directory, returns its full canonicalized path. |
| 243 */ |
| 244 // TODO(rnystrom): Should this be async? |
| 245 String getFullPath(entry) => new File(_getPath(entry)).fullPathSync(); |
| 246 |
| 247 /** |
| 156 * Spawns and runs the process located at [executable], passing in [args]. | 248 * Spawns and runs the process located at [executable], passing in [args]. |
| 157 * Returns a [Future] that will complete the results of the process after it | 249 * Returns a [Future] that will complete the results of the process after it |
| 158 * has ended. | 250 * has ended. |
| 159 */ | 251 */ |
| 160 Future<ProcessResult> runProcess(String executable, List<String> args) { | 252 Future<ProcessResult> runProcess(String executable, List<String> args, |
| 253 [String workingDir]) { |
| 161 int exitCode; | 254 int exitCode; |
| 162 | 255 |
| 163 final process = new Process.start(executable, args); | 256 final options = new ProcessOptions(); |
| 257 if (workingDir != null) options.workingDirectory = workingDir; |
| 258 |
| 259 final process = new Process.start(executable, args, options); |
| 164 | 260 |
| 165 final outStream = new StringInputStream(process.stdout); | 261 final outStream = new StringInputStream(process.stdout); |
| 166 final processStdout = <String>[]; | 262 final processStdout = <String>[]; |
| 167 | 263 |
| 168 final errStream = new StringInputStream(process.stderr); | 264 final errStream = new StringInputStream(process.stderr); |
| 169 final processStderr = <String>[]; | 265 final processStderr = <String>[]; |
| 170 | 266 |
| 171 final completer = new Completer<ProcessResult>(); | 267 final completer = new Completer<ProcessResult>(); |
| 172 | 268 |
| 173 checkComplete() { | 269 checkComplete() { |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 222 } | 318 } |
| 223 | 319 |
| 224 /** | 320 /** |
| 225 * Gets a [Directory] for [entry], which can either already be one, or be a | 321 * Gets a [Directory] for [entry], which can either already be one, or be a |
| 226 * [String]. | 322 * [String]. |
| 227 */ | 323 */ |
| 228 Directory _getDirectory(entry) { | 324 Directory _getDirectory(entry) { |
| 229 if (entry is Directory) return entry; | 325 if (entry is Directory) return entry; |
| 230 return new Directory(entry); | 326 return new Directory(entry); |
| 231 } | 327 } |
| OLD | NEW |