1+ use std:: path:: PathBuf ;
12use std:: {
23 path:: Path ,
34 process:: { Command , Stdio } ,
45} ;
56
67use bstr:: { BStr , BString , ByteSlice } ;
78
9+ /// Other places to find Git in.
10+ #[ cfg( windows) ]
11+ pub ( super ) static ALTERNATIVE_LOCATIONS : & [ & str ] = & [
12+ "C:/Program Files/Git/mingw64/bin" ,
13+ "C:/Program Files (x86)/Git/mingw32/bin" ,
14+ ] ;
15+ #[ cfg( not( windows) ) ]
16+ pub ( super ) static ALTERNATIVE_LOCATIONS : & [ & str ] = & [ ] ;
17+
18+ #[ cfg( windows) ]
19+ pub ( super ) static EXE_NAME : & str = "git.exe" ;
20+ #[ cfg( not( windows) ) ]
21+ pub ( super ) static EXE_NAME : & str = "git" ;
22+
23+ /// Invoke the git executable in PATH to obtain the origin configuration, which is cached and returned.
24+ pub ( super ) static EXE_INFO : once_cell:: sync:: Lazy < Option < BString > > = once_cell:: sync:: Lazy :: new ( || {
25+ let git_cmd = |executable : PathBuf | {
26+ let mut cmd = Command :: new ( executable) ;
27+ cmd. args ( [ "config" , "-l" , "--show-origin" ] )
28+ . stdin ( Stdio :: null ( ) )
29+ . stderr ( Stdio :: null ( ) ) ;
30+ cmd
31+ } ;
32+ let mut cmd = git_cmd ( EXE_NAME . into ( ) ) ;
33+ gix_trace:: debug!( cmd = ?cmd, "invoking git for installation config path" ) ;
34+ let cmd_output = match cmd. output ( ) {
35+ Ok ( out) => out. stdout ,
36+ #[ cfg( windows) ]
37+ Err ( err) if err. kind ( ) == std:: io:: ErrorKind :: NotFound => {
38+ let executable = ALTERNATIVE_LOCATIONS . into_iter ( ) . find_map ( |prefix| {
39+ let candidate = Path :: new ( prefix) . join ( EXE_NAME ) ;
40+ candidate. is_file ( ) . then_some ( candidate)
41+ } ) ?;
42+ gix_trace:: debug!( cmd = ?cmd, "invoking git for installation config path in alternate location" ) ;
43+ git_cmd ( executable) . output ( ) . ok ( ) ?. stdout
44+ }
45+ Err ( _) => return None ,
46+ } ;
47+
48+ first_file_from_config_with_origin ( cmd_output. as_slice ( ) . into ( ) ) . map ( ToOwned :: to_owned)
49+ } ) ;
50+
851/// Returns the file that contains git configuration coming with the installation of the `git` file in the current `PATH`, or `None`
952/// if no `git` executable was found or there were other errors during execution.
10- pub ( crate ) fn install_config_path ( ) -> Option < & ' static BStr > {
53+ pub ( super ) fn install_config_path ( ) -> Option < & ' static BStr > {
1154 let _span = gix_trace:: detail!( "gix_path::git::install_config_path()" ) ;
1255 static PATH : once_cell:: sync:: Lazy < Option < BString > > = once_cell:: sync:: Lazy :: new ( || {
13- // Shortcut: in Msys shells this variable is set which allows to deduce the installation directory
56+ // Shortcut: in Msys shells this variable is set which allows to deduce the installation directory,
1457 // so we can save the `git` invocation.
1558 #[ cfg( windows) ]
1659 if let Some ( mut exec_path) = std:: env:: var_os ( "EXEPATH" ) . map ( std:: path:: PathBuf :: from) {
1760 exec_path. push ( "etc" ) ;
1861 exec_path. push ( "gitconfig" ) ;
1962 return crate :: os_string_into_bstring ( exec_path. into ( ) ) . ok ( ) ;
2063 }
21- let mut cmd = Command :: new ( if cfg ! ( windows) { "git.exe" } else { "git" } ) ;
22- cmd. args ( [ "config" , "-l" , "--show-origin" ] )
23- . stdin ( Stdio :: null ( ) )
24- . stderr ( Stdio :: null ( ) ) ;
25- gix_trace:: debug!( cmd = ?cmd, "invoking git for installation config path" ) ;
26- first_file_from_config_with_origin ( cmd. output ( ) . ok ( ) ?. stdout . as_slice ( ) . into ( ) ) . map ( ToOwned :: to_owned)
64+ EXE_INFO . clone ( )
2765 } ) ;
2866 PATH . as_ref ( ) . map ( AsRef :: as_ref)
2967}
@@ -35,7 +73,7 @@ fn first_file_from_config_with_origin(source: &BStr) -> Option<&BStr> {
3573}
3674
3775/// Given `config_path` as obtained from `install_config_path()`, return the path of the git installation base.
38- pub ( crate ) fn config_to_base_path ( config_path : & Path ) -> & Path {
76+ pub ( super ) fn config_to_base_path ( config_path : & Path ) -> & Path {
3977 config_path
4078 . parent ( )
4179 . expect ( "config file paths always have a file name to pop" )
0 commit comments