From ce2f286df010b730ccebaaaf8639c4cd0878e9fe Mon Sep 17 00:00:00 2001 From: Bob Peterson Date: Mon, 13 Oct 2025 12:57:26 -0500 Subject: [PATCH] Replace git shell commands with std shims gix doesn't work here, since while it's pure Rust, it has a non-configurable dependency on crates using inline assembly, which Miri does not support. This commit is a bit of a hack, and only works in non-bare git repos without e.g packed-refs. --- simulator/runner/bugbase.rs | 69 ++++++++++++++++++++++++------------- 1 file changed, 46 insertions(+), 23 deletions(-) diff --git a/simulator/runner/bugbase.rs b/simulator/runner/bugbase.rs index dd0d6f432..cefed3740 100644 --- a/simulator/runner/bugbase.rs +++ b/simulator/runner/bugbase.rs @@ -1,8 +1,9 @@ use std::{ collections::HashMap, - io::{self, Write}, - path::PathBuf, - process::Command, + env::current_dir, + fs::File, + io::{self, Read, Write}, + path::{Path, PathBuf}, time::SystemTime, }; @@ -452,28 +453,50 @@ impl BugBase { impl BugBase { pub(crate) fn get_current_commit_hash() -> anyhow::Result { - let output = Command::new("git") - .args(["rev-parse", "HEAD"]) - .output() - .with_context(|| "should be able to get the commit hash")?; - let commit_hash = String::from_utf8(output.stdout) - .with_context(|| "commit hash should be valid utf8")? - .trim() - .to_string(); - Ok(commit_hash) + let git_dir = find_git_dir(current_dir()?).with_context(|| "should be a git repo")?; + let hash = + resolve_head(&git_dir).with_context(|| "should be able to get the commit hash")?; + Ok(hash) } pub(crate) fn get_limbo_project_dir() -> anyhow::Result { - Ok(PathBuf::from( - String::from_utf8( - Command::new("git") - .args(["rev-parse", "--show-toplevel"]) - .output() - .with_context(|| "should be able to get the git path")? - .stdout, - ) - .with_context(|| "commit hash should be valid utf8")? - .trim(), - )) + let git_dir = find_git_dir(current_dir()?).with_context(|| "should be a git repo")?; + let workdir = git_dir + .parent() + .with_context(|| "work tree should be parent of .git")?; + Ok(workdir.to_path_buf()) } } + +fn find_git_dir(start_path: impl AsRef) -> Option { + // HACK ignores stuff like bare repo, worktree, etc. + let mut current = start_path.as_ref().to_path_buf(); + loop { + let git_path = current.join(".git"); + if git_path.is_dir() { + return Some(git_path); + } + if !current.pop() { + return None; + } + } +} + +fn resolve_head(git_dir: impl AsRef) -> anyhow::Result { + // HACK ignores stuff like packed-refs + let head_path = git_dir.as_ref().join("HEAD"); + let head_contents = read_to_string(&head_path)?; + if let Some(ref_path) = head_contents.strip_prefix("ref: ") { + let ref_file = git_dir.as_ref().join(ref_path); + read_to_string(&ref_file) + } else { + Ok(head_contents) + } +} + +fn read_to_string(path: impl AsRef) -> anyhow::Result { + let mut file = File::open(path)?; + let mut contents = String::new(); + file.read_to_string(&mut contents)?; + Ok(contents.trim().to_string()) +}