From c5daef2471992f949a7b48ed1cedcf07650412c5 Mon Sep 17 00:00:00 2001 From: Val Alexander Date: Sun, 26 Jul 2026 12:09:58 -0500 Subject: [PATCH 1/2] fix(query): avoid spawning git for memory provenance --- src-rust/crates/query/src/lib.rs | 166 +++++++++++++++++++++++++++---- 1 file changed, 145 insertions(+), 21 deletions(-) diff --git a/src-rust/crates/query/src/lib.rs b/src-rust/crates/query/src/lib.rs index 466901c..fff3cfb 100644 --- a/src-rust/crates/query/src/lib.rs +++ b/src-rust/crates/query/src/lib.rs @@ -50,8 +50,8 @@ use claurst_core::error::ClaudeError; use claurst_core::types::{ContentBlock, Message, ToolResultContent, UsageInfo}; use claurst_tools::{Tool, ToolContext, ToolResult}; use serde_json::Value; -use std::path::Path; -use std::process::Command; +use std::fs; +use std::path::{Path, PathBuf}; use std::sync::Arc; use tokio::sync::mpsc; use tracing::{debug, error, info, warn}; @@ -81,14 +81,16 @@ pub enum QueryOutcome { fn build_session_memory_provenance(session_id: &str, working_dir: &Path) -> MemoryProvenance { let mut provenance = MemoryProvenance::session_memory_extraction(session_id); - if let Some(remote_url) = git_command_output(working_dir, &["remote", "get-url", "origin"]) { - if let Some(repo_slug) = parse_origin_repo_slug(&remote_url) { - provenance = provenance.with_source_repo(repo_slug); + if let Some(git_dir) = find_git_dir(working_dir) { + if let Some(remote_url) = read_origin_remote_url(&git_dir) { + if let Some(repo_slug) = parse_origin_repo_slug(&remote_url) { + provenance = provenance.with_source_repo(repo_slug); + } } - } - if let Some(commit) = git_command_output(working_dir, &["rev-parse", "HEAD"]) { - provenance = provenance.with_source_commit(commit); + if let Some(commit) = read_head_commit(&git_dir) { + provenance = provenance.with_source_commit(commit); + } } if let Ok(actor) = std::env::var("GITHUB_ACTOR") { @@ -98,21 +100,67 @@ fn build_session_memory_provenance(session_id: &str, working_dir: &Path) -> Memo provenance } -fn git_command_output(working_dir: &Path, args: &[&str]) -> Option { - let output = Command::new("git") - .args(args) - .current_dir(working_dir) - .output() - .ok()?; - if !output.status.success() { - return None; +fn find_git_dir(working_dir: &Path) -> Option { + for dir in working_dir.ancestors() { + let dot_git = dir.join(".git"); + if dot_git.is_dir() { + return Some(dot_git); + } + + if dot_git.is_file() { + let git_file = fs::read_to_string(&dot_git).ok()?; + let git_dir = git_file.trim().strip_prefix("gitdir:")?.trim(); + let git_dir = Path::new(git_dir); + return Some(if git_dir.is_absolute() { + git_dir.to_path_buf() + } else { + dir.join(git_dir) + }); + } } - let text = String::from_utf8(output.stdout).ok()?; - let trimmed = text.trim(); - if trimmed.is_empty() { - None + None +} + +fn read_origin_remote_url(git_dir: &Path) -> Option { + let config = fs::read_to_string(git_dir.join("config")).ok()?; + let mut in_origin_section = false; + + for line in config.lines() { + let trimmed = line.trim(); + if trimmed.starts_with('[') && trimmed.ends_with(']') { + in_origin_section = trimmed == r#"[remote "origin"]"#; + continue; + } + + if in_origin_section { + let Some((key, value)) = trimmed.split_once('=') else { + continue; + }; + if key.trim() == "url" { + let url = value.trim(); + if !url.is_empty() { + return Some(url.to_string()); + } + } + } + } + + None +} + +fn read_head_commit(git_dir: &Path) -> Option { + let head = fs::read_to_string(git_dir.join("HEAD")).ok()?; + let head = head.trim(); + let commit = if let Some(reference) = head.strip_prefix("ref:") { + fs::read_to_string(git_dir.join(reference.trim())).ok()? + } else { + head.to_string() + }; + let commit = commit.trim(); + if commit.len() == 40 && commit.chars().all(|ch| ch.is_ascii_hexdigit()) { + Some(commit.to_string()) } else { - Some(trimmed.to_string()) + None } } @@ -2735,6 +2783,82 @@ mod tests { assert!(parse_origin_repo_slug("https://github.com/token@example").is_none()); } + #[test] + fn builds_session_memory_provenance_without_executing_git_from_path() { + let temp = tempfile::tempdir().unwrap(); + let workspace = temp.path().join("workspace"); + std::fs::create_dir(&workspace).unwrap(); + std::fs::create_dir(workspace.join(".git")).unwrap(); + std::fs::create_dir_all(workspace.join(".git").join("refs").join("heads")).unwrap(); + std::fs::write( + workspace.join(".git").join("config"), + "[remote \"origin\"]\n url = https://github.com/OpenCoven/coven-code.git\n", + ) + .unwrap(); + std::fs::write( + workspace.join(".git").join("HEAD"), + "ref: refs/heads/main\n", + ) + .unwrap(); + std::fs::write( + workspace + .join(".git") + .join("refs") + .join("heads") + .join("main"), + "0123456789abcdef0123456789abcdef01234567\n", + ) + .unwrap(); + std::fs::write(workspace.join("git"), "not executed").unwrap(); + + let provenance = build_session_memory_provenance("session-1", &workspace); + + assert_eq!( + provenance.source_repo.as_deref(), + Some("OpenCoven/coven-code") + ); + assert_eq!( + provenance.source_commit.as_deref(), + Some("0123456789abcdef0123456789abcdef01234567") + ); + } + + #[test] + fn reads_git_metadata_from_gitdir_file() { + let temp = tempfile::tempdir().unwrap(); + let workspace = temp.path().join("workspace"); + let git_dir = temp.path().join("actual-git-dir"); + std::fs::create_dir(&workspace).unwrap(); + std::fs::create_dir_all(git_dir.join("refs").join("heads")).unwrap(); + std::fs::write( + workspace.join(".git"), + format!("gitdir: {}\n", git_dir.display()), + ) + .unwrap(); + std::fs::write( + git_dir.join("config"), + "[remote \"origin\"]\n url = git@github.com:OpenCoven/coven-code.git\n", + ) + .unwrap(); + std::fs::write(git_dir.join("HEAD"), "ref: refs/heads/main\n").unwrap(); + std::fs::write( + git_dir.join("refs").join("heads").join("main"), + "abcdef0123456789abcdef0123456789abcdef01\n", + ) + .unwrap(); + + let provenance = build_session_memory_provenance("session-1", &workspace); + + assert_eq!( + provenance.source_repo.as_deref(), + Some("OpenCoven/coven-code") + ); + assert_eq!( + provenance.source_commit.as_deref(), + Some("abcdef0123456789abcdef0123456789abcdef01") + ); + } + // ---- build_system_prompt tests ------------------------------------------ #[test] From be48e4788cf7b522da27fcada01a08d2c16131bc Mon Sep 17 00:00:00 2001 From: Val Alexander <68980965+BunsDev@users.noreply.github.com> Date: Mon, 27 Jul 2026 07:26:25 -0500 Subject: [PATCH 2/2] fix(query): read linked worktree provenance Signed-off-by: Val Alexander <68980965+BunsDev@users.noreply.github.com> --- src-rust/crates/query/src/lib.rs | 40 ++++++++++++++++++++++++-------- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/src-rust/crates/query/src/lib.rs b/src-rust/crates/query/src/lib.rs index fff3cfb..eeaed4a 100644 --- a/src-rust/crates/query/src/lib.rs +++ b/src-rust/crates/query/src/lib.rs @@ -121,8 +121,24 @@ fn find_git_dir(working_dir: &Path) -> Option { None } +fn common_git_dir(git_dir: &Path) -> PathBuf { + let Some(common_dir) = fs::read_to_string(git_dir.join("commondir")) + .ok() + .map(|value| value.trim().to_string()) + .filter(|value| !value.is_empty()) + else { + return git_dir.to_path_buf(); + }; + let common_dir = Path::new(&common_dir); + if common_dir.is_absolute() { + common_dir.to_path_buf() + } else { + git_dir.join(common_dir) + } +} + fn read_origin_remote_url(git_dir: &Path) -> Option { - let config = fs::read_to_string(git_dir.join("config")).ok()?; + let config = fs::read_to_string(common_git_dir(git_dir).join("config")).ok()?; let mut in_origin_section = false; for line in config.lines() { @@ -152,7 +168,10 @@ fn read_head_commit(git_dir: &Path) -> Option { let head = fs::read_to_string(git_dir.join("HEAD")).ok()?; let head = head.trim(); let commit = if let Some(reference) = head.strip_prefix("ref:") { - fs::read_to_string(git_dir.join(reference.trim())).ok()? + let reference = reference.trim(); + fs::read_to_string(git_dir.join(reference)) + .or_else(|_| fs::read_to_string(common_git_dir(git_dir).join(reference))) + .ok()? } else { head.to_string() }; @@ -2784,7 +2803,7 @@ mod tests { } #[test] - fn builds_session_memory_provenance_without_executing_git_from_path() { + fn reads_session_memory_provenance_from_git_metadata() { let temp = tempfile::tempdir().unwrap(); let workspace = temp.path().join("workspace"); std::fs::create_dir(&workspace).unwrap(); @@ -2809,8 +2828,6 @@ mod tests { "0123456789abcdef0123456789abcdef01234567\n", ) .unwrap(); - std::fs::write(workspace.join("git"), "not executed").unwrap(); - let provenance = build_session_memory_provenance("session-1", &workspace); assert_eq!( @@ -2824,25 +2841,28 @@ mod tests { } #[test] - fn reads_git_metadata_from_gitdir_file() { + fn reads_linked_worktree_metadata_from_common_git_dir() { let temp = tempfile::tempdir().unwrap(); let workspace = temp.path().join("workspace"); - let git_dir = temp.path().join("actual-git-dir"); + let common_git_dir = temp.path().join("main.git"); + let git_dir = common_git_dir.join("worktrees").join("workspace"); std::fs::create_dir(&workspace).unwrap(); - std::fs::create_dir_all(git_dir.join("refs").join("heads")).unwrap(); + std::fs::create_dir_all(common_git_dir.join("refs").join("heads")).unwrap(); + std::fs::create_dir_all(&git_dir).unwrap(); std::fs::write( workspace.join(".git"), format!("gitdir: {}\n", git_dir.display()), ) .unwrap(); std::fs::write( - git_dir.join("config"), + common_git_dir.join("config"), "[remote \"origin\"]\n url = git@github.com:OpenCoven/coven-code.git\n", ) .unwrap(); + std::fs::write(git_dir.join("commondir"), "../..\n").unwrap(); std::fs::write(git_dir.join("HEAD"), "ref: refs/heads/main\n").unwrap(); std::fs::write( - git_dir.join("refs").join("heads").join("main"), + common_git_dir.join("refs").join("heads").join("main"), "abcdef0123456789abcdef0123456789abcdef01\n", ) .unwrap();