From 5a93d0256f1943ecadd247761b209b035be4dd52 Mon Sep 17 00:00:00 2001 From: Evan Richter Date: Thu, 22 Jan 2026 13:18:57 -0700 Subject: [PATCH] fix: handle 'no commits yet' status with remote The status parser crashed when opening a repo with no commits but with a remote configured, where git outputs: ## No commits yet on main...origin/main [gone] Updated parse_no_commits to handle the optional remote and ahead/behind info, matching the behavior of parse_branch_status. --- src/git/parse/status/mod.rs | 43 ++++++++++++++++++++++++++++++------- 1 file changed, 35 insertions(+), 8 deletions(-) diff --git a/src/git/parse/status/mod.rs b/src/git/parse/status/mod.rs index 8929d79438..a50ba0cc18 100644 --- a/src/git/parse/status/mod.rs +++ b/src/git/parse/status/mod.rs @@ -56,14 +56,22 @@ fn parse_branch_line(input: &str) -> IResult<&str, BranchStatus> { } fn parse_no_commits(input: &str) -> IResult<&str, BranchStatus> { - map(preceded(tag("No commits yet on "), parse_branch), |local| { - BranchStatus { - local: Some(local.to_string()), - remote: None, - ahead: 0, - behind: 0, - } - }) + map( + ( + preceded(tag("No commits yet on "), parse_branch), + opt(preceded(tag("..."), parse_branch)), + opt(preceded(space1, parse_ahead_behind)), + ), + |(local, remote, ahead_behind)| { + let (ahead, behind) = ahead_behind.unwrap_or((0, 0)); + BranchStatus { + local: Some(local.to_string()), + remote: remote.map(|s| s.to_string()), + ahead, + behind, + } + }, + ) .parse(input) } @@ -399,6 +407,25 @@ mod tests { assert_eq!(result.branch_status.remote, None); } + #[test] + fn no_commits_yet_with_remote() { + let input = "## No commits yet on main...origin/main\n"; + let result = Status::from_str(input).unwrap(); + assert_eq!(result.branch_status.local, Some("main".to_string())); + assert_eq!(result.branch_status.remote, Some("origin/main".to_string())); + } + + #[test] + fn no_commits_yet_with_remote_gone() { + let input = "## No commits yet on main...origin/main [gone]\n?? .gitignore\n"; + let result = Status::from_str(input).unwrap(); + assert_eq!(result.branch_status.local, Some("main".to_string())); + assert_eq!(result.branch_status.remote, Some("origin/main".to_string())); + assert_eq!(result.branch_status.ahead, 0); + assert_eq!(result.branch_status.behind, 0); + assert_eq!(result.files[0].path, ".gitignore"); + } + #[test] fn all_file_status_codes() { let input = r#"## master