Skip to content

better git ui and management#8

Merged
anirudhisonline merged 3 commits into
mainfrom
git-glowup
May 14, 2026
Merged

better git ui and management#8
anirudhisonline merged 3 commits into
mainfrom
git-glowup

Conversation

@anirudhisonline
Copy link
Copy Markdown
Contributor

@anirudhisonline anirudhisonline commented May 14, 2026

Summary by CodeRabbit

  • New Features

    • Branch deletion (with optional force)
    • File/dir context menus: discard, ignore patterns, copy paths, reveal, open, discard-all dialog
    • Env-file deletion and gitignore toggling
    • Commands to discard changes, add to .gitignore, and open files with the OS default
  • Improvements

    • Virtualized file list for large repos; debounced file-change handling and watcher generation control
    • Worktree change tick to signal bulk worktree updates
    • Desktop reveal/open capability permissions extended and CLI allowlist expanded
  • Chores

    • Dev dependency minor version bump

Review Change Stack

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 14, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 99535e6b-e576-4012-8e42-a7bb74f60f7e

📥 Commits

Reviewing files that changed from the base of the PR and between 16f8c46 and 9a13389.

📒 Files selected for processing (2)
  • src-tauri/src/commands/git.rs
  • src-tauri/src/commands/watcher.rs
🚧 Files skipped from review as they are similar to previous changes (2)
  • src-tauri/src/commands/watcher.rs
  • src-tauri/src/commands/git.rs

📝 Walkthrough

Walkthrough

Adds backend git commands and StatusResult shape, selective async file-watching with generation tracking, virtualized Git file-tree and context menus, debounced GitChanges loading with discard-all, workspace worktree tick support, and Tauri capability/config updates.

Changes

Git Operations and File Management

Layer / File(s) Summary
Tauri capabilities and configuration
src-tauri/capabilities/default.json, src-tauri/capabilities/folder-windows.json, .claude/settings.json, package.json
Add opener:allow-open-path and opener:allow-reveal-item-in-dir permissions; expand Claude allowlist; bump @lucide/svelte to ^1.16.0.
Tauri state and handler registration
src-tauri/src/lib.rs
Add AtomicU64 imports; change managed WatcherState to (Mutex::new(None), Arc::new(AtomicU64::new(0))); register new git/discard/gitignore/open handlers.
Watcher selective setup & background debouncer
src-tauri/src/commands/watcher.rs
Add Arc<AtomicU64> generation to WatcherState; introduce SKIP_DIRS and setup_watches; spawn background thread for debouncer creation; normalize and emit fs:changed batches; conditionally store debouncer by generation.
Git status contract and result type
src-tauri/src/commands/git.rs
Introduce StatusResult { files, total } and STATUS_LIMIT; git_status now runs --no-optional-locks, counts total porcelain lines while parsing up to the limit, and returns { files, total }.
Git utilities and file operations
src-tauri/src/commands/git.rs
Add git_delete_branch (optional force), git_discard_all, git_discard_file (staged+worktree fallback), git_add_to_gitignore (read/create/dedupe/append), and open_file_default.
Frontend command bindings
src/lib/commands/git.js
Update gitStatus JSDoc to { files, total }; add wrappers: gitDeleteBranch, gitDiscardAll, gitDiscardFile, gitAddToGitignore, openFileDefault.
GitPanel branch deletion
src/lib/components/panels/GitPanel.svelte
Import gitDeleteBranch and Trash2; add deletion state and handleDeleteBranch; per-branch inline delete/force confirmation UI with unmerged error handling.
GitFileTree virtual scrolling & menus
src/lib/components/panels/GitFileTree.svelte
Replace recursive tree with flattened virtual list (ResizeObserver, visible slice); add per-row ContextMenu actions (discard, ignore patterns, copy paths, reveal, open-with-default); refactor status helpers.
GitChanges debounced loading & discard-all
src/lib/components/panels/GitChanges.svelte
Track totalFiles and RUST_LIMIT; implement scheduleLoad() debounce on worktreeChangeTick; update load() to use { files, total }; add discard-all AlertDialog and handler; show truncated banner; wire GitFileTree callbacks.
Workspace worktree tick & layout batching
src/lib/stores/workspace.svelte.js, src/routes/app/+layout.svelte
Add worktreeChangeTick and bumpWorktree() to workspace; cap per-batch bumpFileTick calls to first 20 paths and emit a single bumpWorktree() per watcher batch for non-.git/ changes.
EnvPanel context menus and deletion
src/lib/components/panels/EnvPanel.svelte
Add context menu and AlertDialog; add delete/gitignore toggle handlers, show-in-Explorer and copy helpers; replace row UI with ContextMenu and add delete confirmation dialog.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Possibly related PRs

Poem

