33
44import gitInfo = require( 'git-repo-info' ) ;
55import * as os from 'os' ;
6+ import * as path from 'path' ;
67import { Executable } from '@microsoft/node-core-library' ;
78
89import { Utilities } from '../utilities/Utilities' ;
@@ -18,6 +19,8 @@ interface IResultOrError<TResult> {
1819export class Git {
1920 private static _checkedGitPath : boolean = false ;
2021 private static _gitPath : string | undefined ;
22+ private static _checkedGitInfo : boolean = false ;
23+ private static _gitInfo : gitInfo . GitRepoInfo | undefined ;
2124
2225 private static _gitEmailResult : IResultOrError < string > | undefined = undefined ;
2326
@@ -42,14 +45,15 @@ export class Git {
4245
4346 /**
4447 * Returns true if the Git binary was found and the current path is under a Git working tree.
48+ * @param repoInfo - If provided, do the check based on this Git repo info. If not provided,
49+ * the result of `Git.getGitInfo()` is used.
4550 */
46- public static isPathUnderGitWorkingTree ( ) : boolean {
51+ public static isPathUnderGitWorkingTree ( repoInfo ?: gitInfo . GitRepoInfo ) : boolean {
4752 if ( Git . isGitPresent ( ) ) { // Do we even have a Git binary?
48- try {
49- return ! ! gitInfo ( ) . sha ;
50- } catch ( e ) {
51- return false ; // Unexpected, but possible if the .git directory is corrupted.
53+ if ( ! repoInfo ) {
54+ repoInfo = Git . getGitInfo ( ) ;
5255 }
56+ return ! ! ( repoInfo && repoInfo . sha ) ;
5357 } else {
5458 return false ;
5559 }
@@ -104,6 +108,40 @@ export class Git {
104108 return emailResult . result ;
105109 }
106110
111+ /**
112+ * Get the folder where Git hooks should go for the current working tree.
113+ * Returns undefined if the current path is not under a Git working tree.
114+ */
115+ public static getHooksFolder ( ) : string | undefined {
116+ const repoInfo : gitInfo . GitRepoInfo | undefined = Git . getGitInfo ( ) ;
117+ if ( repoInfo && repoInfo . worktreeGitDir ) {
118+ return path . join ( repoInfo . worktreeGitDir , 'hooks' ) ;
119+ }
120+ return undefined ;
121+ }
122+
123+ /**
124+ * Get information about the current Git working tree.
125+ * Returns undefined if the current path is not under a Git working tree.
126+ */
127+ public static getGitInfo ( ) : Readonly < gitInfo . GitRepoInfo > | undefined {
128+ if ( ! Git . _checkedGitInfo ) {
129+ let repoInfo : gitInfo . GitRepoInfo | undefined ;
130+ try {
131+ // gitInfo() shouldn't usually throw, but wrapping in a try/catch just in case
132+ repoInfo = gitInfo ( ) ;
133+ } catch ( ex ) {
134+ // if there's an error, assume we're not in a Git working tree
135+ }
136+
137+ if ( repoInfo && Git . isPathUnderGitWorkingTree ( repoInfo ) ) {
138+ Git . _gitInfo = repoInfo ;
139+ }
140+ Git . _checkedGitInfo = true ;
141+ }
142+ return Git . _gitInfo ;
143+ }
144+
107145 private static _tryGetGitEmail ( ) : IResultOrError < string > {
108146 if ( Git . _gitEmailResult === undefined ) {
109147 if ( ! Git . isGitPresent ( ) ) {
0 commit comments