| 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 /// 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'; | 
| (...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 274       // out files in hidden directories. | 274       // out files in hidden directories. | 
| 275       if (recursive) { | 275       if (recursive) { | 
| 276         children.add(doList(new Directory(file), listedDirectories)); | 276         children.add(doList(new Directory(file), listedDirectories)); | 
| 277       } | 277       } | 
| 278     }; | 278     }; | 
| 279     lister.onFile = (file) { | 279     lister.onFile = (file) { | 
| 280       if (!includeHiddenFiles && basename(file).startsWith('.')) return; | 280       if (!includeHiddenFiles && basename(file).startsWith('.')) return; | 
| 281       contents.add(join(dir, basename(file))); | 281       contents.add(join(dir, basename(file))); | 
| 282     }; | 282     }; | 
| 283 | 283 | 
| 284     return completer.future.chain((contents) { | 284     return completer.future.then((contents) { | 
| 285       return Futures.wait(children).transform((childContents) { | 285       return Futures.wait(children).then((childContents) { | 
| 286         contents.addAll(flatten(childContents)); | 286         contents.addAll(flatten(childContents)); | 
| 287         return contents; | 287         return contents; | 
| 288       }); | 288       }); | 
| 289     }); | 289     }); | 
| 290   } | 290   } | 
| 291 | 291 | 
| 292   return doList(_getDirectory(dir), new Set<String>()); | 292   return doList(_getDirectory(dir), new Set<String>()); | 
| 293 } | 293 } | 
| 294 | 294 | 
| 295 /// Asynchronously determines if [dir], which can be a [String] directory path | 295 /// Asynchronously determines if [dir], which can be a [String] directory path | 
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 339 /// If that future completes with an error, it will slepp and then [callback] | 339 /// If that future completes with an error, it will slepp and then [callback] | 
| 340 /// will be invoked again to retry the operation. It will try a few times before | 340 /// will be invoked again to retry the operation. It will try a few times before | 
| 341 /// giving up. | 341 /// giving up. | 
| 342 Future _attemptRetryable(Future callback()) { | 342 Future _attemptRetryable(Future callback()) { | 
| 343   // Only do lame retry logic on Windows. | 343   // Only do lame retry logic on Windows. | 
| 344   if (Platform.operatingSystem != 'windows') return callback(); | 344   if (Platform.operatingSystem != 'windows') return callback(); | 
| 345 | 345 | 
| 346   var attempts = 0; | 346   var attempts = 0; | 
| 347   makeAttempt(_) { | 347   makeAttempt(_) { | 
| 348     attempts++; | 348     attempts++; | 
| 349     return callback().transformException((e) { | 349     return callback().catchError((e) { | 
| 350       if (attempts >= 10) { | 350       if (attempts >= 10) { | 
| 351         throw 'Could not complete operation. Gave up after $attempts attempts.'; | 351         throw 'Could not complete operation. Gave up after $attempts attempts.'; | 
| 352       } | 352       } | 
| 353 | 353 | 
| 354       // Wait a bit and try again. | 354       // Wait a bit and try again. | 
| 355       log.fine("Operation failed, retrying (attempt $attempts)."); | 355       log.fine("Operation failed, retrying (attempt $attempts)."); | 
| 356       return sleep(500).chain(makeAttempt); | 356       return sleep(500).then(makeAttempt); | 
| 357     }); | 357     }); | 
| 358   } | 358   } | 
| 359 | 359 | 
| 360   return makeAttempt(null); | 360   return makeAttempt(null); | 
| 361 } | 361 } | 
| 362 | 362 | 
| 363 /// Creates a new symlink that creates an alias from [from] to [to], both of | 363 /// Creates a new symlink that creates an alias from [from] to [to], both of | 
| 364 /// which can be a [String], [File], or [Directory]. Returns a [Future] which | 364 /// which can be a [String], [File], or [Directory]. Returns a [Future] which | 
| 365 /// completes to the symlink file (i.e. [to]). | 365 /// completes to the symlink file (i.e. [to]). | 
| 366 Future<File> createSymlink(from, to) { | 366 Future<File> createSymlink(from, to) { | 
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 441 | 441 | 
| 442 /// Displays a message and reads a yes/no confirmation from the user. Returns | 442 /// Displays a message and reads a yes/no confirmation from the user. Returns | 
| 443 /// a [Future] that completes to `true` if the user confirms or `false` if they | 443 /// a [Future] that completes to `true` if the user confirms or `false` if they | 
| 444 /// do not. | 444 /// do not. | 
| 445 /// | 445 /// | 
| 446 /// This will automatically append " (y/n)?" to the message, so [message] | 446 /// This will automatically append " (y/n)?" to the message, so [message] | 
| 447 /// should just be a fragment like, "Are you sure you want to proceed". | 447 /// should just be a fragment like, "Are you sure you want to proceed". | 
| 448 Future<bool> confirm(String message) { | 448 Future<bool> confirm(String message) { | 
| 449   log.fine('Showing confirm message: $message'); | 449   log.fine('Showing confirm message: $message'); | 
| 450   stdout.writeString("$message (y/n)? "); | 450   stdout.writeString("$message (y/n)? "); | 
| 451   return readLine().transform((line) => new RegExp(r"^[yY]").hasMatch(line)); | 451   return readLine().then((line) => new RegExp(r"^[yY]").hasMatch(line)); | 
| 452 } | 452 } | 
| 453 | 453 | 
| 454 /// Returns a single line read from a [StringInputStream]. By default, reads | 454 /// Returns a single line read from a [StringInputStream]. By default, reads | 
| 455 /// from stdin. | 455 /// from stdin. | 
| 456 /// | 456 /// | 
| 457 /// A [StringInputStream] passed to this should have no callbacks registered. | 457 /// A [StringInputStream] passed to this should have no callbacks registered. | 
| 458 Future<String> readLine([StringInputStream stream]) { | 458 Future<String> readLine([StringInputStream stream]) { | 
| 459   if (stream == null) stream = _stringStdin; | 459   if (stream == null) stream = _stringStdin; | 
| 460   if (stream.closed) return new Future.immediate(''); | 460   if (stream.closed) return new Future.immediate(''); | 
| 461   void removeCallbacks() { | 461   void removeCallbacks() { | 
| (...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 691 | 691 | 
| 692 /// Creates a temporary directory and passes its path to [fn]. Once the [Future] | 692 /// Creates a temporary directory and passes its path to [fn]. Once the [Future] | 
| 693 /// returned by [fn] completes, the temporary directory and all its contents | 693 /// returned by [fn] completes, the temporary directory and all its contents | 
| 694 /// will be deleted. | 694 /// will be deleted. | 
| 695 Future withTempDir(Future fn(String path)) { | 695 Future withTempDir(Future fn(String path)) { | 
| 696   var tempDir; | 696   var tempDir; | 
| 697   var future = createTempDir().then((dir) { | 697   var future = createTempDir().then((dir) { | 
| 698     tempDir = dir; | 698     tempDir = dir; | 
| 699     return fn(tempDir.path); | 699     return fn(tempDir.path); | 
| 700   }); | 700   }); | 
| 701   future.catchError((_) {}).then(_) { | 701   future.catchError((_) {}).then((_) { | 
| 702     log.fine('Cleaning up temp directory ${tempDir.path}.'); | 702     log.fine('Cleaning up temp directory ${tempDir.path}.'); | 
| 703     deleteDir(tempDir); | 703     deleteDir(tempDir); | 
| 704   }); | 704   }); | 
| 705   return future; | 705   return future; | 
| 706 } | 706 } | 
| 707 | 707 | 
| 708 /// Tests whether or not the git command-line app is available for use. | 708 /// Tests whether or not the git command-line app is available for use. | 
| 709 Future<bool> get isGitInstalled { | 709 Future<bool> get isGitInstalled { | 
| 710   if (_isGitInstalledCache != null) { | 710   if (_isGitInstalledCache != null) { | 
| 711     // TODO(rnystrom): The sleep is to pump the message queue. Can use | 711     // TODO(rnystrom): The sleep is to pump the message queue. Can use | 
| (...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 905 | 905 | 
| 906     // Note: This line of code gets munged by create_sdk.py to be the correct | 906     // Note: This line of code gets munged by create_sdk.py to be the correct | 
| 907     // relative path to 7zip in the SDK. | 907     // relative path to 7zip in the SDK. | 
| 908     var pathTo7zip = '../../third_party/7zip/7za.exe'; | 908     var pathTo7zip = '../../third_party/7zip/7za.exe'; | 
| 909     var command = relativeToPub(pathTo7zip); | 909     var command = relativeToPub(pathTo7zip); | 
| 910 | 910 | 
| 911     // We're passing 'baseDir' both as '-w' and setting it as the working | 911     // We're passing 'baseDir' both as '-w' and setting it as the working | 
| 912     // directory explicitly here intentionally. The former ensures that the | 912     // directory explicitly here intentionally. The former ensures that the | 
| 913     // files added to the archive have the correct relative path in the archive. | 913     // files added to the archive have the correct relative path in the archive. | 
| 914     // The latter enables relative paths in the "-i" args to be resolved. | 914     // The latter enables relative paths in the "-i" args to be resolved. | 
| 915     return runProcess(command, args, workingDir: baseDir).chain((_) { | 915     return runProcess(command, args, workingDir: baseDir).then((_) { | 
| 916       // GZIP it. 7zip doesn't support doing both as a single operation. Send | 916       // GZIP it. 7zip doesn't support doing both as a single operation. Send | 
| 917       // the output to stdout. | 917       // the output to stdout. | 
| 918       args = ["a", "unused", "-tgzip", "-so", tarFile]; | 918       args = ["a", "unused", "-tgzip", "-so", tarFile]; | 
| 919       return startProcess(command, args); | 919       return startProcess(command, args); | 
| 920     }).chain((process) { | 920     }).then((process) { | 
| 921       // Drain and discard 7zip's stderr. 7zip writes its normal output to | 921       // Drain and discard 7zip's stderr. 7zip writes its normal output to | 
| 922       // stderr. We don't want to show that since it's meaningless. | 922       // stderr. We don't want to show that since it's meaningless. | 
| 923       // TODO(rnystrom): Should log this and display it if an actual error | 923       // TODO(rnystrom): Should log this and display it if an actual error | 
| 924       // occurs. | 924       // occurs. | 
| 925       consumeInputStream(process.stderr); | 925       consumeInputStream(process.stderr); | 
| 926       return pipeInputToInput(process.stdout, stream); | 926       return pipeInputToInput(process.stdout, stream); | 
| 927     }); | 927     }); | 
| 928   }); | 928   }); | 
| 929   return stream; | 929   return stream; | 
| 930 } | 930 } | 
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 964 Directory _getDirectory(entry) { | 964 Directory _getDirectory(entry) { | 
| 965   if (entry is Directory) return entry; | 965   if (entry is Directory) return entry; | 
| 966   return new Directory(entry); | 966   return new Directory(entry); | 
| 967 } | 967 } | 
| 968 | 968 | 
| 969 /// Gets a [Uri] for [uri], which can either already be one, or be a [String]. | 969 /// Gets a [Uri] for [uri], which can either already be one, or be a [String]. | 
| 970 Uri _getUri(uri) { | 970 Uri _getUri(uri) { | 
| 971   if (uri is Uri) return uri; | 971   if (uri is Uri) return uri; | 
| 972   return new Uri.fromString(uri); | 972   return new Uri.fromString(uri); | 
| 973 } | 973 } | 
| OLD | NEW | 
|---|