From e74095e0a035b090284135c88133106ba6a19fc3 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Sun, 11 Aug 2024 08:24:51 +0200 Subject: [PATCH] fix: prevent panic in `Repository::rev_parse_single()` when `HEAD` was invalid. When using a refspec like `HEAD:file`. --- gix/src/revision/spec/parse/delegate/mod.rs | 15 ++++++++++----- gix/src/revision/spec/parse/types.rs | 5 +++++ gix/tests/revision/spec/from_bytes/mod.rs | 6 +++--- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/gix/src/revision/spec/parse/delegate/mod.rs b/gix/src/revision/spec/parse/delegate/mod.rs index 9f1f4523a8c..8dd313358c6 100644 --- a/gix/src/revision/spec/parse/delegate/mod.rs +++ b/gix/src/revision/spec/parse/delegate/mod.rs @@ -203,11 +203,16 @@ impl<'repo> Delegate<'repo> { for (r, obj) in self.refs.iter().zip(self.objs.iter_mut()) { if let (Some(ref_), obj_opt @ None) = (r, obj) { if let Some(id) = ref_.target.try_id().map(ToOwned::to_owned).or_else(|| { - ref_.clone() - .attach(repo) - .peel_to_id_in_place() - .ok() - .map(crate::Id::detach) + match ref_.clone().attach(repo).peel_to_id_in_place() { + Err(err) => { + self.err.push(Error::PeelToId { + name: ref_.name.clone(), + source: err, + }); + None + } + Ok(id) => Some(id.detach()), + } }) { obj_opt.get_or_insert_with(HashSet::default).insert(id); }; diff --git a/gix/src/revision/spec/parse/types.rs b/gix/src/revision/spec/parse/types.rs index 9629b0b34d4..3bc6cdd079e 100644 --- a/gix/src/revision/spec/parse/types.rs +++ b/gix/src/revision/spec/parse/types.rs @@ -55,6 +55,11 @@ pub struct Options { #[derive(Debug, thiserror::Error)] #[allow(missing_docs)] pub enum Error { + #[error("Could not peel '{}' to obtain its target", name)] + PeelToId { + name: gix_ref::FullName, + source: reference::peel::Error, + }, #[error("The rev-spec is malformed and misses a ref name")] Malformed, #[error("Unborn heads do not have a reflog yet")] diff --git a/gix/tests/revision/spec/from_bytes/mod.rs b/gix/tests/revision/spec/from_bytes/mod.rs index 713a8da8510..78eb9f55dae 100644 --- a/gix/tests/revision/spec/from_bytes/mod.rs +++ b/gix/tests/revision/spec/from_bytes/mod.rs @@ -147,11 +147,11 @@ fn access_blob_through_tree() { #[test] fn invalid_head() { let repo = repo("invalid-head").unwrap(); + let err = parse_spec("HEAD:file", &repo).unwrap_err(); + assert_eq!(err.to_string(), "Could not peel 'HEAD' to obtain its target"); + let err = parse_spec("HEAD", &repo).unwrap_err(); assert_eq!(err.to_string(), "The rev-spec is malformed and misses a ref name"); - - let err = parse_spec("HEAD:file", &repo).unwrap_err(); - assert_eq!(err.to_string(), "TBD"); } #[test]