git: Fix panic on duplicate status entries in git status parsing (#49191)
## Summary Fixes **ZED-2XA** — "Unexpected duplicated status entries: Untracked and Untracked" crash. **Impact:** 22 occurrences, 3 users affected (Sentry). The panic was introduced in #23483 (2025-01-22) which added the `dedup_by` logic for handling deleted-in-index + untracked file combinations. No related GitHub issues were found filed against this crash. ## Root Cause `GitStatus::from_str` sorts entries by path and then calls `dedup_by` to merge duplicate entries. The only handled case was `(INDEX_DELETED, Untracked)` — all other duplicates hit a catch-all `panic!`. In practice, git can produce duplicate `??` (untracked) entries for the same path, which triggered this crash. ## Fix - Identical duplicate statuses (e.g., `Untracked, Untracked`) are now silently deduplicated (keep one) - Other unexpected duplicate combinations log a warning instead of crashing - Added a regression test that parses `"?? file.txt\0?? file.txt"` and verifies it produces a single entry ## Verification - Reproduction test passes: `cargo test -p git -- test_duplicate_untracked_entries` - Full crate tests pass: `cargo test -p git` (20/20) - Clippy clean: `./script/clippy` Release Notes: - Fixed a crash when git produces duplicate status entries for the same file path Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
This commit is contained in:
1 parent
0d3fbfafc8
commit
f870128f7b
1 file changed
+17
-2
@@ -475,7 +475,12 @@ impl FromStr for GitStatus {
|
||||
}
|
||||
.into();
|
||||
}
|
||||
_ => panic!("Unexpected duplicated status entries: {a_status:?} and {b_status:?}"),
|
||||
(x, y) if x == y => {}
|
||||
_ => {
|
||||
log::warn!(
|
||||
"Unexpected duplicated status entries: {a_status:?} and {b_status:?}"
|
||||
);
|
||||
}
|
||||
}
|
||||
true
|
||||
});
|
||||
@@ -580,9 +585,19 @@ mod tests {
|
||||
|
||||
use crate::{
|
||||
repository::RepoPath,
|
||||
status::{TreeDiff, TreeDiffStatus},
|
||||
status::{FileStatus, GitStatus, TreeDiff, TreeDiffStatus},
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn test_duplicate_untracked_entries() {
|
||||
// Regression test for ZED-2XA: git can produce duplicate untracked entries
|
||||
// for the same path. This should deduplicate them instead of panicking.
|
||||
let input = "?? file.txt\0?? file.txt";
|
||||
let status: GitStatus = input.parse().unwrap();
|
||||
assert_eq!(status.entries.len(), 1);
|
||||
assert_eq!(status.entries[0].1, FileStatus::Untracked);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_tree_diff_parsing() {
|
||||
let input = ":000000 100644 0000000000000000000000000000000000000000 0062c311b8727c3a2e3cd7a41bc9904feacf8f98 A\x00.zed/settings.json\x00".to_owned() +
|
||||
|
||||
Reference in new issue
Block a user