fix(platform): in the Flatpak a pass's shell is bash
Flatpak sets SHELL to /bin/sh, the host's (zsh here) being no file of the Sdk's, and claude's Bash tool runs commands with bash or zsh. In the sandbox SHELL becomes /bin/bash unless it names a bash or zsh that is there. Found by the sandbox checks: a pass's environment had SHELL=/bin/sh. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
5dab4b49d5
commit
aaa0bb1059
3 changed files with 30 additions and 1 deletions
|
|
@ -65,7 +65,10 @@ namespace Crafter::Review::Platform {
|
||||||
|
|
||||||
void Init() {
|
void Init() {
|
||||||
CurrentModeValue = fs::exists(PathsValue().flatpakInfo) ? Mode::Sandbox : Mode::Native;
|
CurrentModeValue = fs::exists(PathsValue().flatpakInfo) ? Mode::Sandbox : Mode::Native;
|
||||||
if (CurrentModeValue == Mode::Sandbox) RestoreHostXdg();
|
if (CurrentModeValue == Mode::Sandbox) {
|
||||||
|
RestoreHostXdg();
|
||||||
|
RestoreShell();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Mode CurrentMode() {
|
Mode CurrentMode() {
|
||||||
|
|
@ -128,6 +131,12 @@ namespace Crafter::Review::Platform {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RestoreShell() {
|
||||||
|
const std::string shell = GetEnv("SHELL").value_or("");
|
||||||
|
const bool usable = (shell.ends_with("/bash") || shell.ends_with("/zsh")) && access(shell.c_str(), X_OK) == 0;
|
||||||
|
if (!usable && access("/bin/bash", X_OK) == 0) setenv("SHELL", "/bin/bash", 1);
|
||||||
|
}
|
||||||
|
|
||||||
fs::path SelfExe() {
|
fs::path SelfExe() {
|
||||||
std::error_code error;
|
std::error_code error;
|
||||||
const fs::path exe = fs::read_symlink("/proc/self/exe", error);
|
const fs::path exe = fs::read_symlink("/proc/self/exe", error);
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,11 @@ export namespace Crafter::Review::Platform {
|
||||||
// $HOME), so git reads ~/.config/git/config, Playwright finds
|
// $HOME), so git reads ~/.config/git/config, Playwright finds
|
||||||
// ~/.cache/ms-playwright, and claude and npx behave as on the host.
|
// ~/.cache/ms-playwright, and claude and npx behave as on the host.
|
||||||
void RestoreHostXdg();
|
void RestoreHostXdg();
|
||||||
|
// Flatpak sets SHELL to /bin/sh, the host's (zsh here) being no file of
|
||||||
|
// the Sdk's. claude's Bash tool runs commands with bash or zsh, and the
|
||||||
|
// Sdk has bash: SHELL becomes /bin/bash unless it already names a bash
|
||||||
|
// or zsh that is there.
|
||||||
|
void RestoreShell();
|
||||||
// The absolute path of the running binary (/proc/self/exe).
|
// The absolute path of the running binary (/proc/self/exe).
|
||||||
std::filesystem::path SelfExe();
|
std::filesystem::path SelfExe();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -205,6 +205,21 @@ int main() {
|
||||||
Check(Platform::GetEnv("XDG_CONFIG_HOME") == "/elsewhere/config", "a host XDG directory the host set comes back");
|
Check(Platform::GetEnv("XDG_CONFIG_HOME") == "/elsewhere/config", "a host XDG directory the host set comes back");
|
||||||
Check(Platform::GetEnv("XDG_CACHE_HOME") == Dyn::JoinPath(home, ".cache"), "one it left unset is the XDG default under $HOME");
|
Check(Platform::GetEnv("XDG_CACHE_HOME") == Dyn::JoinPath(home, ".cache"), "one it left unset is the XDG default under $HOME");
|
||||||
Check(Platform::GetEnv("XDG_STATE_HOME") == Dyn::JoinPath(home, ".local/state"), "state too");
|
Check(Platform::GetEnv("XDG_STATE_HOME") == Dyn::JoinPath(home, ".local/state"), "state too");
|
||||||
|
// The shell: the sandbox's /bin/sh becomes bash; a bash or zsh that is
|
||||||
|
// there stays.
|
||||||
|
const std::optional<std::string> shell = Platform::GetEnv("SHELL");
|
||||||
|
setenv("SHELL", "/bin/sh", 1);
|
||||||
|
Platform::RestoreShell();
|
||||||
|
const std::optional<std::string> fromSh = Platform::GetEnv("SHELL");
|
||||||
|
setenv("SHELL", "/no/such/zsh", 1);
|
||||||
|
Platform::RestoreShell();
|
||||||
|
const std::optional<std::string> fromMissing = Platform::GetEnv("SHELL");
|
||||||
|
setenv("SHELL", "/bin/bash", 1);
|
||||||
|
Platform::RestoreShell();
|
||||||
|
const std::optional<std::string> fromBash = Platform::GetEnv("SHELL");
|
||||||
|
if (shell) setenv("SHELL", shell->c_str(), 1);
|
||||||
|
Check(!fs::exists("/bin/bash") || (fromSh == "/bin/bash" && fromMissing == "/bin/bash" && fromBash == "/bin/bash"),
|
||||||
|
"SHELL: /bin/sh and a shell that is not there become /bin/bash; bash stays");
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue