git: Avoid calling git help -a on every commit (#44586)

Updates #43993 

Release Notes:

- N/A
This commit is contained in:
Cole Miller
2025-12-11 01:03:35 +00:00
committed by GitHub
parent 7c4a85f5f1
commit 37077a8ebb
+60 -35
View File
@@ -652,6 +652,7 @@ pub struct RealGitRepository {
pub repository: Arc<Mutex<git2::Repository>>,
pub system_git_binary_path: Option<PathBuf>,
pub any_git_binary_path: PathBuf,
any_git_binary_help_output: Arc<Mutex<Option<SharedString>>>,
executor: BackgroundExecutor,
}
@@ -670,6 +671,7 @@ impl RealGitRepository {
system_git_binary_path,
any_git_binary_path,
executor,
any_git_binary_help_output: Arc::new(Mutex::new(None)),
})
}
@@ -680,6 +682,27 @@ impl RealGitRepository {
.context("failed to read git work directory")
.map(Path::to_path_buf)
}
async fn any_git_binary_help_output(&self) -> SharedString {
if let Some(output) = self.any_git_binary_help_output.lock().clone() {
return output;
}
let git_binary_path = self.any_git_binary_path.clone();
let executor = self.executor.clone();
let working_directory = self.working_directory();
let output: SharedString = self
.executor
.spawn(async move {
GitBinary::new(git_binary_path, working_directory?, executor)
.run(["help", "-a"])
.await
})
.await
.unwrap_or_default()
.into();
*self.any_git_binary_help_output.lock() = Some(output.clone());
output
}
}
#[derive(Clone, Debug)]
@@ -2290,48 +2313,50 @@ impl GitRepository for RealGitRepository {
env: Arc<HashMap<String, String>>,
) -> BoxFuture<'_, Result<()>> {
let working_directory = self.working_directory();
let repository = self.repository.clone();
let git_binary_path = self.any_git_binary_path.clone();
let executor = self.executor.clone();
self.executor
.spawn(async move {
let working_directory = working_directory?;
let git = GitBinary::new(git_binary_path, working_directory.clone(), executor)
.envs(HashMap::clone(&env));
let help_output = self.any_git_binary_help_output();
let output = git.run(&["help", "-a"]).await?;
if !output.lines().any(|line| line.trim().starts_with("hook ")) {
log::warn!(
"git hook command not available, running the {} hook manually",
hook.as_str()
);
async move {
let working_directory = working_directory?;
if !help_output
.await
.lines()
.any(|line| line.trim().starts_with("hook "))
{
let hook_abs_path = repository.lock().path().join("hooks").join(hook.as_str());
if hook_abs_path.is_file() {
let output = self
.executor
.spawn(
new_smol_command(&hook_abs_path)
.envs(env.iter())
.current_dir(&working_directory)
.output(),
)
.await?;
let hook_abs_path = working_directory
.join(".git")
.join("hooks")
.join(hook.as_str());
if hook_abs_path.is_file() {
let output = new_smol_command(&hook_abs_path)
.envs(env.iter())
.current_dir(&working_directory)
.output()
.await?;
anyhow::ensure!(
output.status.success(),
"{} hook failed:\n{}",
hook.as_str(),
String::from_utf8_lossy(&output.stderr)
);
if !output.status.success() {
return Err(GitBinaryCommandError {
stdout: String::from_utf8_lossy(&output.stdout).into_owned(),
stderr: String::from_utf8_lossy(&output.stderr).into_owned(),
status: output.status,
}
.into());
}
return Ok(());
}
git.run(&["hook", "run", "--ignore-missing", hook.as_str()])
.await?;
Ok(())
})
.boxed()
return Ok(());
}
let git = GitBinary::new(git_binary_path, working_directory, executor)
.envs(HashMap::clone(&env));
git.run(&["hook", "run", "--ignore-missing", hook.as_str()])
.await?;
Ok(())
}
.boxed()
}
}