🐰 I scurried through files with nimble paws,
Added commands and slimmed watcher claws,
Virtual lists now hop past with grace,
Discard and delete: a single-click embrace,
Branches fall gently — a tidy code-lawn applause.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'better git ui and management' is directly related to the main changes—enhanced Git UI (discard workflows, branch deletion, file tree virtualization, context menus) and new management commands (git discard, gitignore, file opening).
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch git-glowup

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

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src-tauri/src/commands/git.rs`:
- Around line 746-768: open_file_default contains a command-injection risk on
Windows because it shells the unescaped path through cmd; replace the manual
platform-specific Command::new(...) calls inside the open_file_default function
with the tauri-plugin-opener API (use its open function that accepts the path
and safely handles escaping across platforms) so you no longer invoke
cmd/xdg-open/open directly; if you cannot use tauri-plugin-opener for some
reason, validate the incoming path in open_file_default to ensure it is a real
file path (reject null bytes, shell metacharacters like &, |, >, ;, &&, ||) and
use std::fs and platform-safe launching APIs rather than passing the raw string
to a shell.

In `@src-tauri/src/commands/watcher.rs`:
- Around line 67-97: The current setup_watches only registers
RecursiveMode::Recursive for existing depth-2 dirs, so new folders created later
are never watched; update setup_watches to register recursive watches for each
depth-1 directory (the debouncer.watch call for variable d1) instead of
NonRecursive so new subdirectories created under d1 are covered, keeping the
is_skip_dir checks; alternatively (if you prefer finer control) add logic in
your watcher event loop to handle Create directory events and call
debouncer.watch(new_path, RecursiveMode::Recursive) for the created dirs—refer
to setup_watches, debouncer.watch, and is_skip_dir to locate and implement this
change.
- Around line 117-172: The spawned watcher thread can overwrite shared watcher
state and emit for the wrong project if a newer unwatch/watch happened; fix by
binding a unique watcher/session id or the canonical project_path snapshot when
creating the debouncer (use project_path or a generated u64 token) and before
calling setup_watches, before emitting via app_for_events.emit, and before
storing into watcher_state (WatcherState) compare the current global expected
id/path in app_clone.state with the thread's id/path and abort if they differ;
ensure new_debouncer, setup_watches, and the emission/store paths all check this
identifier so stale threads neither overwrite the Option<debouncer> nor emit
events for a different project.

In `@src/lib/components/panels/GitChanges.svelte`:
- Around line 220-222: The displayed "staged" and "changed" counts are
misleading when totalFiles > RUST_LIMIT because stagedCount is computed from the
truncated files array; update the UI in GitChanges.svelte to either compute
counts from the full dataset if available or mark them as approximate when
files.length < totalFiles: use files, stagedCount and totalFiles to detect
truncation (files.length < totalFiles) and then render a clear indication such
as "≈ {stagedCount} staged · ≈ {totalFiles - stagedCount} changed" or "
{stagedCount} staged (showing {files.length} of {totalFiles})" instead of the
current literal counts; apply the same change to the discard confirmation dialog
code that references stagedCount/totalFiles (the dialog block around line ~329)
so both places consistently show accurate-or-approximate counts.

In `@src/lib/components/panels/GitFileTree.svelte`:
- Line 205: The current {`#each` visible as { node, depth } (node.path + depth)}
key risks collisions; change the key expression in the each block to a
deterministic concatenation that cannot ambigously join path and depth (for
example use a template string with a clear separator like
`${node.path}::${depth}`) or, if available, switch to a unique identifier such
as node.id; update the each block key accordingly in GitFileTree.svelte so the
key uses the new non-ambiguous expression instead of node.path + depth.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 73ac72dd-60dd-4f5b-ab66-37c4ef1040cb

📥 Commits

Reviewing files that changed from the base of the PR and between fb287af and d1835d0.

