1
- import { spawnSync } from 'child_process' ;
1
+ import { spawnSync , SpawnSyncReturns } from 'child_process' ;
2
2
3
3
/**
4
4
* Class that can be used to execute Git commands within a given project directory.
@@ -10,65 +10,89 @@ export class GitClient {
10
10
11
11
constructor ( public projectDir : string , public remoteGitUrl : string ) { }
12
12
13
+ /**
14
+ * Spawns a child process running Git. The "stderr" output is inherited and will be printed
15
+ * in case of errors. This makes it easier to debug failed commands.
16
+ */
17
+ private _spawnGitProcess ( args : string [ ] ) : SpawnSyncReturns < string > {
18
+ return spawnSync ( 'git' , args , {
19
+ cwd : this . projectDir ,
20
+ stdio : [ 'pipe' , 'pipe' , 'inherit' ] ,
21
+ encoding : 'utf8' ,
22
+ } ) ;
23
+ }
24
+
13
25
/** Gets the currently checked out branch for the project directory. */
14
26
getCurrentBranch ( ) {
15
- return spawnSync ( 'git' , [ 'symbolic-ref' , '--short' , 'HEAD' ] , { cwd : this . projectDir } )
16
- . stdout . toString ( ) . trim ( ) ;
27
+ return this . _spawnGitProcess ( [ 'symbolic-ref' , '--short' , 'HEAD' ] ) . stdout . trim ( ) ;
17
28
}
18
29
19
30
/** Gets the commit SHA for the specified remote repository branch. */
20
31
getRemoteCommitSha ( branchName : string ) : string {
21
- return spawnSync ( 'git' , [ 'ls-remote' , this . remoteGitUrl , '-h' , `refs/heads/${ branchName } ` ] ,
22
- { cwd : this . projectDir } ) . stdout . toString ( ) . split ( '\t' ) [ 0 ] . trim ( ) ;
32
+ return this . _spawnGitProcess ( [ 'ls-remote' , this . remoteGitUrl , '-h' ,
33
+ `refs/heads/${ branchName } ` ] )
34
+ . stdout . split ( '\t' ) [ 0 ] . trim ( ) ;
23
35
}
24
36
25
37
/** Gets the latest commit SHA for the specified git reference. */
26
38
getLocalCommitSha ( refName : string ) {
27
- return spawnSync ( 'git' , [ 'rev-parse' , refName ] , { cwd : this . projectDir } )
28
- . stdout . toString ( ) . trim ( ) ;
39
+ return this . _spawnGitProcess ( [ 'rev-parse' , refName ] ) . stdout . trim ( ) ;
29
40
}
30
41
31
42
/** Gets whether the current Git repository has uncommitted changes. */
32
43
hasUncommittedChanges ( ) : boolean {
33
- return spawnSync ( 'git' , [ 'diff-index' , '--quiet' , 'HEAD' ] , { cwd : this . projectDir } ) . status !== 0 ;
44
+ return this . _spawnGitProcess ( [ 'diff-index' , '--quiet' , 'HEAD' ] ) . status !== 0 ;
34
45
}
35
46
36
47
/** Checks out an existing branch with the specified name. */
37
48
checkoutBranch ( branchName : string ) : boolean {
38
- return spawnSync ( 'git' , [ 'checkout' , branchName ] , { cwd : this . projectDir } ) . status === 0 ;
49
+ return this . _spawnGitProcess ( [ 'checkout' , branchName ] ) . status === 0 ;
39
50
}
40
51
41
52
/** Creates a new branch which is based on the previous active branch. */
42
53
checkoutNewBranch ( branchName : string ) : boolean {
43
- return spawnSync ( 'git' , [ 'checkout' , '-b' , branchName ] , { cwd : this . projectDir } ) . status === 0 ;
54
+ return this . _spawnGitProcess ( [ 'checkout' , '-b' , branchName ] ) . status === 0 ;
44
55
}
45
56
46
57
/** Stages all changes by running `git add -A`. */
47
58
stageAllChanges ( ) : boolean {
48
- return spawnSync ( 'git' , [ 'add' , '-A' ] , { cwd : this . projectDir } ) . status === 0 ;
59
+ return this . _spawnGitProcess ( [ 'add' , '-A' ] ) . status === 0 ;
49
60
}
50
61
51
62
/** Creates a new commit within the current branch with the given commit message. */
52
63
createNewCommit ( message : string ) : boolean {
53
- return spawnSync ( 'git' , [ 'commit' , '-m' , message ] , { cwd : this . projectDir } ) . status === 0 ;
64
+ return this . _spawnGitProcess ( [ 'commit' , '-m' , message ] ) . status === 0 ;
54
65
}
55
66
56
67
/** Gets the title of a specified commit reference. */
57
68
getCommitTitle ( commitRef : string ) : string {
58
- return spawnSync ( 'git' , [ 'log' , '-n1' , '--format' , '%s' , commitRef ] , { cwd : this . projectDir } )
59
- . stdout . toString ( ) . trim ( ) ;
69
+ return this . _spawnGitProcess ( [ 'log' , '-n1' , '--format="%s"' , commitRef ] ) . stdout . trim ( ) ;
60
70
}
61
71
62
72
/** Creates a tag for the specified commit reference. */
63
73
createTag ( commitRef : string , tagName : string , message : string ) : boolean {
64
- return spawnSync ( 'git' , [ 'tag' , tagName , '-m' , message ] , { cwd : this . projectDir } ) . status === 0 ;
74
+ return this . _spawnGitProcess ( [ 'tag' , tagName , '-m' , message ] ) . status === 0 ;
75
+ }
76
+
77
+ /** Checks whether the specified tag exists locally. */
78
+ hasLocalTag ( tagName : string ) {
79
+ return this . _spawnGitProcess ( [ 'rev-parse' , `refs/tags/${ tagName } ` ] ) . status === 0 ;
80
+ }
81
+
82
+ /** Gets the Git SHA of the specified local tag. */
83
+ getShaOfLocalTag ( tagName : string ) {
84
+ return this . _spawnGitProcess ( [ 'rev-parse' , `refs/tags/${ tagName } ` ] ) . stdout . trim ( ) ;
85
+ }
86
+
87
+ /** Gets the Git SHA of the specified remote tag. */
88
+ getShaOfRemoteTag ( tagName : string ) : string {
89
+ return this . _spawnGitProcess ( [ 'ls-remote' , this . remoteGitUrl , '-t' , `refs/tags/${ tagName } ` ] )
90
+ . stdout . split ( '\t' ) [ 0 ] . trim ( ) ;
65
91
}
66
92
67
93
/** Pushes the specified tag to the remote git repository. */
68
94
pushTagToRemote ( tagName : string ) : boolean {
69
- return spawnSync ( 'git' , [ 'push' , this . remoteGitUrl , `refs/tags/${ tagName } ` ] , {
70
- cwd : this . projectDir
71
- } ) . status === 0 ;
95
+ return this . _spawnGitProcess ( [ 'push' , this . remoteGitUrl , `refs/tags/${ tagName } ` ] ) . status === 0 ;
72
96
}
73
97
}
74
98
0 commit comments