@@ -3,7 +3,7 @@ use rand::{distributions::Alphanumeric, Rng};
33use std:: io;
44use std:: io:: Write ;
55use std:: path:: PathBuf ;
6- use std:: process:: { Command , Output } ;
6+ use std:: process:: { Command , ExitStatus , Output } ;
77use thiserror:: Error ;
88
99use tempfile:: NamedTempFile ;
@@ -14,8 +14,8 @@ pub enum GitCommandError {
1414 IOError { value : io:: Error } ,
1515 #[ error( "Cannot change to UTF8 format" ) ]
1616 UTF8Error { value : std:: str:: Utf8Error } ,
17- #[ error( "status: {0:?}, stderr: {1:?}" , value . status, value . stderr) ]
18- GitError { value : Output } ,
17+ #[ error( "status: {0:?}, stderr: {1:?}" , status, stderr) ]
18+ GitError { status : ExitStatus , stderr : String } ,
1919 #[ error( "Invalid function call" ) ]
2020 InvalidFunctionCallError ,
2121 #[ error( "Empty list (level: {0:?}" , level) ]
@@ -28,6 +28,13 @@ impl From<std::io::Error> for GitCommandError {
2828 }
2929}
3030
31+ impl From < std:: string:: FromUtf8Error > for GitCommandError {
32+ fn from ( value : std:: string:: FromUtf8Error ) -> Self {
33+ let error = value. utf8_error ( ) ;
34+ GitCommandError :: UTF8Error { value : error }
35+ }
36+ }
37+
3138impl From < std:: str:: Utf8Error > for GitCommandError {
3239 fn from ( value : std:: str:: Utf8Error ) -> Self {
3340 GitCommandError :: UTF8Error { value }
@@ -62,7 +69,10 @@ impl GitHelper {
6269 . output ( ) ?;
6370
6471 if !output. status . success ( ) {
65- return Err ( GitCommandError :: GitError { value : output } ) ;
72+ return Err ( GitCommandError :: GitError {
73+ status : output. status ,
74+ stderr : String :: from_utf8 ( output. stderr ) ?,
75+ } ) ;
6676 }
6777
6878 let branch_name = std:: str:: from_utf8 ( output. stdout . as_slice ( ) ) ?
@@ -79,7 +89,10 @@ impl GitHelper {
7989 . output ( ) ?;
8090
8191 if !output. status . success ( ) {
82- return Err ( GitCommandError :: GitError { value : output } ) ;
92+ return Err ( GitCommandError :: GitError {
93+ status : output. status ,
94+ stderr : String :: from_utf8 ( output. stderr ) ?,
95+ } ) ;
8396 }
8497
8598 let diff_list: Vec < PathBuf > =
@@ -116,7 +129,10 @@ impl GitHelper {
116129 . output ( ) ?;
117130
118131 if !output. status . success ( ) {
119- return Err ( GitCommandError :: GitError { value : output } ) ;
132+ return Err ( GitCommandError :: GitError {
133+ status : output. status ,
134+ stderr : String :: from_utf8 ( output. stderr ) ?,
135+ } ) ;
120136 }
121137
122138 self . temp_branch_name = Some ( branch_name) ;
@@ -130,15 +146,21 @@ impl GitHelper {
130146 . output ( ) ?;
131147
132148 if !output. status . success ( ) {
133- return Err ( GitCommandError :: GitError { value : output } ) ;
149+ return Err ( GitCommandError :: GitError {
150+ status : output. status ,
151+ stderr : String :: from_utf8 ( output. stderr ) ?,
152+ } ) ;
134153 }
135154
136155 let output = Command :: new ( "git" )
137156 . args ( [ "branch" , "-d" , name. as_str ( ) ] )
138157 . output ( ) ?;
139158
140159 if !output. status . success ( ) {
141- return Err ( GitCommandError :: GitError { value : output } ) ;
160+ return Err ( GitCommandError :: GitError {
161+ status : output. status ,
162+ stderr : String :: from_utf8 ( output. stderr ) ?,
163+ } ) ;
142164 }
143165
144166 Ok ( output)
@@ -154,7 +176,10 @@ impl GitHelper {
154176 . output ( ) ?;
155177
156178 if !output. status . success ( ) {
157- return Err ( GitCommandError :: GitError { value : output } ) ;
179+ return Err ( GitCommandError :: GitError {
180+ status : output. status ,
181+ stderr : String :: from_utf8 ( output. stderr ) ?,
182+ } ) ;
158183 }
159184
160185 Ok ( output)
@@ -164,6 +189,13 @@ impl GitHelper {
164189 & self ,
165190 commits : & Vec < GitCommitCandidate > ,
166191 ) -> Result < Vec < Output > , GitCommandError > {
192+ let args = vec ! [ "rev-parse" , "--show-toplevel" ] ;
193+ let project_dir = PathBuf :: from (
194+ String :: from_utf8 ( Command :: new ( "git" ) . args ( args) . output ( ) ?. stdout ) ?
195+ . trim_end_matches ( "\r \n " )
196+ . trim_end_matches ( "\n " ) ,
197+ ) ;
198+
167199 let mut outputs = vec ! [ ] ;
168200
169201 for commit in commits {
@@ -195,10 +227,16 @@ impl GitHelper {
195227 spec_filepath,
196228 ] ;
197229
198- let output = Command :: new ( "git" ) . args ( args) . output ( ) ?;
230+ let output = Command :: new ( "git" )
231+ . current_dir ( project_dir. as_path ( ) )
232+ . args ( args)
233+ . output ( ) ?;
199234
200235 if !output. status . success ( ) {
201- return Err ( GitCommandError :: GitError { value : output } ) ;
236+ return Err ( GitCommandError :: GitError {
237+ status : output. status ,
238+ stderr : String :: from_utf8 ( output. stderr ) ?,
239+ } ) ;
202240 }
203241
204242 outputs. push ( output) ;
@@ -244,6 +282,10 @@ mod tests {
244282 println ! ( "{:?}" , helper. reset( ) ?) ;
245283 let msg = "test" . to_owned ( ) ;
246284 let commit_cands = vec ! [ GitCommitCandidate { msg, file_paths } ] ;
285+
286+ // Change to some directory not equal to the project root directory
287+ env:: set_current_dir ( temp_dir. path ( ) . join ( "dir_1" ) ) ?;
288+
247289 let outputs = helper. commit ( & commit_cands) ?;
248290 assert_eq ! ( outputs. len( ) , commit_cands. len( ) ) ;
249291 for output in outputs {
0 commit comments