From 127890dc71303a7f90766c8264083b14c714603a Mon Sep 17 00:00:00 2001 From: Alpha Chen Date: Sun, 26 Apr 2026 19:06:15 +0000 Subject: [PATCH] Check HEAD existence with rev-parse instead of parsing stderr Two-command approach: git rev-parse --verify HEAD uses exit codes reliably, then git show only runs when HEAD exists so any failure means the file is absent. No more fragility from matching stderr text. Assisted-by: GLM-5.1 via pi --- src/quire.rs | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/src/quire.rs b/src/quire.rs index fd552d2..6eee5c9 100644 --- a/src/quire.rs +++ b/src/quire.rs @@ -58,6 +58,21 @@ impl Repo { /// Returns an error when the config file exists but contains /// malformed Fennel — source labels point at the right line. pub fn config(&self) -> crate::Result { + // Check whether HEAD exists first — exit code distinguishes this + // reliably without parsing stderr text. + let has_head = std::process::Command::new("git") + .args(["rev-parse", "--verify", "HEAD"]) + .current_dir(&self.path) + .stdout(std::process::Stdio::null()) + .stderr(std::process::Stdio::null()) + .status() + .map_err(crate::Error::Io)? + .success(); + + if !has_head { + return Ok(RepoConfig::default()); + } + let output = std::process::Command::new("git") .args(["show", "HEAD:.quire/config.fnl"]) .current_dir(&self.path) @@ -65,15 +80,8 @@ impl Repo { .map_err(crate::Error::Io)?; if !output.status.success() { - let stderr = String::from_utf8_lossy(&output.stderr); - // HEAD missing (fresh repo) or file absent — both mean "no config". - if stderr.contains("invalid object name") || stderr.contains("does not exist") { - return Ok(RepoConfig::default()); - } - // Unexpected git error. - return Err(crate::Error::Git(format!( - "failed to read HEAD:.quire/config.fnl: {stderr}" - ))); + // HEAD exists but the file doesn't — not an error. + return Ok(RepoConfig::default()); } let source = String::from_utf8(output.stdout).map_err(|e| { -- 2.54.0