⛔ Files ignored due to path filters (18)
  • bun.lock is excluded by !**/*.lock
  • src/lib/components/ui/context-menu/context-menu-checkbox-item.svelte is excluded by !src/lib/components/ui/**
  • src/lib/components/ui/context-menu/context-menu-content.svelte is excluded by !src/lib/components/ui/**
  • src/lib/components/ui/context-menu/context-menu-group-heading.svelte is excluded by !src/lib/components/ui/**
  • src/lib/components/ui/context-menu/context-menu-group.svelte is excluded by !src/lib/components/ui/**
  • src/lib/components/ui/context-menu/context-menu-item.svelte is excluded by !src/lib/components/ui/**
  • src/lib/components/ui/context-menu/context-menu-label.svelte is excluded by !src/lib/components/ui/**
  • src/lib/components/ui/context-menu/context-menu-portal.svelte is excluded by !src/lib/components/ui/**
  • src/lib/components/ui/context-menu/context-menu-radio-group.svelte is excluded by !src/lib/components/ui/**
  • src/lib/components/ui/context-menu/context-menu-radio-item.svelte is excluded by !src/lib/components/ui/**
  • src/lib/components/ui/context-menu/context-menu-separator.svelte is excluded by !src/lib/components/ui/**
  • src/lib/components/ui/context-menu/context-menu-shortcut.svelte is excluded by !src/lib/components/ui/**
  • src/lib/components/ui/context-menu/context-menu-sub-content.svelte is excluded by !src/lib/components/ui/**
  • src/lib/components/ui/context-menu/context-menu-sub-trigger.svelte is excluded by !src/lib/components/ui/**
  • src/lib/components/ui/context-menu/context-menu-sub.svelte is excluded by !src/lib/components/ui/**
  • src/lib/components/ui/context-menu/context-menu-trigger.svelte is excluded by !src/lib/components/ui/**
  • src/lib/components/ui/context-menu/context-menu.svelte is excluded by !src/lib/components/ui/**
  • src/lib/components/ui/context-menu/index.js is excluded by !src/lib/components/ui/**
📒 Files selected for processing (13)
  • .claude/settings.json
  • package.json
  • src-tauri/capabilities/default.json
  • src-tauri/capabilities/folder-windows.json
  • src-tauri/src/commands/git.rs
  • src-tauri/src/commands/watcher.rs
  • src-tauri/src/lib.rs
  • src/lib/commands/git.js
  • src/lib/components/panels/GitChanges.svelte
  • src/lib/components/panels/GitFileTree.svelte
  • src/lib/components/panels/GitPanel.svelte
  • src/lib/stores/workspace.svelte.js
  • src/routes/app/+layout.svelte

Comment thread src-tauri/src/commands/git.rs
Comment thread src-tauri/src/commands/watcher.rs
Comment thread src-tauri/src/commands/watcher.rs
Comment thread src/lib/components/panels/GitChanges.svelte
Comment thread src/lib/components/panels/GitFileTree.svelte Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
src/lib/components/panels/EnvPanel.svelte (1)

54-58: 💤 Low value

Path separator detection is fragile on Windows with mixed-separator paths.

The separator detection assumes the base path uses consistent separators. On Windows, paths can have mixed separators (e.g., C:/Users\foo). Consider using a more robust approach or letting Tauri/the backend handle path construction.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/lib/components/panels/EnvPanel.svelte` around lines 54 - 58, The absPath
function’s separator detection is fragile because it assumes base uses a single
separator; instead normalize both workspace.folderPath and relPath by replacing
all backslashes and forward slashes with a single canonical separator and then
construct the path using the platform-aware separator from a path utility (e.g.,
path.sep) or, better, use a path-joining helper (e.g., path.join or the
Tauri/backend path API) to concatenate values; update absPath (which reads
workspace.folderPath and relPath) to first normalize/reduce mixed separators,
then join via the platform-aware join/sep routine so mixed Windows paths like
"C:/Users\foo" are handled correctly.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src-tauri/src/commands/git.rs`:
- Around line 791-798: The code trims `pattern` for the de-dup check but writes
the raw `pattern` to the file; change the logic to use a trimmed pattern for
both comparison and writing (e.g., introduce a trimmed variable like
`pattern_trimmed = pattern.trim()` and use it in the existing.lines().any(...)
check and when building `new_content`), preserving the existing newline handling
(use `pattern_trimmed` instead of `pattern` in the format calls) so no
accidental leading/trailing whitespace is written to .gitignore.

In `@src-tauri/src/commands/watcher.rs`:
- Around line 175-183: unwatch_project currently clears the watcher state
(WatcherState) but does not increment the shared generation counter, leaving a
race where a stale background thread started by watch_project can later reattach
a debouncer; modify unwatch_project to acquire the same lock on state.0, set the
guard to None and also increment the associated generation counter (the same
generation field used by watch_project) before returning so any in-flight
threads comparing gen will fail and cannot overwrite cleared state.

---

Nitpick comments:
In `@src/lib/components/panels/EnvPanel.svelte`:
- Around line 54-58: The absPath function’s separator detection is fragile
because it assumes base uses a single separator; instead normalize both
workspace.folderPath and relPath by replacing all backslashes and forward
slashes with a single canonical separator and then construct the path using the
platform-aware separator from a path utility (e.g., path.sep) or, better, use a
path-joining helper (e.g., path.join or the Tauri/backend path API) to
concatenate values; update absPath (which reads workspace.folderPath and
relPath) to first normalize/reduce mixed separators, then join via the
platform-aware join/sep routine so mixed Windows paths like "C:/Users\foo" are
handled correctly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 1697ae0c-773b-45ce-be2a-cd0c356c4016

📥 Commits

Reviewing files that changed from the base of the PR and between d1835d0 and 16f8c46.

📒 Files selected for processing (6)
  • src-tauri/src/commands/git.rs
  • src-tauri/src/commands/watcher.rs
  • src-tauri/src/lib.rs
  • src/lib/components/panels/EnvPanel.svelte
  • src/lib/components/panels/GitChanges.svelte
  • src/lib/components/panels/GitFileTree.svelte
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/lib/components/panels/GitChanges.svelte
  • src/lib/components/panels/GitFileTree.svelte

Comment thread src-tauri/src/commands/git.rs Outdated
Comment thread src-tauri/src/commands/watcher.rs
@anirudhisonline anirudhisonline merged commit e6b1e36 into main May 14, 2026
1 check passed
@anirudhisonline anirudhisonline deleted the git-glowup branch May 14, 2026 19:03
This was referenced May 22, 2026
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