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

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

Issue 10392023: Change dart:io to use Future for one-shot operations. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Adding stable test binaries Created 8 years, 7 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/compiler/build_helper.dart ('k') | utils/tests/pub/pub_test.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 /** 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');
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
84 return results[0] || results[1]; 84 return results[0] || results[1];
85 }); 85 });
86 } 86 }
87 87
88 /** 88 /**
89 * Asynchronously determines if [file], which can be a [String] file path or a 89 * Asynchronously determines if [file], which can be a [String] file path or a
90 * [File], exists on the file system. Returns a [Future] that completes with 90 * [File], exists on the file system. Returns a [Future] that completes with
91 * the result. 91 * the result.
92 */ 92 */
93 Future<bool> fileExists(file) { 93 Future<bool> fileExists(file) {
94 final completer = new Completer<bool>(); 94 return new File(_getPath(file)).exists();
95
96 file = new File(_getPath(file));
97 file.onError = (error) => completer.completeException(error);
98 file.exists((exists) => completer.complete(exists));
99
100 return completer.future;
101 } 95 }
102 96
103 /** 97 /**
104 * Reads the contents of the text file [file], which can either be a [String] or 98 * Reads the contents of the text file [file], which can either be a [String] or
105 * a [File]. 99 * a [File].
106 */ 100 */
107 Future<String> readTextFile(file) { 101 Future<String> readTextFile(file) {
108 file = new File(_getPath(file)); 102 return new File(_getPath(file)).readAsText(Encoding.UTF_8);
109 final completer = new Completer<String>();
110 file.onError = (error) => completer.completeException(error);
111 file.readAsText(Encoding.UTF_8, (text) => completer.complete(text));
112
113 return completer.future;
114 } 103 }
115 104
116 /** 105 /**
117 * Creates [file] (which can either be a [String] or a [File]), and writes 106 * Creates [file] (which can either be a [String] or a [File]), and writes
118 * [contents] to it. Completes when the file is written and closed. 107 * [contents] to it. Completes when the file is written and closed.
119 */ 108 */
120 Future<File> writeTextFile(file, String contents) { 109 Future<File> writeTextFile(file, String contents) {
121 file = new File(_getPath(file)); 110 file = new File(_getPath(file));
122 final completer = new Completer<File>(); 111 return file.open(FileMode.WRITE).chain((opened) {
123 file.onError = (error) => completer.completeException(error); 112 return opened.writeString(contents).chain((ignore) {
124 file.open(FileMode.WRITE, (opened) { 113 return opened.close().transform((ignore) => file);
125 opened.onError = (error) => completer.completeException(error); 114 });
126 opened.onNoPendingWrites = () {
127 opened.close(() => completer.complete(file));
128 };
129 opened.writeString(contents);
130 }); 115 });
131
132 return completer.future;
133 } 116 }
134 117
135 /** 118 /**
136 * Creates a directory [dir]. Returns a [Future] that completes when the 119 * Creates a directory [dir]. Returns a [Future] that completes when the
137 * directory is created. 120 * directory is created.
138 */ 121 */
139 Future<Directory> createDir(dir) { 122 Future<Directory> createDir(dir) {
140 final completer = new Completer<Directory>();
141 dir = _getDirectory(dir); 123 dir = _getDirectory(dir);
142 dir.onError = (error) => completer.completeException(error); 124 return dir.create();
143 dir.create(() => completer.complete(dir));
144
145 return completer.future;
146 } 125 }
147 126
148 /** 127 /**
149 * Ensures that [path] and all its parent directories exist. If they don't 128 * Ensures that [path] and all its parent directories exist. If they don't
150 * exist, creates them. Returns a [Future] that completes once all the 129 * exist, creates them. Returns a [Future] that completes once all the
151 * directories are created. 130 * directories are created.
152 */ 131 */
153 Future<Directory> ensureDir(path) { 132 Future<Directory> ensureDir(path) {
154 path = _getPath(path); 133 path = _getPath(path);
155 if (path == '.') return new Future.immediate(new Directory('.')); 134 if (path == '.') return new Future.immediate(new Directory('.'));
(...skipping 16 matching lines...) Expand all
172 return completer.future; 151 return completer.future;
173 }); 152 });
174 } 153 }
175 154
176 /** 155 /**
177 * Creates a temp directory whose name will be based on [dir] with a unique 156 * Creates a temp directory whose name will be based on [dir] with a unique
178 * suffix appended to it. Returns a [Future] that completes when the directory 157 * suffix appended to it. Returns a [Future] that completes when the directory
179 * is created. 158 * is created.
180 */ 159 */
181 Future<Directory> createTempDir(dir) { 160 Future<Directory> createTempDir(dir) {
182 final completer = new Completer<Directory>();
183 dir = _getDirectory(dir); 161 dir = _getDirectory(dir);
184 dir.onError = (error) => completer.completeException(error); 162 return dir.createTemp();
185 dir.createTemp(() => completer.complete(dir));
186
187 return completer.future;
188 } 163 }
189 164
190 /** 165 /**
191 * Asynchronously recursively deletes [dir], which can be a [String] or a 166 * Asynchronously recursively deletes [dir], which can be a [String] or a
192 * [Directory]. Returns a [Future] that completes when the deletion is done. 167 * [Directory]. Returns a [Future] that completes when the deletion is done.
193 */ 168 */
194 Future<Directory> deleteDir(dir) { 169 Future<Directory> deleteDir(dir) {
195 final completer = new Completer<Directory>();
196 dir = _getDirectory(dir); 170 dir = _getDirectory(dir);
197 dir.onError = (error) => completer.completeException(error); 171 return dir.deleteRecursively();
198 dir.deleteRecursively(() => completer.complete(dir));
199
200 return completer.future;
201 } 172 }
202 173
203 /** 174 /**
204 * Asynchronously lists the contents of [dir], which can be a [String] directory 175 * Asynchronously lists the contents of [dir], which can be a [String] directory
205 * path or a [Directory]. If [recursive] is `true`, lists subdirectory contents 176 * path or a [Directory]. If [recursive] is `true`, lists subdirectory contents
206 * (defaults to `false`). If [includeSpecialFiles] is `true`, includes 177 * (defaults to `false`). If [includeSpecialFiles] is `true`, includes
207 * hidden `.DS_Store` files (defaults to `false`, other hidden files may be 178 * hidden `.DS_Store` files (defaults to `false`, other hidden files may be
208 * omitted later). 179 * omitted later).
209 */ 180 */
210 Future<List<String>> listDir(dir, 181 Future<List<String>> listDir(dir,
211 [bool recursive = false, bool includeSpecialFiles = false]) { 182 [bool recursive = false, bool includeSpecialFiles = false]) {
212 final completer = new Completer<List<String>>(); 183 final completer = new Completer<List<String>>();
213 final contents = <String>[]; 184 final contents = <String>[];
214 185
215 dir = _getDirectory(dir); 186 dir = _getDirectory(dir);
187 var lister = dir.list(recursive: recursive);
216 188
217 dir.onDone = (done) { 189 lister.onDone = (done) {
218 // TODO(rnystrom): May need to sort here if it turns out onDir and onFile 190 // TODO(rnystrom): May need to sort here if it turns out onDir and onFile
219 // aren't guaranteed to be called in a certain order. So far, they seem to. 191 // aren't guaranteed to be called in a certain order. So far, they seem to.
220 if (done) completer.complete(contents); 192 if (done) completer.complete(contents);
221 }; 193 };
222 194
223 dir.onError = (error) => completer.completeException(error); 195 lister.onError = (error) => completer.completeException(error);
224 dir.onDir = (file) => contents.add(file); 196 lister.onDir = (file) => contents.add(file);
225 dir.onFile = (file) { 197 lister.onFile = (file) {
226 if (!includeSpecialFiles) { 198 if (!includeSpecialFiles) {
227 if (basename(file) == '.DS_Store') return; 199 if (basename(file) == '.DS_Store') return;
228 } 200 }
229 contents.add(file); 201 contents.add(file);
230 }; 202 };
231 203
232 dir.list(recursive: recursive);
233
234 return completer.future; 204 return completer.future;
235 } 205 }
236 206
237 /** 207 /**
238 * Asynchronously determines if [dir], which can be a [String] directory path 208 * Asynchronously determines if [dir], which can be a [String] directory path
239 * or a [Directory], exists on the file system. Returns a [Future] that 209 * or a [Directory], exists on the file system. Returns a [Future] that
240 * completes with the result. 210 * completes with the result.
241 */ 211 */
242 Future<bool> dirExists(dir) { 212 Future<bool> dirExists(dir) {
243 final completer = new Completer<bool>();
244
245 dir = _getDirectory(dir); 213 dir = _getDirectory(dir);
246 dir.onError = (error) => completer.completeException(error); 214 return dir.exists();
247 dir.exists((exists) => completer.complete(exists));
248
249 return completer.future;
250 } 215 }
251 216
252 /** 217 /**
253 * "Cleans" [dir]. If that directory already exists, it will be deleted. Then a 218 * "Cleans" [dir]. If that directory already exists, it will be deleted. Then a
254 * new empty directory will be created. Returns a [Future] that completes when 219 * new empty directory will be created. Returns a [Future] that completes when
255 * the new clean directory is created. 220 * the new clean directory is created.
256 */ 221 */
257 Future<Directory> cleanDir(dir) { 222 Future<Directory> cleanDir(dir) {
258 return dirExists(dir).chain((exists) { 223 return dirExists(dir).chain((exists) {
259 if (exists) { 224 if (exists) {
(...skipping 27 matching lines...) Expand all
287 * the current working directory, returns its full canonicalized path. 252 * the current working directory, returns its full canonicalized path.
288 */ 253 */
289 // TODO(rnystrom): Should this be async? 254 // TODO(rnystrom): Should this be async?
290 String getFullPath(entry) => new File(_getPath(entry)).fullPathSync(); 255 String getFullPath(entry) => new File(_getPath(entry)).fullPathSync();
291 256
292 /** 257 /**
293 * Spawns and runs the process located at [executable], passing in [args]. 258 * Spawns and runs the process located at [executable], passing in [args].
294 * Returns a [Future] that will complete the results of the process after it 259 * Returns a [Future] that will complete the results of the process after it
295 * has ended. 260 * has ended.
296 */ 261 */
297 Future<ProcessResult> runProcess(String executable, List<String> args, 262 Future<PubProcessResult> runProcess(String executable, List<String> args,
298 [String workingDir]) { 263 [String workingDir]) {
299 int exitCode; 264 int exitCode;
300 265
301 final options = new ProcessOptions(); 266 final options = new ProcessOptions();
302 if (workingDir != null) options.workingDirectory = workingDir; 267 if (workingDir != null) options.workingDirectory = workingDir;
303 268
304 final process = new Process.start(executable, args, options); 269 final process = Process.start(executable, args, options);
305 270
306 final outStream = new StringInputStream(process.stdout); 271 final outStream = new StringInputStream(process.stdout);
307 final processStdout = <String>[]; 272 final processStdout = <String>[];
308 273
309 final errStream = new StringInputStream(process.stderr); 274 final errStream = new StringInputStream(process.stderr);
310 final processStderr = <String>[]; 275 final processStderr = <String>[];
311 276
312 final completer = new Completer<ProcessResult>(); 277 final completer = new Completer<PubProcessResult>();
313 278
314 checkComplete() { 279 checkComplete() {
315 // Wait until the process is done and its output streams are closed. 280 // Wait until the process is done and its output streams are closed.
316 if (!outStream.closed) return; 281 if (!outStream.closed) return;
317 if (!errStream.closed) return; 282 if (!errStream.closed) return;
318 if (exitCode == null) return; 283 if (exitCode == null) return;
319 284
320 completer.complete(new ProcessResult( 285 completer.complete(new PubProcessResult(
321 processStdout, processStderr, exitCode)); 286 processStdout, processStderr, exitCode));
322 } 287 }
323 288
324 outStream.onLine = () => processStdout.add(outStream.readLine()); 289 outStream.onLine = () => processStdout.add(outStream.readLine());
325 outStream.onClosed = checkComplete; 290 outStream.onClosed = checkComplete;
326 outStream.onError = (error) => completer.completeException(error); 291 outStream.onError = (error) => completer.completeException(error);
327 292
328 errStream.onLine = () => processStderr.add(errStream.readLine()); 293 errStream.onLine = () => processStderr.add(errStream.readLine());
329 errStream.onClosed = checkComplete; 294 errStream.onClosed = checkComplete;
330 errStream.onError = (error) => completer.completeException(error); 295 errStream.onError = (error) => completer.completeException(error);
331 296
332 process.onExit = (actualExitCode) { 297 process.onExit = (actualExitCode) {
333 exitCode = actualExitCode; 298 exitCode = actualExitCode;
334 checkComplete(); 299 checkComplete();
335 }; 300 };
336 301
337 process.onError = (error) => completer.completeException(error); 302 process.onError = (error) => completer.completeException(error);
338 303
339 return completer.future; 304 return completer.future;
340 } 305 }
341 306
342 /** 307 /**
343 * Contains the results of invoking a [Process] and waiting for it to complete. 308 * Contains the results of invoking a [Process] and waiting for it to complete.
344 */ 309 */
345 class ProcessResult { 310 class PubProcessResult {
346 final List<String> stdout; 311 final List<String> stdout;
347 final List<String> stderr; 312 final List<String> stderr;
348 final int exitCode; 313 final int exitCode;
349 314
350 const ProcessResult(this.stdout, this.stderr, this.exitCode); 315 const PubProcessResult(this.stdout, this.stderr, this.exitCode);
351 } 316 }
352 317
353 /** 318 /**
354 * Gets the path string for [entry], which can either already be a path string, 319 * Gets the path string for [entry], which can either already be a path string,
355 * or be a [File] or [Directory]. Allows working generically with "file-like" 320 * or be a [File] or [Directory]. Allows working generically with "file-like"
356 * objects. 321 * objects.
357 */ 322 */
358 String _getPath(entry) { 323 String _getPath(entry) {
359 if (entry is String) return entry; 324 if (entry is String) return entry;
360 if (entry is File) return entry.name; 325 if (entry is File) return entry.name;
361 if (entry is Directory) return entry.path; 326 if (entry is Directory) return entry.path;
362 throw 'Entry $entry is not a supported type.'; 327 throw 'Entry $entry is not a supported type.';
363 } 328 }
364 329
365 /** 330 /**
366 * Gets a [Directory] for [entry], which can either already be one, or be a 331 * Gets a [Directory] for [entry], which can either already be one, or be a
367 * [String]. 332 * [String].
368 */ 333 */
369 Directory _getDirectory(entry) { 334 Directory _getDirectory(entry) {
370 if (entry is Directory) return entry; 335 if (entry is Directory) return entry;
371 return new Directory(entry); 336 return new Directory(entry);
372 } 337 }
OLDNEW
« no previous file with comments | « utils/compiler/build_helper.dart ('k') | utils/tests/pub/pub_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698