1
+ use std:: path:: PathBuf ;
1
2
use std:: {
2
3
path:: Path ,
3
4
process:: { Command , Stdio } ,
4
5
} ;
5
6
6
7
use bstr:: { BStr , BString , ByteSlice } ;
7
8
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
+
8
51
/// Returns the file that contains git configuration coming with the installation of the `git` file in the current `PATH`, or `None`
9
52
/// 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 > {
11
54
let _span = gix_trace:: detail!( "gix_path::git::install_config_path()" ) ;
12
55
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,
14
57
// so we can save the `git` invocation.
15
58
#[ cfg( windows) ]
16
59
if let Some ( mut exec_path) = std:: env:: var_os ( "EXEPATH" ) . map ( std:: path:: PathBuf :: from) {
17
60
exec_path. push ( "etc" ) ;
18
61
exec_path. push ( "gitconfig" ) ;
19
62
return crate :: os_string_into_bstring ( exec_path. into ( ) ) . ok ( ) ;
20
63
}
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 ( )
27
65
} ) ;
28
66
PATH . as_ref ( ) . map ( AsRef :: as_ref)
29
67
}
@@ -35,7 +73,7 @@ fn first_file_from_config_with_origin(source: &BStr) -> Option<&BStr> {
35
73
}
36
74
37
75
/// 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 {
39
77
config_path
40
78
. parent ( )
41
79
. expect ( "config file paths always have a file name to pop" )
0 commit comments