Sidebar file tree: ancestor refresh fix + VS Code-style git decorations#6
Sidebar file tree: ancestor refresh fix + VS Code-style git decorations#6fazxes wants to merge 2 commits into
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.
Fork-only files. CLAUDE.md is a copy of WARP.md so Claude Code reads the same project guidance; AGENTS.md is a symlink to CLAUDE.md so any AGENTS-aware tooling converges on the same content. The design spec records the brainstorming + audit decisions behind the git decorations feature shipped in the previous commit.
2b47b3c to
303f895
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2b47b3c85e
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| for path in statuses.keys() { | ||
| for ancestor in path.ancestors().skip(1) { |
There was a problem hiding this comment.
Exclude ignored paths from dirty-directory rollups
recompute_dirty_dirs marks ancestors dirty for every cached status entry, but it never filters out GitStatus::Ignored. Since the new status reader includes ignored files, repositories with only ignored artifacts can still populate dirty_dirs, causing persistent dirty dots on parent directories/root even when there are no actionable git changes. Filtering ignored statuses out of the rollup keeps directory decorations consistent with actual dirty state.
Useful? React with 👍 / 👎.
| .include_ignored(true) | ||
| .recurse_untracked_dirs(true) | ||
| .recurse_ignored_dirs(true) |
There was a problem hiding this comment.
Avoid recursive ignored-file scans in status refresh
The new status options recurse through ignored directories for every refresh, and spawn_full_git_status_refresh invokes this with pathspec=None on initial load. In repos with large ignored trees (for example node_modules or build outputs), this can force a full walk and caching of ignored files, significantly increasing startup latency and memory for decorations. Disabling recursive ignored traversal (or limiting it to explicitly requested paths) would prevent this regression.
Useful? React with 👍 / 👎.
Summary
Changes
app/src/code/file_tree/view.rshandle_repository_metadata_event;FileTreeGitDecorationenum;render_itemthreads&AppContext; right-edge badge + parent dirty dotcrates/repo_metadata/src/git_status.rs(new)git2-backed status reader, scoped pathspec support, returnsHashMap<StandardizedPath, GitStatus>crates/repo_metadata/src/local_model.rsgit_statuses+dirty_dirscache; off-thread recompute inhandle_watcher_event;.git/events trigger full-repo refresh; cleanup onremove_repositorycrates/repo_metadata/src/wrapper_model.rsgit_status_forandis_dirty_direxposed throughRepoMetadataModeldocs/superpowers/specs/2026-05-04-git-decorations-design.mdDesign notes
rebuild_flattened_items(does NOT clobberroot_dir.entry).Deletedstatus is mapped by the reader for completeness but skipped in the view — deleted files have no tree row in v1 (matches VS Code Explorer behavior; the SCM panel is the right home for that).WarpThememethods (ui_yellow_color,ansi_fg_red) and editor diff helpers (add_color); no raw RGB.Test plan
cargo check -p repo_metadatacleancargo check -p warpcleancargo test -p repo_metadata git_status -- --nocapture(2 tests pass)cargo test -p warp git_status_decorations_update_for_ancestor_displayed_root -- --nocapture(1 test passes)./script/run --release) succeeds and launchesMbadge yellow within ~1s; new file →Ubadge green; staged →A; collapse parent of modified file → dim ● dot🤖 Generated with Claude Code