| 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'; |
| 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 'log.dart' as log; | 15 import 'log.dart' as log; |
| 16 import 'utils.dart'; | 16 import 'utils.dart'; |
| 17 | 17 |
| 18 bool _isGitInstalledCache; | |
| 19 | |
| 20 /// The cached Git command. | |
| 21 String _gitCommandCache; | |
| 22 | |
| 23 final NEWLINE_PATTERN = new RegExp("\r\n?|\n\r?"); | 18 final NEWLINE_PATTERN = new RegExp("\r\n?|\n\r?"); |
| 24 | 19 |
| 25 /// Joins a number of path string parts into a single path. Handles | 20 /// Joins a number of path string parts into a single path. Handles |
| 26 /// platform-specific path separators. Parts can be [String], [Directory], or | 21 /// platform-specific path separators. Parts can be [String], [Directory], or |
| 27 /// [File] objects. | 22 /// [File] objects. |
| 28 String join(part1, [part2, part3, part4, part5, part6, part7, part8]) { | 23 String join(part1, [part2, part3, part4, part5, part6, part7, part8]) { |
| 29 var parts = [part1, part2, part3, part4, part5, part6, part7, part8] | 24 var parts = [part1, part2, part3, part4, part5, part6, part7, part8] |
| 30 .mappedBy((part) => part == null ? null : _getPath(part)).toList(); | 25 .mappedBy((part) => part == null ? null : _getPath(part)).toList(); |
| 31 | 26 |
| 32 return path.join(parts[0], parts[1], parts[2], parts[3], parts[4], parts[5], | 27 return path.join(parts[0], parts[1], parts[2], parts[3], parts[4], parts[5], |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 177 /// exist, creates them. Returns a [Future] that completes once all the | 172 /// exist, creates them. Returns a [Future] that completes once all the |
| 178 /// directories are created. | 173 /// directories are created. |
| 179 Future<Directory> ensureDir(path) { | 174 Future<Directory> ensureDir(path) { |
| 180 path = _getPath(path); | 175 path = _getPath(path); |
| 181 log.fine("Ensuring directory $path exists."); | 176 log.fine("Ensuring directory $path exists."); |
| 182 if (path == '.') return new Future.immediate(new Directory('.')); | 177 if (path == '.') return new Future.immediate(new Directory('.')); |
| 183 | 178 |
| 184 return dirExists(path).then((exists) { | 179 return dirExists(path).then((exists) { |
| 185 if (exists) { | 180 if (exists) { |
| 186 log.fine("Directory $path already exists."); | 181 log.fine("Directory $path already exists."); |
| 187 return new Future.immediate(new Directory(path)); | 182 return new Directory(path); |
| 188 } | 183 } |
| 189 | 184 |
| 190 return ensureDir(dirname(path)).then((_) { | 185 return ensureDir(dirname(path)).then((_) { |
| 191 return createDir(path).catchError((asyncError) { | 186 return createDir(path).catchError((asyncError) { |
| 192 if (asyncError.error is! DirectoryIOException) throw asyncError; | 187 if (asyncError.error is! DirectoryIOException) throw asyncError; |
| 193 // Error 17 means the directory already exists (or 183 on Windows). | 188 // Error 17 means the directory already exists (or 183 on Windows). |
| 194 if (asyncError.error.osError.errorCode == 17 || | 189 if (asyncError.error.osError.errorCode == 17 || |
| 195 asyncError.error.osError.errorCode == 183) { | 190 asyncError.error.osError.errorCode == 183) { |
| 196 log.fine("Got 'already exists' error when creating directory."); | 191 log.fine("Got 'already exists' error when creating directory."); |
| 197 return _getDirectory(path); | 192 return _getDirectory(path); |
| (...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 404 if (exists) return createSymlink(from, to); | 399 if (exists) return createSymlink(from, to); |
| 405 | 400 |
| 406 // It's OK for the self link (i.e. the root package) to not have a lib | 401 // It's OK for the self link (i.e. the root package) to not have a lib |
| 407 // directory since it may just be a leaf application that only has | 402 // directory since it may just be a leaf application that only has |
| 408 // code in bin or web. | 403 // code in bin or web. |
| 409 if (!isSelfLink) { | 404 if (!isSelfLink) { |
| 410 log.warning('Warning: Package "$name" does not have a "lib" directory so ' | 405 log.warning('Warning: Package "$name" does not have a "lib" directory so ' |
| 411 'you will not be able to import any libraries from it.'); | 406 'you will not be able to import any libraries from it.'); |
| 412 } | 407 } |
| 413 | 408 |
| 414 return new Future.immediate(to); | 409 return to; |
| 415 }); | 410 }); |
| 416 } | 411 } |
| 417 | 412 |
| 418 /// Given [entry] which may be a [String], [File], or [Directory] relative to | 413 /// Given [entry] which may be a [String], [File], or [Directory] relative to |
| 419 /// the current working directory, returns its full canonicalized path. | 414 /// the current working directory, returns its full canonicalized path. |
| 420 String getFullPath(entry) => path.absolute(_getPath(entry)); | 415 String getFullPath(entry) => path.absolute(_getPath(entry)); |
| 421 | 416 |
| 422 /// Returns whether or not [entry] is an absolute path. | 417 /// Returns whether or not [entry] is an absolute path. |
| 423 bool isAbsolute(entry) => path.isAbsolute(_getPath(entry)); | 418 bool isAbsolute(entry) => path.isAbsolute(_getPath(entry)); |
| 424 | 419 |
| (...skipping 339 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 764 var tempDir; | 759 var tempDir; |
| 765 return createTempDir().then((dir) { | 760 return createTempDir().then((dir) { |
| 766 tempDir = dir; | 761 tempDir = dir; |
| 767 return fn(tempDir.path); | 762 return fn(tempDir.path); |
| 768 }).whenComplete(() { | 763 }).whenComplete(() { |
| 769 log.fine('Cleaning up temp directory ${tempDir.path}.'); | 764 log.fine('Cleaning up temp directory ${tempDir.path}.'); |
| 770 return deleteDir(tempDir); | 765 return deleteDir(tempDir); |
| 771 }); | 766 }); |
| 772 } | 767 } |
| 773 | 768 |
| 774 /// Tests whether or not the git command-line app is available for use. | |
| 775 Future<bool> get isGitInstalled { | |
| 776 if (_isGitInstalledCache != null) { | |
| 777 // TODO(rnystrom): The sleep is to pump the message queue. Can use | |
| 778 // Future.immediate() when #3356 is fixed. | |
| 779 return sleep(0).then((_) => _isGitInstalledCache); | |
| 780 } | |
| 781 | |
| 782 return _gitCommand.then((git) => git != null); | |
| 783 } | |
| 784 | |
| 785 /// Run a git process with [args] from [workingDir]. | |
| 786 Future<PubProcessResult> runGit(List<String> args, | |
| 787 {String workingDir, Map<String, String> environment}) { | |
| 788 return _gitCommand.then((git) => runProcess(git, args, | |
| 789 workingDir: workingDir, environment: environment)); | |
| 790 } | |
| 791 | |
| 792 /// Returns the name of the git command-line app, or null if Git could not be | |
| 793 /// found on the user's PATH. | |
| 794 Future<String> get _gitCommand { | |
| 795 // TODO(nweiz): Just use Future.immediate once issue 3356 is fixed. | |
| 796 if (_gitCommandCache != null) { | |
| 797 return sleep(0).then((_) => _gitCommandCache); | |
| 798 } | |
| 799 | |
| 800 return _tryGitCommand("git").then((success) { | |
| 801 if (success) return new Future.immediate("git"); | |
| 802 | |
| 803 // Git is sometimes installed on Windows as `git.cmd` | |
| 804 return _tryGitCommand("git.cmd").then((success) { | |
| 805 if (success) return "git.cmd"; | |
| 806 return null; | |
| 807 }); | |
| 808 }).then((command) { | |
| 809 _gitCommandCache = command; | |
| 810 return command; | |
| 811 }); | |
| 812 } | |
| 813 | |
| 814 /// Checks whether [command] is the Git command for this computer. | |
| 815 Future<bool> _tryGitCommand(String command) { | |
| 816 var completer = new Completer<bool>(); | |
| 817 | |
| 818 // If "git --version" prints something familiar, git is working. | |
| 819 var future = runProcess(command, ["--version"]); | |
| 820 | |
| 821 future.then((results) { | |
| 822 var regex = new RegExp("^git version"); | |
| 823 completer.complete(results.stdout.length == 1 && | |
| 824 regex.hasMatch(results.stdout[0])); | |
| 825 }).catchError((err) { | |
| 826 // If the process failed, they probably don't have it. | |
| 827 completer.complete(false); | |
| 828 }); | |
| 829 | |
| 830 return completer.future; | |
| 831 } | |
| 832 | |
| 833 /// Extracts a `.tar.gz` file from [stream] to [destination], which can be a | 769 /// Extracts a `.tar.gz` file from [stream] to [destination], which can be a |
| 834 /// directory or a path. Returns whether or not the extraction was successful. | 770 /// directory or a path. Returns whether or not the extraction was successful. |
| 835 Future<bool> extractTarGz(InputStream stream, destination) { | 771 Future<bool> extractTarGz(InputStream stream, destination) { |
| 836 destination = _getPath(destination); | 772 destination = _getPath(destination); |
| 837 | 773 |
| 838 log.fine("Extracting .tar.gz stream to $destination."); | 774 log.fine("Extracting .tar.gz stream to $destination."); |
| 839 | 775 |
| 840 if (Platform.operatingSystem == "windows") { | 776 if (Platform.operatingSystem == "windows") { |
| 841 return _extractTarGzWindows(stream, destination); | 777 return _extractTarGzWindows(stream, destination); |
| 842 } | 778 } |
| (...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1030 Directory _getDirectory(entry) { | 966 Directory _getDirectory(entry) { |
| 1031 if (entry is Directory) return entry; | 967 if (entry is Directory) return entry; |
| 1032 return new Directory(entry); | 968 return new Directory(entry); |
| 1033 } | 969 } |
| 1034 | 970 |
| 1035 /// Gets a [Uri] for [uri], which can either already be one, or be a [String]. | 971 /// Gets a [Uri] for [uri], which can either already be one, or be a [String]. |
| 1036 Uri _getUri(uri) { | 972 Uri _getUri(uri) { |
| 1037 if (uri is Uri) return uri; | 973 if (uri is Uri) return uri; |
| 1038 return new Uri.fromString(uri); | 974 return new Uri.fromString(uri); |
| 1039 } | 975 } |
| OLD | NEW |