fix: sanitize appimage git subprocess env

This commit is contained in:
lucaronin
2026-05-01 02:01:49 +02:00
parent 0987946cff
commit 568ada8992
6 changed files with 85 additions and 10 deletions

View File

@@ -57,13 +57,45 @@ const DEFAULT_GITIGNORE: &str = "# Tolaria app files (machine-specific, never co
*.swo\n";
fn git_command() -> Command {
crate::hidden_command("git")
let mut command = crate::hidden_command("git");
sanitize_linux_appimage_git_env(&mut command);
command
}
#[cfg(any(test, all(desktop, target_os = "linux")))]
const LINUX_APPIMAGE_GIT_ENV_REMOVALS: [&str; 3] =
["LD_LIBRARY_PATH", "LD_PRELOAD", "GIT_EXEC_PATH"];
#[cfg(all(desktop, target_os = "linux"))]
fn sanitize_linux_appimage_git_env(command: &mut Command) {
sanitize_linux_appimage_git_env_for_launch(command, linux_appimage_env_present());
}
#[cfg(not(all(desktop, target_os = "linux")))]
fn sanitize_linux_appimage_git_env(_command: &mut Command) {}
#[cfg(any(test, all(desktop, target_os = "linux")))]
fn sanitize_linux_appimage_git_env_for_launch(command: &mut Command, is_appimage: bool) {
if !is_appimage {
return;
}
for key in LINUX_APPIMAGE_GIT_ENV_REMOVALS {
command.env_remove(key);
}
}
#[cfg(all(desktop, target_os = "linux"))]
fn linux_appimage_env_present() -> bool {
["APPIMAGE", "APPDIR"]
.into_iter()
.any(|key| std::env::var(key).is_ok_and(|value| !value.trim().is_empty()))
}
/// Ensure a `.gitignore` with sensible defaults exists in the vault directory.
/// Creates the file if missing; leaves existing `.gitignore` files untouched.
pub fn ensure_gitignore(path: &str) -> Result<(), String> {
let gitignore_path = Path::new(path).join(".gitignore");
pub fn ensure_gitignore(path: impl AsRef<Path>) -> Result<(), String> {
let gitignore_path = path.as_ref().join(".gitignore");
if !gitignore_path.exists() {
std::fs::write(&gitignore_path, DEFAULT_GITIGNORE)
.map_err(|e| format!("Failed to write .gitignore: {}", e))?;
@@ -72,15 +104,15 @@ pub fn ensure_gitignore(path: &str) -> Result<(), String> {
}
/// Initialize a new git repository, stage all files, and create an initial commit.
pub fn init_repo(path: &str) -> Result<(), String> {
let dir = Path::new(path);
pub fn init_repo(path: impl AsRef<Path>) -> Result<(), String> {
let dir = path.as_ref();
run_git(dir, &["init"])?;
ensure_author_config(dir)?;
// Write .gitignore before the first commit so machine-specific and
// macOS metadata files are never tracked and don't cause conflicts.
ensure_gitignore(path)?;
ensure_gitignore(dir)?;
run_git(dir, &["add", "."])?;
commit_initial_vault_setup(dir)?;
@@ -176,6 +208,7 @@ fn parse_github_repo_path(url: &str) -> Option<String> {
#[cfg(test)]
mod tests {
use super::*;
use std::collections::HashMap;
use std::fs;
use tempfile::TempDir;
@@ -259,6 +292,18 @@ mod tests {
(bare_dir, clone_a_dir, clone_b_dir)
}
fn command_envs(command: &Command) -> HashMap<String, Option<String>> {
command
.get_envs()
.map(|(key, value)| {
(
key.to_string_lossy().to_string(),
value.map(|entry| entry.to_string_lossy().to_string()),
)
})
.collect()
}
#[test]
fn test_ensure_gitignore_creates_file() {
let dir = TempDir::new().unwrap();
@@ -282,6 +327,32 @@ mod tests {
assert_eq!(content, "my-rule\n");
}
#[test]
fn test_linux_appimage_git_commands_remove_appimage_loader_env() {
let mut command = crate::hidden_command("git");
sanitize_linux_appimage_git_env_for_launch(&mut command, true);
let envs = command_envs(&command);
for key in LINUX_APPIMAGE_GIT_ENV_REMOVALS {
assert_eq!(envs.get(key), Some(&None));
}
}
#[test]
fn test_non_appimage_git_commands_keep_parent_env_unmodified() {
let mut command = crate::hidden_command("git");
sanitize_linux_appimage_git_env_for_launch(&mut command, false);
let envs = command_envs(&command);
for key in LINUX_APPIMAGE_GIT_ENV_REMOVALS {
assert!(!envs.contains_key(key));
}
}
#[test]
fn test_init_repo_creates_git_directory() {
let dir = TempDir::new().unwrap();