Sidebar file tree: ancestor refresh fix + VS Code-style git decorations#10078
Sidebar file tree: ancestor refresh fix + VS Code-style git decorations#10078fazxes wants to merge 1 commit intowarpdotdev:masterfrom
Conversation
Two related improvements to the sidebar file tree:
1. Fix: refresh ancestor-displayed roots on FileTreeEntryUpdated.
Previously, FileTreeView::handle_repository_metadata_event filtered
roots by exact path equality, so when a displayed root was a common
ancestor of an indexed repository (collapsed via group_roots_by_common_ancestor),
updates routed to the nested repo's path were silently dropped and the
tree never rebuilt. Now ancestor roots also trigger rebuild_flattened_items
without clobbering their entry.
2. Feature: VS Code-style git decorations.
- New repo_metadata::git_status module wraps git2 to compute per-file
status (Modified, Added, Untracked, Deleted, Conflict, Renamed, Ignored).
- LocalRepoMetadataModel caches statuses + dirty-dir rollup; recomputes
off-thread on every watcher event, treats .git/ internals as a full-repo
refresh, reuses FileTreeEntryUpdated for UI propagation.
- RepoMetadataModel exposes git_status_for / is_dirty_dir to consumers.
- FileTreeView renders a letter badge (M/A/U/C/R) + filename color tint,
with a dim dot rolled up onto parent directories. Deleted is intentionally
omitted in v1 because deleted files are removed from the tree.
Tests: status reader unit (real temp git repo), model cache + dirty-dir,
view-level decoration mapping. cargo check -p repo_metadata and
cargo check -p warp both clean.
|
Thank you for your pull request and welcome to our community. We could not parse the GitHub identity of the following contributors: Pranit Sharma.
|
|
I'm starting a first review of this pull request. You can view the conversation on Warp. I completed the review and no human review was requested for this pull request. Comment Powered by Oz |
fb3153f to
cee704c
Compare
|
Thank you for your pull request and welcome to our community. We could not parse the GitHub identity of the following contributors: Pranit Sharma.
|
There was a problem hiding this comment.
Overview
This PR adds local git-status decoration support to the sidebar file tree and adjusts metadata refresh handling for ancestor-displayed roots.
Concerns
- The new
git2dependency is unconditional even though all runtime usage isnot(target_family = "wasm"), which can break wasm builds forrepo_metadata. - Ignored statuses are included in dirty-directory rollups, so repositories with ignored build outputs can show dirty dots even when there are no real git changes.
- Full status refreshes recurse through ignored directories, which can be expensive for common ignored trees such as
target/ornode_modules/. - This is a user-visible UI change, but the PR description does not include screenshots or video. For faster review, please upload screenshots or a video of the feature working end to end.
Verdict
Found: 0 critical, 4 important, 0 suggestions
Request changes
Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).
Powered by Oz
| notify-debouncer-full.workspace = true | ||
| async-fs.workspace = true | ||
| watcher.workspace = true | ||
| git2 = { version = "0.20.4", default-features = false, features = [ |
There was a problem hiding this comment.
git2 is only used behind not(target_family = "wasm"), but this dependency is unconditional; move it under a matching target-specific dependency section so wasm builds of repo_metadata do not try to build/link libgit2.
| .include_untracked(true) | ||
| .include_ignored(true) | ||
| .recurse_untracked_dirs(true) | ||
| .recurse_ignored_dirs(true) |
There was a problem hiding this comment.
target/ or node_modules/ can spend a long time in status refresh and allocate huge status caches; avoid recursing ignored dirs or make ignored status collection scoped to visible paths.
| }; | ||
|
|
||
| let mut dirty_dirs = HashSet::new(); | ||
| for path in statuses.keys() { |
There was a problem hiding this comment.
GitStatus::Ignored out of dirty rollups or avoid storing ignored statuses as dirty descendants.
Summary
FileTreeView::handle_repository_metadata_eventdropsFileTreeEntryUpdatedevents routed to the longest-matching repo path (viaLocalRepoMetadataModel::find_repository_for_path_string), so the tree never rebuilds. Fix matches roots whoseentry.root_directory()is a strict ancestor of the updated path; preserves existing exact-match behavior.FileTreeEntryUpdated.Why
The bug fix is small (~30 lines) and catches a real correctness gap. The decoration feature is independent but lands cleanly on top of the same update path.
Implementation notes
repo_metadata::git_statusmodule (uses the existing vendoredlibgit2already inapp/Cargo.toml; addedgit2dep torepo_metadata/Cargo.toml).LocalRepoMetadataModelgetsgit_statusesanddirty_dirscaches; recomputes off-thread inside the existingctx.spawnblock inhandle_watcher_event..git/internal events trigger a full-repo refresh, normal events use scoped pathspecs.RepoMetadataModel(wrapper) exposesgit_status_forandis_dirty_dirfor consumers.FileTreeGitDecorationenum;render_itemwas extended to receive&AppContext.ui_yellow_color,ansi_fg_red) and editor diff helpers (add_color) — no raw RGB.Deletedstatus is mapped by the reader but skipped in the view in this version: deleted files are removed from the tree byFileTreeMutation::Remove, so there's no row to decorate. Matches VS Code Explorer behavior (deletions surface in the SCM panel).Tests
git_status::tests::statuses_for_repo_maps_modified_untracked_added_and_ignored— uses a real temp git repo (init, commit baseline, modify/untrack/ignore/stage), asserts the enum mapping.local_model::tests::git_status_recompute_marks_modified_file_and_dirty_ancestors— model-level cache + rollup test.view_tests::git_status_decorations_update_for_ancestor_displayed_root— view-level: ancestor-displayed root with a nested modified file, asserts decoration mapping (badgeM, modified color). The existing harness has no precedent for asserting renderedTextcolor directly; falls back to model-state + decoration assertions.Test plan
cargo check -p repo_metadatacargo check -p warpcargo test -p repo_metadata git_statuscargo test -p warp git_status_decorations_update_for_ancestor_displayed_root./script/run --release) launches successfullyCHANGELOG-IMPROVEMENT: File tree shows VS Code-style git status decorations and refreshes ancestor-displayed roots when nested repos change.
🤖 Generated with Claude Code