Skip to content

fix(core): stop labelling unclassified git statuses as clean - #863

Open
kevin9327 wants to merge 1 commit into
dmtrKovalenko:mainfrom
kevin9327:fix/git-status-conflicted
Open

fix(core): stop labelling unclassified git statuses as clean#863
kevin9327 wants to merge 1 commit into
dmtrKovalenko:mainfrom
kevin9327:fix/git-status-conflicted

Conversation

@kevin9327

@kevin9327 kevin9327 commented Sep 9, 2026

Copy link
Copy Markdown

The defect

A merge-conflicted file is reported as clean.

format_git_status_opt ends with:

} else if status.contains(Status::CURRENT) || status.is_empty() {
    Some("clean")
} else {
    None
}

GIT_STATUS_CURRENT is 0 in libgit2, so git2::Status::CURRENT is the empty
bitflag and status.contains(Status::CURRENT) is vacuously true for every
status. Every state the chain does not name explicitly therefore falls out as
clean, and the else { None } arm — plus format_git_status's
unwrap_or("unknown") — is unreachable.

The states that hit it: CONFLICTED, WT_TYPECHANGE, INDEX_TYPECHANGE,
INDEX_RENAMED.

CONFLICTED genuinely reaches this function: fuzz_git_watcher_stress.rs
already asserts "picker must surface CONFLICTED after merge". So after a
conflicted merge the picker shows those files as clean, and since #845 the MCP
output drops the annotation entirely rather than flagging anything.

The Lua layer is already set up for the fallback — GIT_LABELS in
lua/fff/file_picker/file_info.lua carries unknown = '?', a label the Rust
side could never produce.

The fix

Test is_empty() and let anything else fall through to the existing unknown
fallback, as the code was written to do.

Verification (Windows, default ripgrep features)

RUSTUP_TOOLCHAIN was pinned to 1.98.0-x86_64-pc-windows-msvc because
rust-toolchain.toml's stable channel could not update on this machine.

Before, cargo test -p fff-search --lib -- git:::

test git::tests::unclassified_status_is_not_reported_as_clean ... FAILED

---- git::tests::unclassified_status_is_not_reported_as_clean stdout ----

thread 'git::tests::unclassified_status_is_not_reported_as_clean' (41116) panicked at crates\fff-core\src\git.rs:198:9:
assertion `left == right` failed
  left: Some("clean")
 right: None

test result: FAILED. 1 passed; 1 failed; 0 ignored; 0 measured; 158 filtered out

After:

test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 158 filtered out

The same test pins every label that must not move — None, Status::empty()
and Status::CURRENT all still read clean, and untracked / modified /
staged_modified / ignored are unchanged. Those assertions pass both before
and after, so only the previously-misfiled states move.

  • cargo test -p fff-search --lib — 160 passed, 0 failed.
  • cargo test -p fff-mcp --bins — 22 passed, 0 failed (covers
    suffix_omits_clean_git_status and suffix_keeps_dirty_git_status).
  • cargo fmt --all -- --check — clean.

Summary by CodeRabbit

  • Bug Fixes
    • Git status reporting now correctly identifies conflicted and type-changed files instead of incorrectly labeling them as clean.
    • Existing recognized Git status labels remain unchanged.

@coderabbitai

coderabbitai Bot commented Sep 9, 2026

Copy link
Copy Markdown

Review Change StackReview Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Advanced

Run ID: d64472d3-0338-4317-b9e0-837d85be2b92

📥 Commits

Reviewing files that changed from the base of the PR and between 7f8537e and 65d48d3.

📒 Files selected for processing (1)
  • crates/fff-core/src/git.rs

Included review availability: Your plan provides up to 10 included reviews per hour; 7 remain after this review.


📝 Walkthrough

Walkthrough

The Git status formatter now reports clean only for empty statuses. Conflicted and typechanged statuses return unknown. Tests verify these results and preserve existing labels.

Changes

Git status classification

Layer / File(s) Summary
Status formatting and regression tests
crates/fff-core/src/git.rs
format_git_status_opt uses status.is_empty() instead of checking Status::CURRENT. Tests cover conflicted, typechanged, empty, current, modified, new, and ignored statuses.

Priority: ⬇️ Low

Estimated code review effort: 1 (Trivial) | ~5 minutes

Merge Risk: ⚪ Minimal · up to 65d48

Git status output now correctly reports unclassified states as unknown rather than clean, with existing recognized status labels preserved. No current merge-blocking risk remains.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 3 functions across 1 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: unclassified Git statuses are no longer labelled as clean.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
  • Fix all pre-merge checks with AI
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant