@@ -6,6 +6,7 @@ use once_cell::sync::Lazy;
6
6
7
7
use crate :: env:: git:: EXE_NAME ;
8
8
9
+ mod auxiliary;
9
10
mod git;
10
11
11
12
/// Return the location at which installation specific git configuration file can be found, or `None`
@@ -28,84 +29,6 @@ pub fn installation_config_prefix() -> Option<&'static Path> {
28
29
installation_config ( ) . map ( git:: config_to_base_path)
29
30
}
30
31
31
- /// `usr`-like directory component names that MSYS2 may provide, other than for `/usr` itself.
32
- ///
33
- /// These are the values of the "Prefix" column of the "Environments" and "Legacy Environments"
34
- /// tables in the [MSYS2 Environments](https://www.msys2.org/docs/environments/) documentation,
35
- /// with the leading `/` separator removed, except that this does not list `usr` itself.
36
- ///
37
- /// On Windows, we prefer to use `sh` as provided by Git for Windows, when present. To find it, we
38
- /// run `git --exec-path` to get a path that is usually `<platform>/libexec/git-core` in the Git
39
- /// for Windows installation, where `<platform>` is something like `mingw64`. It is also acceptable
40
- /// to find `sh` in an environment not provided by Git for Windows, such as an independent MSYS2
41
- /// environment in which a `git` package has been installed. However, in an unusual installation,
42
- /// or if the user has set a custom value of `GIT_EXEC_PATH`, the output of `git --exec-path` may
43
- /// take a form other than `<platform>/libexec/git-core`, such that finding shell at a location
44
- /// like `../../../bin/sh.exe` relative to it should not be attempted. We lower the risk by
45
- /// checking that `<platform>` is a plausible value that is not likely to have any other meaning.
46
- ///
47
- /// This involves two tradeoffs. First, it may be reasonable to find `sh.exe` in an environment
48
- /// that is not MSYS2 at all, for which in principle the prefix could be different. But listing
49
- /// more prefixes or matching a broad pattern of platform-like strings might be too broad. So only
50
- /// prefixes that have been used in MSYS2 are considered.
51
- ///
52
- /// Second, we don't recognize `usr` itself here, even though is a plausible prefix. In MSYS2, it
53
- /// is the prefix for MSYS2 non-native programs, i.e. those that use `msys-2.0.dll`. But unlike the
54
- /// `<platform>` names we recognize, `usr` also has an effectively unbounded range of plausible
55
- /// meanings on non-Unix systems, which may occasionally relate to subdirectories whose contents
56
- /// are controlled by different user accounts.
57
- ///
58
- /// If we start with a `libexec/git-core` directory that we already use and trust, and it is in a
59
- /// directory with a name like `mingw64`, we infer that this `mingw64` directory has the expected
60
- /// meaning and that its `usr` sibling, if present, is acceptable to treat as though it is a
61
- /// first-level directory inside an MSYS2-like tree. So we are willing to traverse down to
62
- /// `usr/sh.exe` and attempt to use it. But if the `libexec/git-core` we use and trust is inside a
63
- /// directory named `usr`, that `usr` directory may still not have the meaning we expect of `usr`.
64
- ///
65
- /// The conditions for a privilege escalation attack or other serious malfunction seem unlikely. If
66
- /// research indicates the risk is low enough, `usr` may be added. But for now it is omitted.
67
- const MSYS_USR_VARIANTS : & [ & str ] = & [ "mingw64" , "mingw32" , "clangarm64" , "clang64" , "clang32" , "ucrt64" ] ;
68
-
69
- /// Shell path fragments to concatenate to the root of a Git for Windows or MSYS2 installation.
70
- ///
71
- /// These look like absolute Unix-style paths, but the leading `/` separators are present because
72
- /// they simplify forming paths like `C:/Program Files/Git` obtained by removing trailing
73
- /// components from the output of `git --exec-path`.
74
- const RAW_SH_EXE_PATH_SUFFIXES : & [ & str ] = & [
75
- "/bin/sh.exe" , // Usually a shim, which currently we prefer, if available.
76
- "/usr/bin/sh.exe" ,
77
- ] ;
78
-
79
- ///
80
- fn raw_join ( path : & Path , raw_suffix : & str ) -> OsString {
81
- let mut raw_path = OsString :: from ( path) ;
82
- raw_path. push ( raw_suffix) ;
83
- raw_path
84
- }
85
-
86
- ///
87
- fn find_sh_on_windows ( ) -> Option < OsString > {
88
- core_dir ( )
89
- . filter ( |core| core. is_absolute ( ) && core. ends_with ( "libexec/git-core" ) )
90
- . and_then ( |core| core. ancestors ( ) . nth ( 2 ) )
91
- . filter ( |prefix| {
92
- // Only use `libexec/git-core` from inside something `usr`-like, such as `mingw64`.
93
- MSYS_USR_VARIANTS . iter ( ) . any ( |name| prefix. ends_with ( name) )
94
- } )
95
- . and_then ( |prefix| prefix. parent ( ) )
96
- . into_iter ( )
97
- . flat_map ( |git_root| {
98
- // Enumerate locations where `sh.exe` usually is. To avoid breaking scripts that assume the
99
- // shell's own path contains no `\`, and so messages are more readable, append literally
100
- // with `/` separators. The path from `git --exec-path` already uses `/` separators (and no
101
- // trailing `/`) unless explicitly overridden to an unusual value via `GIT_EXEC_PATH`.
102
- RAW_SH_EXE_PATH_SUFFIXES
103
- . iter ( )
104
- . map ( |raw_suffix| raw_join ( git_root, raw_suffix) )
105
- } )
106
- . find ( |raw_path| Path :: new ( raw_path) . is_file ( ) )
107
- }
108
-
109
32
/// Return the shell that Git would use, the shell to execute commands from.
110
33
///
111
34
/// On Windows, this is the full path to `sh.exe` bundled with Git for Windows if we can find it.
@@ -117,7 +40,7 @@ fn find_sh_on_windows() -> Option<OsString> {
117
40
pub fn shell ( ) -> & ' static OsStr {
118
41
static PATH : Lazy < OsString > = Lazy :: new ( || {
119
42
if cfg ! ( windows) {
120
- find_sh_on_windows ( ) . unwrap_or_else ( || "sh.exe" . into ( ) )
43
+ auxiliary :: find_sh_on_windows ( ) . unwrap_or_else ( || "sh.exe" . into ( ) )
121
44
} else {
122
45
"/bin/sh" . into ( )
123
46
}
0 commit comments