Index: utils/pub/io.dart |
diff --git a/utils/pub/io.dart b/utils/pub/io.dart |
index 25e8d7fde85e7ef7c6236afdce4a0666bda86360..5fa13d97f89fc30859d378cc8bbe9dd0443caaa9 100644 |
--- a/utils/pub/io.dart |
+++ b/utils/pub/io.dart |
@@ -10,6 +10,7 @@ |
#import('dart:io'); |
#import('dart:isolate'); |
#import('dart:uri'); |
+#import('utils.dart'); |
/** Gets the current working directory. */ |
String get workingDir => new File('.').fullPathSync(); |
@@ -473,20 +474,42 @@ Future timeout(Future input, int milliSeconds, String message) { |
return completer.future; |
} |
-/** |
- * Tests whether or not the git command-line app is available for use. |
- */ |
-Future<bool> get isGitInstalled { |
- // TODO(rnystrom): We could cache this after the first check. We aren't right |
- // now because Future.immediate() will invoke its callback synchronously. |
- // That does bad things in cases where the caller expects futures to always |
- // be async. In particular, withGit() in the pub tests which calls |
- // expectAsync() will fail horribly if the test isn't actually async. |
+/// The cached Git command. |
+String __gitCommand; |
Bob Nystrom
2012/09/11 19:53:55
"_gitCommandCache"
|
+ |
+/// Tests whether or not the git command-line app is available for use. |
+Future<bool> get isGitInstalled => _gitCommand.transform((git) => git != null); |
+ |
+/// Run a git process with [args] from [workingDir]. |
+Future<PubProcessResult> runGit(List<String> args, [String workingDir]) => |
+ _gitCommand.chain((git) => runProcess(git, args, workingDir)); |
+ |
+/// Returns the name of the git command-line app, or null if Git could not be |
+/// found on the user's PATH. |
+Future<String> get _gitCommand { |
+ // TODO(nweiz): Just use Future.immediate once issue 3356 is fixed. |
+ if (__gitCommand != null) return sleep(0).transform((_) => __gitCommand); |
+ |
+ return _tryGitCommand("git").chain((success) { |
+ if (success) return new Future.immediate("git"); |
+ |
+ // Git is sometimes installed on Windows as `git.cmd` |
+ return _tryGitCommand("git.cmd").transform((success) { |
+ if (success) return "git.cmd"; |
+ return null; |
+ }); |
+ }).transform((command) { |
+ __gitCommand = command; |
+ return command; |
+ }); |
+} |
+/// Checks whether [command] is the Git command for this computer. |
+Future<bool> _tryGitCommand(String command) { |
var completer = new Completer<bool>(); |
// If "git --version" prints something familiar, git is working. |
- var future = runProcess("git", ["--version"]); |
+ var future = runProcess(command, ["--version"]); |
future.then((results) { |
var regex = new RegExp("^git version"); |