| OLD | NEW |
| 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 | |
| 3 // BSD-style license that can be found in the LICENSE file. | |
| 4 | |
| 5 /// Helper functionality for invoking Git. | |
| 6 library pub.git; | 1 library pub.git; |
| 7 | |
| 8 import 'dart:async'; | 2 import 'dart:async'; |
| 9 import 'dart:io'; | 3 import 'dart:io'; |
| 10 | |
| 11 import 'package:stack_trace/stack_trace.dart'; | 4 import 'package:stack_trace/stack_trace.dart'; |
| 12 | |
| 13 import 'exceptions.dart'; | 5 import 'exceptions.dart'; |
| 14 import 'io.dart'; | 6 import 'io.dart'; |
| 15 import 'log.dart' as log; | 7 import 'log.dart' as log; |
| 16 import 'utils.dart'; | 8 import 'utils.dart'; |
| 17 | |
| 18 /// An exception thrown because a git command failed. | |
| 19 class GitException implements ApplicationException { | 9 class GitException implements ApplicationException { |
| 20 /// The arguments to the git command. | |
| 21 final List<String> args; | 10 final List<String> args; |
| 22 | |
| 23 /// The standard error emitted by git. | |
| 24 final String stderr; | 11 final String stderr; |
| 25 | |
| 26 String get message => 'Git error. Command: git ${args.join(" ")}\n$stderr'; | 12 String get message => 'Git error. Command: git ${args.join(" ")}\n$stderr'; |
| 27 | 13 GitException(Iterable<String> args, this.stderr) : args = args.toList(); |
| 28 GitException(Iterable<String> args, this.stderr) | |
| 29 : args = args.toList(); | |
| 30 | |
| 31 String toString() => message; | 14 String toString() => message; |
| 32 } | 15 } |
| 33 | |
| 34 /// Tests whether or not the git command-line app is available for use. | |
| 35 bool get isInstalled { | 16 bool get isInstalled { |
| 36 if (_isInstalledCache != null) return _isInstalledCache; | 17 if (_isInstalledCache != null) return _isInstalledCache; |
| 37 _isInstalledCache = _gitCommand != null; | 18 _isInstalledCache = _gitCommand != null; |
| 38 return _isInstalledCache; | 19 return _isInstalledCache; |
| 39 } | 20 } |
| 40 bool _isInstalledCache; | 21 bool _isInstalledCache; |
| 41 | 22 Future<List<String>> run(List<String> args, {String workingDir, Map<String, |
| 42 /// Run a git process with [args] from [workingDir]. | 23 String> environment}) { |
| 43 /// | |
| 44 /// Returns the stdout as a list of strings if it succeeded. Completes to an | |
| 45 /// exception if it failed. | |
| 46 Future<List<String>> run(List<String> args, | |
| 47 {String workingDir, Map<String, String> environment}) { | |
| 48 if (!isInstalled) { | 24 if (!isInstalled) { |
| 49 fail("Cannot find a Git executable.\n" | 25 fail( |
| 50 "Please ensure Git is correctly installed."); | 26 "Cannot find a Git executable.\n" "Please ensure Git is correctly instal
led."); |
| 51 } | 27 } |
| 52 | 28 return runProcess( |
| 53 return runProcess(_gitCommand, args, workingDir: workingDir, | 29 _gitCommand, |
| 30 args, |
| 31 workingDir: workingDir, |
| 54 environment: environment).then((result) { | 32 environment: environment).then((result) { |
| 55 if (!result.success) throw new GitException(args, result.stderr.join("\n")); | 33 if (!result.success) throw new GitException(args, result.stderr.join("\n")); |
| 56 return result.stdout; | 34 return result.stdout; |
| 57 }); | 35 }); |
| 58 } | 36 } |
| 59 | 37 List<String> runSync(List<String> args, {String workingDir, Map<String, |
| 60 /// Like [run], but synchronous. | 38 String> environment}) { |
| 61 List<String> runSync(List<String> args, {String workingDir, | |
| 62 Map<String, String> environment}) { | |
| 63 if (!isInstalled) { | 39 if (!isInstalled) { |
| 64 fail("Cannot find a Git executable.\n" | 40 fail( |
| 65 "Please ensure Git is correctly installed."); | 41 "Cannot find a Git executable.\n" "Please ensure Git is correctly instal
led."); |
| 66 } | 42 } |
| 67 | 43 var result = runProcessSync( |
| 68 var result = runProcessSync(_gitCommand, args, | 44 _gitCommand, |
| 45 args, |
| 69 workingDir: workingDir, | 46 workingDir: workingDir, |
| 70 environment: environment); | 47 environment: environment); |
| 71 if (!result.success) throw new GitException(args, result.stderr.join("\n")); | 48 if (!result.success) throw new GitException(args, result.stderr.join("\n")); |
| 72 return result.stdout; | 49 return result.stdout; |
| 73 } | 50 } |
| 74 | |
| 75 /// Returns the name of the git command-line app, or null if Git could not be | |
| 76 /// found on the user's PATH. | |
| 77 String get _gitCommand { | 51 String get _gitCommand { |
| 78 if (_commandCache != null) return _commandCache; | 52 if (_commandCache != null) return _commandCache; |
| 79 | |
| 80 var command; | 53 var command; |
| 81 if (_tryGitCommand("git")) { | 54 if (_tryGitCommand("git")) { |
| 82 _commandCache = "git"; | 55 _commandCache = "git"; |
| 83 } else if (_tryGitCommand("git.cmd")){ | 56 } else if (_tryGitCommand("git.cmd")) { |
| 84 _commandCache = "git.cmd"; | 57 _commandCache = "git.cmd"; |
| 85 } else { | 58 } else { |
| 86 return null; | 59 return null; |
| 87 } | 60 } |
| 88 | |
| 89 log.fine('Determined git command $command.'); | 61 log.fine('Determined git command $command.'); |
| 90 return _commandCache; | 62 return _commandCache; |
| 91 } | 63 } |
| 92 String _commandCache; | 64 String _commandCache; |
| 93 | |
| 94 /// Checks whether [command] is the Git command for this computer. | |
| 95 bool _tryGitCommand(String command) { | 65 bool _tryGitCommand(String command) { |
| 96 // If "git --version" prints something familiar, git is working. | |
| 97 try { | 66 try { |
| 98 var result = runProcessSync(command, ["--version"]); | 67 var result = runProcessSync(command, ["--version"]); |
| 99 var regexp = new RegExp("^git version"); | 68 var regexp = new RegExp("^git version"); |
| 100 return result.stdout.length == 1 && regexp.hasMatch(result.stdout.single); | 69 return result.stdout.length == 1 && regexp.hasMatch(result.stdout.single); |
| 101 } on ProcessException catch (error, stackTrace) { | 70 } on ProcessException catch (error, stackTrace) { |
| 102 var chain = new Chain.forTrace(stackTrace); | 71 var chain = new Chain.forTrace(stackTrace); |
| 103 // If the process failed, they probably don't have it. | |
| 104 log.message('Git command is not "$command": $error\n$chain'); | 72 log.message('Git command is not "$command": $error\n$chain'); |
| 105 return false; | 73 return false; |
| 106 } | 74 } |
| 107 } | 75 } |
| OLD | NEW |