From c22c9431ba47fc51183b80e5616e9ed6f55385a8 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 19 Mar 2026 13:52:52 +0000 Subject: [PATCH 1/3] Initial plan From 69566d9f1ecb260fae15c9768bd1a6060f216038 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 19 Mar 2026 14:02:58 +0000 Subject: [PATCH 2/3] fix: add SPDX headers to CLAUDE.md; delegate SerializableBranch deserialization to from_gitmodules Co-authored-by: bashandbone <89049923+bashandbone@users.noreply.github.com> --- CLAUDE.md | 6 ++++++ src/options.rs | 9 +++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index e2860d3..efa544d 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,3 +1,9 @@ + + # CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. diff --git a/src/options.rs b/src/options.rs index 9fb7a8f..5cf5069 100644 --- a/src/options.rs +++ b/src/options.rs @@ -402,13 +402,14 @@ impl Serialize for SerializableBranch { } impl<'de> Deserialize<'de> for SerializableBranch { - /// Deserialize from a plain string using the same logic as [`FromStr`]. + /// Deserialize from a plain string, delegating to [`from_gitmodules`](GitmodulesConvert::from_gitmodules). /// Accepts `"."`, `"current"`, `"current-in-super-project"`, `"superproject"`, or `"super"` - /// as [`CurrentInSuperproject`](SerializableBranch::CurrentInSuperproject); all other strings - /// become [`Name`](SerializableBranch::Name). + /// as [`CurrentInSuperproject`](SerializableBranch::CurrentInSuperproject); all other + /// non-empty, non-whitespace strings become [`Name`](SerializableBranch::Name). + /// Empty or whitespace-only strings are rejected with a deserialization error. fn deserialize>(deserializer: D) -> Result { let s = String::deserialize(deserializer)?; - SerializableBranch::from_str(&s) + SerializableBranch::from_gitmodules(&s) .map_err(|_| serde::de::Error::custom(format!("invalid branch value: {s}"))) } } From 2146de868938b212139db3ade6166e6de48285b3 Mon Sep 17 00:00:00 2001 From: Adam Poulemanos <89049923+bashandbone@users.noreply.github.com> Date: Thu, 19 Mar 2026 10:24:35 -0400 Subject: [PATCH 3/3] Apply suggestions from code review Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- src/options.rs | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/src/options.rs b/src/options.rs index 5cf5069..5eaeb5e 100644 --- a/src/options.rs +++ b/src/options.rs @@ -447,7 +447,10 @@ impl GitmodulesConvert for SerializableBranch { || options == "current-in-super-project" || options == "superproject" || options == "super" - || options == SerializableBranch::current_in_superproject().unwrap_or_default() + || SerializableBranch::current_in_superproject() + .ok() + .as_deref() + .map_or(false, |cur| cur == options) { return Ok(SerializableBranch::CurrentInSuperproject); } @@ -465,6 +468,34 @@ impl GitmodulesConvert for SerializableBranch { } } +#[cfg(test)] +mod tests { + use super::SerializableBranch; + + #[test] + fn test_branch_deserialize_from_toml_rejects_empty_and_whitespace() { + // Empty string should be rejected + let res_empty: Result = + toml::from_str(r#"branch = """"#); + assert!(res_empty.is_err(), "expected error for empty branch value"); + let err_empty = res_empty.unwrap_err().to_string(); + assert!( + err_empty.contains("invalid branch value"), + "error for empty branch value should contain context, got: {err_empty}" + ); + + // Whitespace-only string should be rejected + let res_ws: Result = + toml::from_str(r#"branch = " ""#); + assert!(res_ws.is_err(), "expected error for whitespace-only branch value"); + let err_ws = res_ws.unwrap_err().to_string(); + assert!( + err_ws.contains("invalid branch value"), + "error for whitespace-only branch value should contain context, got: {err_ws}" + ); + } +} + impl TryFrom for SerializableBranch { type Error = ();