-
-
Notifications
You must be signed in to change notification settings - Fork 328
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix gix_path::env::login_shell()
by removing it
#1758
Changes from all commits
51bbb86
73ee27a
75d689f
0737c41
5400320
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
use std::ffi::OsString; | ||
use std::ffi::{OsStr, OsString}; | ||
use std::path::{Path, PathBuf}; | ||
|
||
use bstr::{BString, ByteSlice}; | ||
|
@@ -28,21 +28,25 @@ pub fn installation_config_prefix() -> Option<&'static Path> { | |
installation_config().map(git::config_to_base_path) | ||
} | ||
|
||
/// Return the shell that Git would prefer as login shell, the shell to execute Git commands from. | ||
/// Return the shell that Git would use, the shell to execute commands from. | ||
/// | ||
/// On Windows, this is the `bash.exe` bundled with it, and on Unix it's the shell specified by `SHELL`, | ||
/// or `None` if it is truly unspecified. | ||
pub fn login_shell() -> Option<&'static Path> { | ||
static PATH: Lazy<Option<PathBuf>> = Lazy::new(|| { | ||
/// On Windows, this is the full path to `sh.exe` bundled with Git, and on | ||
/// Unix it's `/bin/sh` as posix compatible shell. | ||
/// If the bundled shell on Windows cannot be found, `sh` is returned as the name of a shell | ||
/// as it could possibly be found in `PATH`. | ||
/// Note that the returned path might not be a path on disk. | ||
pub fn shell() -> &'static OsStr { | ||
static PATH: Lazy<OsString> = Lazy::new(|| { | ||
if cfg!(windows) { | ||
installation_config_prefix() | ||
.and_then(|p| p.parent()) | ||
.map(|p| p.join("usr").join("bin").join("bash.exe")) | ||
core_dir() | ||
.and_then(|p| p.ancestors().nth(3)) // Skip something like mingw64/libexec/git-core. | ||
.map(|p| p.join("usr").join("bin").join("sh.exe")) | ||
.map_or_else(|| OsString::from("sh"), Into::into) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In addition to this The My guess is that the distinction is similarly shim-related for the shells, though maybe the advantages and disadvantages that arise from using a shim versus the target executable are different for
I point this out in case you know you wish to use one over the other. I do not know which is better, nor do I have a guess. I've listed this in #1761 so it is not forgotten and to remind me to look into it in the future. This is definitely not a blocker for the PR. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Generally I'd like the With that said, I didn't find the shim last time I looked, because I tested on a VM that just has the full-blown git SDK for Windows, which doesn't seem to have it. The normal Git installation does have the shim though, but it's apparently not the most portable assumption to make about the Git installation. Speaking of portable, I have never tested with the 'portable' version of the Git installer, if there is one. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Thanks--in #1761 I had forgotten about how the Git for Windows SDK is another distinctive environment, which is really a different kind of Git for Windows installation, that should be tested specifically. I've added it to the list in #1761 for further research. It might be something that be treated the same as an upstream MSYS2 with
It sounds like
Yes, the downloads page lists a Portable ("thumbdrive edition") download. Although it's been ages since I've used that directly, it is also used by other packagers, including the Scoop package, which is how I install Git for Windows, except when I am doing it differently to test something else. So I think the portable version is covered already. I've added it to the list in #1761. I put a check mark on it, which can be removed if someone finds I am missing something here. One subtlety is that Scoop (and other package managers such as Chocolatey) provide their own shims. However, we are not attempting to use those shims, and they are in addition to what one gets with a standard full Git for Windows installation. (They point at Git for Windows's own shims.) To be clear, we very well may be running those shims--in a Scoop installation, the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I would have loved to provide that information but just yesterday that VM demolished itself after a Windows update and is inoperable. During the weekend I plan to restore it from backup, so I could help here if still useful.
Maybe the Shim could be a fallback if it turns out to be more portable, i.e. each or most of the Git packages one can use on Windows have it under that particular path, like
I agree. Expressing the above differently I could also say that I am happy with finding the actual file locations like we do now, but also think it might be simpler to rely on shims more if these paths are more consistent across the various installation methods. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
That must be annoying--good luck!
Currently, for If the I've been meaning, and will eventually manage, to update that. Alternatively, if we use the Git for Windows I'm not sure about Chocolatey, and also I haven't recently researched what other package managers besides Whether this makes sense to do probably depends on why we would be doing it. But it seems to me that it is not justified to do it if the reason is to be more likely to find |
||
} else { | ||
std::env::var_os("SHELL").map(PathBuf::from) | ||
"/bin/sh".into() | ||
} | ||
}); | ||
PATH.as_deref() | ||
PATH.as_ref() | ||
} | ||
|
||
/// Return the name of the Git executable to invoke it. | ||
|
@@ -102,6 +106,36 @@ pub fn xdg_config(file: &str, env_var: &mut dyn FnMut(&str) -> Option<OsString>) | |
}) | ||
} | ||
|
||
static GIT_CORE_DIR: Lazy<Option<PathBuf>> = Lazy::new(|| { | ||
let mut cmd = std::process::Command::new(exe_invocation()); | ||
|
||
#[cfg(windows)] | ||
{ | ||
use std::os::windows::process::CommandExt; | ||
const CREATE_NO_WINDOW: u32 = 0x08000000; | ||
cmd.creation_flags(CREATE_NO_WINDOW); | ||
} | ||
let output = cmd.arg("--exec-path").output().ok()?; | ||
|
||
if !output.status.success() { | ||
return None; | ||
} | ||
|
||
BString::new(output.stdout) | ||
.strip_suffix(b"\n")? | ||
.to_path() | ||
.ok()? | ||
.to_owned() | ||
.into() | ||
}); | ||
|
||
/// Return the directory obtained by calling `git --exec-path`. | ||
/// | ||
/// Returns `None` if Git could not be found or if it returned an error. | ||
pub fn core_dir() -> Option<&'static Path> { | ||
GIT_CORE_DIR.as_deref() | ||
} | ||
|
||
/// Returns the platform dependent system prefix or `None` if it cannot be found (right now only on windows). | ||
/// | ||
/// ### Performance | ||
|
@@ -125,22 +159,7 @@ pub fn system_prefix() -> Option<&'static Path> { | |
} | ||
} | ||
|
||
let mut cmd = std::process::Command::new(exe_invocation()); | ||
#[cfg(windows)] | ||
{ | ||
use std::os::windows::process::CommandExt; | ||
const CREATE_NO_WINDOW: u32 = 0x08000000; | ||
cmd.creation_flags(CREATE_NO_WINDOW); | ||
} | ||
cmd.arg("--exec-path").stderr(std::process::Stdio::null()); | ||
gix_trace::debug!(cmd = ?cmd, "invoking git to get system prefix/exec path"); | ||
let path = cmd.output().ok()?.stdout; | ||
let path = BString::new(path) | ||
.trim_with(|b| b.is_ascii_whitespace()) | ||
.to_path() | ||
.ok()? | ||
.to_owned(); | ||
|
||
let path = GIT_CORE_DIR.as_deref()?; | ||
let one_past_prefix = path.components().enumerate().find_map(|(idx, c)| { | ||
matches!(c,std::path::Component::Normal(name) if name.to_str() == Some("libexec")).then_some(idx) | ||
})?; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For executables on Windows, we have usually been searching for them with names that end in
.exe
. It generally works either way. I would not expect a usablesh
implementation to be found that does not end in.exe
, so I don't think we would be losing anything by returningsh.exe
as the fallback on Windows, much as we usegit.exe
(rather thangit
) on Windows.I haven't made a diff suggestion for this because it should probably be decided together with the question of whether the code should be refactored to make the local static item
PATH
anOsString
rather than anOption<OsString>
. Also, this is definitely not a blocker for the PR!There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a great point and I have made the change.