From e2c95a8d842cf1715e3cc08419d4724abf6dc852 Mon Sep 17 00:00:00 2001 From: Mayank Verma Date: Fri, 14 Nov 2025 07:46:38 +0530 Subject: [PATCH] git: Continue parsing other branches when refs have missing fields (#42523) Closes #34684 Release Notes: - (Let's Git Together) Fixed Git panel not showing any branches when repository contains refs with missing fields --- crates/git/src/repository.rs | 81 +++++++++++++++++++++++++++++------- 1 file changed, 67 insertions(+), 14 deletions(-) diff --git a/crates/git/src/repository.rs b/crates/git/src/repository.rs index 2a1cd9478d3079716eda8234c02c8122b9381b38..2c9189962492daa75dba86e9e2ebd247ad85254e 100644 --- a/crates/git/src/repository.rs +++ b/crates/git/src/repository.rs @@ -2387,22 +2387,37 @@ fn parse_branch_input(input: &str) -> Result> { continue; } let mut fields = line.split('\x00'); - let is_current_branch = fields.next().context("no HEAD")? == "*"; - let head_sha: SharedString = fields.next().context("no objectname")?.to_string().into(); - let parent_sha: SharedString = fields.next().context("no parent")?.to_string().into(); - let ref_name = fields.next().context("no refname")?.to_string().into(); - let upstream_name = fields.next().context("no upstream")?.to_string(); - let upstream_tracking = parse_upstream_track(fields.next().context("no upstream:track")?)?; - let commiterdate = fields.next().context("no committerdate")?.parse::()?; - let author_name = fields.next().context("no authorname")?.to_string().into(); - let subject: SharedString = fields - .next() - .context("no contents:subject")? - .to_string() - .into(); + let Some(head) = fields.next() else { + continue; + }; + let Some(head_sha) = fields.next().map(|f| f.to_string().into()) else { + continue; + }; + let Some(parent_sha) = fields.next().map(|f| f.to_string()) else { + continue; + }; + let Some(ref_name) = fields.next().map(|f| f.to_string().into()) else { + continue; + }; + let Some(upstream_name) = fields.next().map(|f| f.to_string()) else { + continue; + }; + let Some(upstream_tracking) = fields.next().and_then(|f| parse_upstream_track(f).ok()) + else { + continue; + }; + let Some(commiterdate) = fields.next().and_then(|f| f.parse::().ok()) else { + continue; + }; + let Some(author_name) = fields.next().map(|f| f.to_string().into()) else { + continue; + }; + let Some(subject) = fields.next().map(|f| f.to_string().into()) else { + continue; + }; branches.push(Branch { - is_head: is_current_branch, + is_head: head == "*", ref_name, most_recent_commit: Some(CommitSummary { sha: head_sha, @@ -2744,6 +2759,44 @@ mod tests { ) } + #[test] + fn test_branches_parsing_containing_refs_with_missing_fields() { + #[allow(clippy::octal_escapes)] + let input = " \090012116c03db04344ab10d50348553aa94f1ea0\0refs/heads/broken\n \0eb0cae33272689bd11030822939dd2701c52f81e\0895951d681e5561478c0acdd6905e8aacdfd2249\0refs/heads/dev\0\0\01762948725\0Zed\0Add feature\n*\0895951d681e5561478c0acdd6905e8aacdfd2249\0\0refs/heads/main\0\0\01762948695\0Zed\0Initial commit\n"; + + let branches = parse_branch_input(input).unwrap(); + assert_eq!(branches.len(), 2); + assert_eq!( + branches, + vec![ + Branch { + is_head: false, + ref_name: "refs/heads/dev".into(), + upstream: None, + most_recent_commit: Some(CommitSummary { + sha: "eb0cae33272689bd11030822939dd2701c52f81e".into(), + subject: "Add feature".into(), + commit_timestamp: 1762948725, + author_name: SharedString::new("Zed"), + has_parent: true, + }) + }, + Branch { + is_head: true, + ref_name: "refs/heads/main".into(), + upstream: None, + most_recent_commit: Some(CommitSummary { + sha: "895951d681e5561478c0acdd6905e8aacdfd2249".into(), + subject: "Initial commit".into(), + commit_timestamp: 1762948695, + author_name: SharedString::new("Zed"), + has_parent: false, + }) + } + ] + ) + } + impl RealGitRepository { /// Force a Git garbage collection on the repository. fn gc(&self) -> BoxFuture<'_, Result<()>> {