Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 20 additions & 20 deletions crates/prek/src/cli/update/repository.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ pub(super) async fn setup_and_fetch_repo(repo_url: &str, repo_path: &Path) -> Re
.arg("--filter=blob:none")
.arg("--tags")
.current_dir(repo_path)
.isolate_from_git_env()
.sanitize_git_repo_env()
.stdout(Stdio::null())
.stderr(Stdio::null())
.status()
Expand All @@ -44,7 +44,7 @@ pub(super) async fn resolve_revision_to_commit(repo_path: &Path, rev: &str) -> R
.arg(format!("{rev}^{{}}"))
.check(true)
.current_dir(repo_path)
.isolate_from_git_env()
.sanitize_git_repo_env()
.output()
.await?;

Expand Down Expand Up @@ -84,7 +84,7 @@ pub(super) async fn is_commit_present(repo_path: &Path, commit: &str) -> Result<
.env(EnvVars::LC_ALL, "C")
.check(false)
.current_dir(repo_path)
.isolate_from_git_env()
.sanitize_git_repo_env()
.stdout(Stdio::null())
.output()
.await?;
Expand Down Expand Up @@ -128,7 +128,7 @@ pub(super) async fn resolve_bleeding_edge(repo_path: &Path) -> Result<Option<Str
.arg("--exact-match")
.check(false)
.current_dir(repo_path)
.isolate_from_git_env()
.sanitize_git_repo_env()
.output()
.await?;
let rev = if output.status.success() {
Expand All @@ -140,7 +140,7 @@ pub(super) async fn resolve_bleeding_edge(repo_path: &Path) -> Result<Option<Str
.arg("FETCH_HEAD")
.check(true)
.current_dir(repo_path)
.isolate_from_git_env()
.sanitize_git_repo_env()
.output()
.await?;
String::from_utf8_lossy(&output.stdout).trim().to_string()
Expand All @@ -162,7 +162,7 @@ pub(super) async fn list_tag_metadata(repo: &Path) -> Result<Vec<TagTimestamp>>
.arg("refs/tags")
.check(true)
.current_dir(repo)
.isolate_from_git_env()
.sanitize_git_repo_env()
.output()
.await?;

Expand Down Expand Up @@ -381,7 +381,7 @@ pub(super) async fn checkout_and_validate_manifest(
.arg("show")
.arg(format!("{rev}:{PRE_COMMIT_HOOKS_YAML}"))
.current_dir(repo_path)
.isolate_from_git_env()
.sanitize_git_repo_env()
.stdout(Stdio::null())
.stderr(Stdio::null())
.status()
Expand All @@ -395,7 +395,7 @@ pub(super) async fn checkout_and_validate_manifest(
.arg("--")
.arg(PRE_COMMIT_HOOKS_YAML)
.current_dir(repo_path)
.isolate_from_git_env()
.sanitize_git_repo_env()
.stdout(Stdio::null())
.stderr(Stdio::null())
.status()
Expand Down Expand Up @@ -445,7 +445,7 @@ mod tests {
.unwrap()
.arg("init")
.current_dir(repo)
.isolate_from_git_env()
.sanitize_git_repo_env()
.output()
.await
.unwrap();
Expand All @@ -454,7 +454,7 @@ mod tests {
.unwrap()
.args(["config", "user.email", "test@test.com"])
.current_dir(repo)
.isolate_from_git_env()
.sanitize_git_repo_env()
.output()
.await
.unwrap();
Expand All @@ -463,7 +463,7 @@ mod tests {
.unwrap()
.args(["config", "user.name", "Test"])
.current_dir(repo)
.isolate_from_git_env()
.sanitize_git_repo_env()
.output()
.await
.unwrap();
Expand All @@ -479,7 +479,7 @@ mod tests {
"initial",
])
.current_dir(repo)
.isolate_from_git_env()
.sanitize_git_repo_env()
.output()
.await
.unwrap();
Expand All @@ -488,7 +488,7 @@ mod tests {
.unwrap()
.args(["branch", "-M", "trunk"])
.current_dir(repo)
.isolate_from_git_env()
.sanitize_git_repo_env()
.output()
.await
.unwrap();
Expand Down Expand Up @@ -524,7 +524,7 @@ mod tests {
async fn create_commit(repo: &Path, message: &str) {
git_cmd(repo)
.args(["commit", "--allow-empty", "-m", message])
.isolate_from_git_env()
.sanitize_git_repo_env()
.output()
.await
.unwrap();
Expand All @@ -543,7 +543,7 @@ mod tests {
.args(["commit", "--allow-empty", "-m", message])
.env("GIT_AUTHOR_DATE", &date_str)
.env("GIT_COMMITTER_DATE", &date_str)
.isolate_from_git_env()
.sanitize_git_repo_env()
.output()
.await
.unwrap();
Expand All @@ -553,7 +553,7 @@ mod tests {
git_cmd(repo)
.arg("tag")
.arg(tag)
.isolate_from_git_env()
.sanitize_git_repo_env()
.output()
.await
.unwrap();
Expand All @@ -575,7 +575,7 @@ mod tests {
.arg(tag)
.env("GIT_AUTHOR_DATE", &date_str)
.env("GIT_COMMITTER_DATE", &date_str)
.isolate_from_git_env()
.sanitize_git_repo_env()
.output()
.await
.unwrap();
Expand Down Expand Up @@ -613,7 +613,7 @@ mod tests {
.unwrap()
.args(["fetch", ".", "HEAD"])
.current_dir(repo)
.isolate_from_git_env()
.sanitize_git_repo_env()
.output()
.await
.unwrap();
Expand All @@ -633,7 +633,7 @@ mod tests {
.unwrap()
.args(["fetch", ".", "HEAD"])
.current_dir(repo)
.isolate_from_git_env()
.sanitize_git_repo_env()
.output()
.await
.unwrap();
Expand All @@ -644,7 +644,7 @@ mod tests {
.unwrap()
.args(["rev-parse", "HEAD"])
.current_dir(repo)
.isolate_from_git_env()
.sanitize_git_repo_env()
.output()
.await
.unwrap()
Expand Down
76 changes: 30 additions & 46 deletions crates/prek/src/git.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,38 +69,29 @@ pub(crate) static GIT_ROOT: LazyLock<Result<PathBuf, Error>> = LazyLock::new(||
})
});

/// Remove some `GIT_` environment variables exposed by `git`.
/// Repository-local environment variables cleared before operating on another repository.
///
/// For some commands, like `git commit -a` or `git commit -p`, git creates a `.git/index.lock` file
/// and set `GIT_INDEX_FILE` to point to it.
/// We need to keep the `GIT_INDEX_FILE` env var to make sure `git write-tree` works correctly.
/// <https://stackoverflow.com/questions/65639403/git-pre-commit-hook-how-can-i-get-added-modified-files-when-commit-with-a-flag/65647202#65647202>
static GIT_ENVS_TO_REMOVE: LazyLock<Vec<(String, String)>> = LazyLock::new(|| {
let keep = &[
"GIT_EXEC_PATH",
"GIT_SSH",
"GIT_SSH_COMMAND",
"GIT_SSL_CAINFO",
"GIT_SSL_NO_VERIFY",
"GIT_CONFIG_COUNT",
"GIT_CONFIG_PARAMETERS",
"GIT_HTTP_PROXY_AUTHMETHOD",
"GIT_ALLOW_PROTOCOL",
"GIT_ASKPASS",
];

std::env::vars()
.filter(|(k, _)| {
k.starts_with("GIT_")
&& !k.starts_with("GIT_CONFIG_KEY_")
&& !k.starts_with("GIT_CONFIG_VALUE_")
&& !keep.contains(&k.as_str())
})
.collect()
});
/// `GIT_CONFIG_PARAMETERS`, `GIT_CONFIG_COUNT`, `GIT_CONFIG_KEY_*`, and `GIT_CONFIG_VALUE_*`
/// are deliberately excluded so nested Git commands retain caller-supplied command-scoped settings.
static GIT_REPO_LOCAL_ENVS: &[&str] = &[
Comment thread
j178 marked this conversation as resolved.
Comment thread
j178 marked this conversation as resolved.
"GIT_ALTERNATE_OBJECT_DIRECTORIES",
Comment thread
j178 marked this conversation as resolved.
"GIT_CONFIG",
"GIT_OBJECT_DIRECTORY",
"GIT_DIR",
"GIT_WORK_TREE",
"GIT_IMPLICIT_WORK_TREE",
"GIT_GRAFT_FILE",
"GIT_INDEX_FILE",
"GIT_NO_REPLACE_OBJECTS",
"GIT_REPLACE_REF_BASE",
"GIT_PREFIX",
"GIT_INTERNAL_SUPER_PREFIX",
"GIT_SHALLOW_FILE",
"GIT_COMMON_DIR",
];

pub(crate) trait GitCommandExt {
fn isolate_from_git_env(&mut self) -> &mut Self;
fn sanitize_git_repo_env(&mut self) -> &mut Self;
}

pub(crate) fn apply_git_work_tree(cmd: &mut Command) -> &mut Command {
Expand All @@ -111,15 +102,8 @@ pub(crate) fn apply_git_work_tree(cmd: &mut Command) -> &mut Command {
}

impl GitCommandExt for Cmd {
fn isolate_from_git_env(&mut self) -> &mut Self {
// `git_cmd()` adds this synthetic value as a command-local env. Commands
// that call `isolate_from_git_env()` are intentionally detached from the
// current repo, so remove it here; inherited `GIT_WORK_TREE` is handled
// by `GIT_ENVS_TO_REMOVE`.
if git_work_tree().is_some() {
self.env_remove(EnvVars::GIT_WORK_TREE);
}
for (key, _) in GIT_ENVS_TO_REMOVE.iter() {
fn sanitize_git_repo_env(&mut self) -> &mut Self {
for key in GIT_REPO_LOCAL_ENVS {
self.env_remove(key);
}
self
Expand Down Expand Up @@ -515,7 +499,7 @@ pub(crate) async fn init_repo(url: &str, path: &Path) -> Result<(), Error> {
.arg("init")
.arg("--template=")
.arg(path)
.isolate_from_git_env()
.sanitize_git_repo_env()
.check(true)
.output()
.await?;
Expand All @@ -526,7 +510,7 @@ pub(crate) async fn init_repo(url: &str, path: &Path) -> Result<(), Error> {
.arg("add")
.arg("origin")
.arg(url)
.isolate_from_git_env()
.sanitize_git_repo_env()
.check(true)
.output()
.await?;
Expand Down Expand Up @@ -589,7 +573,7 @@ async fn shallow_clone(
.arg("origin")
.arg(rev)
.arg("--depth=1")
.isolate_from_git_env()
.sanitize_git_repo_env()
.env(EnvVars::LC_ALL, "C")
.env(EnvVars::GIT_TERMINAL_PROMPT, terminal_prompt.env_value())
.check(true)
Expand All @@ -600,7 +584,7 @@ async fn shallow_clone(
.current_dir(path)
.arg("checkout")
.arg("FETCH_HEAD")
.isolate_from_git_env()
.sanitize_git_repo_env()
.env(EnvVars::PREK_INTERNAL__SKIP_POST_CHECKOUT, "1")
.env(EnvVars::LC_ALL, "C")
.env(EnvVars::GIT_TERMINAL_PROMPT, terminal_prompt.env_value())
Expand All @@ -619,7 +603,7 @@ async fn full_clone(rev: &str, path: &Path, terminal_prompt: TerminalPrompt) ->
.arg("fetch")
.arg("origin")
.arg("--tags")
.isolate_from_git_env()
.sanitize_git_repo_env()
.env(EnvVars::LC_ALL, "C")
.env(EnvVars::GIT_TERMINAL_PROMPT, terminal_prompt.env_value())
.check(true)
Expand All @@ -630,7 +614,7 @@ async fn full_clone(rev: &str, path: &Path, terminal_prompt: TerminalPrompt) ->
.current_dir(path)
.arg("checkout")
.arg(rev)
.isolate_from_git_env()
.sanitize_git_repo_env()
.env(EnvVars::PREK_INTERNAL__SKIP_POST_CHECKOUT, "1")
.env(EnvVars::LC_ALL, "C")
.env(EnvVars::GIT_TERMINAL_PROMPT, terminal_prompt.env_value())
Expand Down Expand Up @@ -662,7 +646,7 @@ async fn update_submodules(
if shallow {
cmd.arg("--depth=1");
}
cmd.isolate_from_git_env()
cmd.sanitize_git_repo_env()
.env(EnvVars::LC_ALL, "C")
.env(EnvVars::GIT_TERMINAL_PROMPT, terminal_prompt.env_value())
.check(true)
Expand All @@ -682,7 +666,7 @@ async fn should_update_submodules(path: &Path) -> Result<bool, Error> {
.arg("ls-files")
.arg("-z")
.arg("-s")
.isolate_from_git_env()
.sanitize_git_repo_env()
.env(EnvVars::LC_ALL, "C")
.check(true)
.output()
Expand Down
2 changes: 2 additions & 0 deletions crates/prek/src/languages/bun/bun.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use prek_consts::prepend_paths;
use tracing::debug;

use crate::cli::reporter::HookInstallReporter;
use crate::git::GitCommandExt;
use crate::hook::InstalledHook;
use crate::hook::{Hook, InstallInfo};
use crate::languages::bun::BunRequest;
Expand Down Expand Up @@ -83,6 +84,7 @@ impl LanguageBackend for Bun {
.args(deps)
.env(EnvVars::PATH, new_path)
.env(EnvVars::BUN_INSTALL, &info.env_path)
.sanitize_git_repo_env()
.check(true)
.output()
.await?;
Expand Down
2 changes: 2 additions & 0 deletions crates/prek/src/languages/dart.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use serde::{Deserialize, Serialize};
use tracing::debug;

use crate::cli::reporter::HookInstallReporter;
use crate::git::GitCommandExt;
use crate::hook::{Hook, InstallInfo, InstalledHook};
use crate::hook_entry::PreparedHookEntry;
use crate::languages::{ExecutionEnvironment, LanguageBackend};
Expand Down Expand Up @@ -351,6 +352,7 @@ async fn install_package_config(
.env(EnvVars::PUB_CACHE, env_path)
.arg("pub")
.arg("get")
.sanitize_git_repo_env()
.check(true)
.output()
.await?;
Expand Down
4 changes: 2 additions & 2 deletions crates/prek/src/languages/golang/golang.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ impl LanguageBackend for Golang {
go_install_cmd()
.arg("./...")
.current_dir(repo)
.isolate_from_git_env()
.sanitize_git_repo_env()
.check(true)
.output()
.await?;
Expand All @@ -91,7 +91,7 @@ impl LanguageBackend for Golang {
cmd.current_dir(repo);
}
cmd.arg(dep)
.isolate_from_git_env()
.sanitize_git_repo_env()
.check(true)
.output()
.await?;
Expand Down
2 changes: 2 additions & 0 deletions crates/prek/src/languages/haskell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use prek_consts::prepend_paths;
use tracing::debug;

use crate::cli::reporter::HookInstallReporter;
use crate::git::GitCommandExt;
use crate::hook::{Hook, InstallInfo, InstalledHook};
use crate::languages::{ExecutionEnvironment, LanguageBackend};
use crate::process::Cmd;
Expand Down Expand Up @@ -86,6 +87,7 @@ impl LanguageBackend for Haskell {
.arg("--installdir")
.arg(&bin_dir)
.args(pkgs)
.sanitize_git_repo_env()
.check(true)
.output()
.await
Expand Down
Loading
Loading