context in headers

This commit is contained in:
pash
2026-01-30 14:01:46 -08:00
parent d7bcca0de7
commit 53056a4f8d
2 changed files with 51 additions and 29 deletions

View File

@@ -125,7 +125,16 @@ pub async fn get_git_remote_urls(cwd: &Path) -> Option<BTreeMap<String, String>>
/// Collect fetch remotes without checking whether `cwd` is in a git repo.
pub async fn get_git_remote_urls_assume_git_repo(cwd: &Path) -> Option<BTreeMap<String, String>> {
let output = run_git_command_with_timeout(&["remote", "-v"], cwd).await?;
get_git_remote_urls_assume_git_repo_with_timeout(cwd, GIT_COMMAND_TIMEOUT).await
}
/// Collect fetch remotes without checking whether `cwd` is in a git repo,
/// using the provided timeout.
pub async fn get_git_remote_urls_assume_git_repo_with_timeout(
cwd: &Path,
timeout_dur: TokioDuration,
) -> Option<BTreeMap<String, String>> {
let output = run_git_command_with_timeout_override(&["remote", "-v"], cwd, timeout_dur).await?;
if !output.status.success() {
return None;
}
@@ -136,7 +145,17 @@ pub async fn get_git_remote_urls_assume_git_repo(cwd: &Path) -> Option<BTreeMap<
/// Return the current HEAD commit hash without checking whether `cwd` is in a git repo.
pub async fn get_head_commit_hash(cwd: &Path) -> Option<String> {
let output = run_git_command_with_timeout(&["rev-parse", "HEAD"], cwd).await?;
get_head_commit_hash_with_timeout(cwd, GIT_COMMAND_TIMEOUT).await
}
/// Return the current HEAD commit hash without checking whether `cwd` is in a
/// git repo, using the provided timeout.
pub async fn get_head_commit_hash_with_timeout(
cwd: &Path,
timeout_dur: TokioDuration,
) -> Option<String> {
let output =
run_git_command_with_timeout_override(&["rev-parse", "HEAD"], cwd, timeout_dur).await?;
if !output.status.success() {
return None;
}
@@ -253,10 +272,19 @@ pub async fn git_diff_to_remote(cwd: &Path) -> Option<GitDiffToRemote> {
/// Run a git command with a timeout to prevent blocking on large repositories
async fn run_git_command_with_timeout(args: &[&str], cwd: &Path) -> Option<std::process::Output> {
run_git_command_with_timeout_override(args, cwd, GIT_COMMAND_TIMEOUT).await
}
/// Run a git command with a caller-provided timeout.
async fn run_git_command_with_timeout_override(
args: &[&str],
cwd: &Path,
timeout_dur: TokioDuration,
) -> Option<std::process::Output> {
let mut command = Command::new("git");
command.args(args).current_dir(cwd);
command.kill_on_drop(true);
let result = timeout(GIT_COMMAND_TIMEOUT, command.output()).await;
let result = timeout(timeout_dur, command.output()).await;
match result {
Ok(Ok(output)) => Some(output),

View File

@@ -3,11 +3,10 @@ use std::path::Path;
use serde::Serialize;
use tokio::time::Duration as TokioDuration;
use tokio::time::timeout;
use crate::git_info::get_git_remote_urls_assume_git_repo;
use crate::git_info::get_git_remote_urls_assume_git_repo_with_timeout;
use crate::git_info::get_git_repo_root;
use crate::git_info::get_head_commit_hash;
use crate::git_info::get_head_commit_hash_with_timeout;
const TURN_METADATA_TIMEOUT: TokioDuration = TokioDuration::from_millis(150);
@@ -31,28 +30,23 @@ struct TurnMetadata {
pub(crate) async fn build_turn_metadata_header(cwd: &Path) -> Option<String> {
let repo_root = get_git_repo_root(cwd)?;
// Cap the total time we spend gathering optional metadata so turn startup
// stays responsive even when git is slow in certain environments.
timeout(TURN_METADATA_TIMEOUT, async {
let (latest_git_commit_hash, associated_remote_urls) = tokio::join!(
get_head_commit_hash(cwd),
get_git_remote_urls_assume_git_repo(cwd)
);
if latest_git_commit_hash.is_none() && associated_remote_urls.is_none() {
return None;
}
// Keep git subprocess work bounded per command, without wrapping the
// entire metadata build in a separate timeout.
let (latest_git_commit_hash, associated_remote_urls) = tokio::join!(
get_head_commit_hash_with_timeout(cwd, TURN_METADATA_TIMEOUT),
get_git_remote_urls_assume_git_repo_with_timeout(cwd, TURN_METADATA_TIMEOUT)
);
if latest_git_commit_hash.is_none() && associated_remote_urls.is_none() {
return None;
}
let mut workspaces = BTreeMap::new();
workspaces.insert(
repo_root.to_string_lossy().into_owned(),
TurnMetadataWorkspace {
associated_remote_urls,
latest_git_commit_hash,
},
);
serde_json::to_string(&TurnMetadata { workspaces }).ok()
})
.await
.ok()
.flatten()
let mut workspaces = BTreeMap::new();
workspaces.insert(
repo_root.to_string_lossy().into_owned(),
TurnMetadataWorkspace {
associated_remote_urls,
latest_git_commit_hash,
},
);
serde_json::to_string(&TurnMetadata { workspaces }).ok()
}