[PR #503] [MERGED] Scope Git watching and status to the sync directory #3352

Closed
opened 2026-07-15 02:03:05 -05:00 by GiteaMirror · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/mountain-loop/yaak/pull/503
Author: @gschier
Created: 7/9/2026
Status: Merged
Merged: 7/9/2026
Merged by: @gschier

Base: mainHead: scope-git-watcher


📝 Commits (9)

  • a49e8c1 Scope Git watching and status to the sync directory
  • 564b4ed Rename External file changes to Other files, sync-relative paths
  • 6d02ea0 Commit only the files checked in the commit dialog
  • 3f40df7 Address review: worktree refs, Windows pathspecs, symlink scoping
  • b0a2d23 Address review: literal pathspec matching, branch info refresh
  • a415b56 Derive staged sync-dir files at commit time instead of passing paths
  • 10def00 Make scoped status options the constructor, scope commit and pull
  • 668b22a Revert branch-info invalidation from watch events
  • 8d7a4e0 Let git scope the staged-file listing, run from the repo root

📊 Changes

9 files changed (+260 additions, -26 deletions)

View changed files

📝 Cargo.lock (+1 -0)
📝 apps/yaak-client/components/git/GitCommitDialog.tsx (+10 -2)
📝 crates-tauri/yaak-app-client/src/git_watcher.rs (+30 -8)
📝 crates/yaak-git/Cargo.toml (+4 -0)
📝 crates/yaak-git/bindings/gen_git.ts (+6 -1)
📝 crates/yaak-git/src/commit.rs (+87 -2)
📝 crates/yaak-git/src/pull.rs (+5 -2)
📝 crates/yaak-git/src/repository.rs (+8 -1)
📝 crates/yaak-git/src/status.rs (+109 -10)

📄 Description

What

Fixes https://yaak.app/feedback/posts/linux-app-consistently-uses-100-cpu-when-idle

With a sync folder inside a large busy repo (monorepo with vendor dirs, node_modules, build churn):

  • The Git watcher watched the entire containing repository, so every file event anywhere in the repo ran an ignore-check, and every non-ignored event triggered two full status walks (immediate + post-settle). On Linux (inotify, no App Nap throttling) this pegs a core constantly. Reproduced on macOS at 100.9% CPU during event bursts; macOS's FSEvents coalescing otherwise masks it.
  • The commit dialog's status walked the full worktree with include_unmodified, loading previous blob content for every tracked file in the repo, and listed every dirty repo file under "External file changes".
  • git commit committed the entire index, so files staged outside Yaak (e.g. in the containing monorepo) were silently swept into Yaak commits.
  • Pull refused to run whenever anything in the containing repo was dirty — its uncommitted-changes check walked the whole worktree, making pull permanently unusable in a busy monorepo.

How

  • The watcher covers only the sync directory, plus the Git metadata that affects branch/status info: top-level gitdir (HEAD, index, packed-refs) non-recursively and refs/ recursively — skipping the churn-heavy objects/
  • Both status functions (git_worktree_status, git_status) are pathspec-scoped to the requested directory via a shared helper — a no-op when the sync dir is the repo root, so standalone repos behave exactly as before
  • Commits derive the staged files under the sync dir at commit time and pass them as pathspecs (git commit -- <files>), so a Yaak commit contains exactly what the dialog shows; externally staged files are untouched and stay staged
  • Status walks are built through a single scoped_status_options constructor so new call sites can't forget the scoping — which is how the pull check was found; it's now scoped too (git merge still refuses to clobber uncommitted files outside the sync dir)
  • The "External file changes" section is renamed to "Other files" (it now only ever shows non-Yaak files within the sync folder — its original purpose) and paths display relative to the sync directory

Testing

  • Unit tests for both status functions: subdir-scoped walks report only subdir files (with correct relaDir), repo-root walks report everything
  • Repro repo (React + 93k-file ignored tree + 30k-file untracked tree + 50ms churn script): commit dialog went from seconds to instant and lists only sync-dir files; sidebar git indicators still update on request changes; branch info still refreshes on terminal commits
  • Pending: verification on a Linux box, where the original report came from

🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/mountain-loop/yaak/pull/503 **Author:** [@gschier](https://github.com/gschier) **Created:** 7/9/2026 **Status:** ✅ Merged **Merged:** 7/9/2026 **Merged by:** [@gschier](https://github.com/gschier) **Base:** `main` ← **Head:** `scope-git-watcher` --- ### 📝 Commits (9) - [`a49e8c1`](https://github.com/mountain-loop/yaak/commit/a49e8c167b4a3cb4505242fe9bf1133d2c78e93c) Scope Git watching and status to the sync directory - [`564b4ed`](https://github.com/mountain-loop/yaak/commit/564b4edf10e95dbf69ffbad7e63f2ee9dc112afa) Rename External file changes to Other files, sync-relative paths - [`6d02ea0`](https://github.com/mountain-loop/yaak/commit/6d02ea03e8d6aaebd3b8f9a4be97a386cbc1ce7b) Commit only the files checked in the commit dialog - [`3f40df7`](https://github.com/mountain-loop/yaak/commit/3f40df71d0fc4185779346624fde52beda0cdc81) Address review: worktree refs, Windows pathspecs, symlink scoping - [`b0a2d23`](https://github.com/mountain-loop/yaak/commit/b0a2d233a629e8c56f6d0061fae00ac00c281873) Address review: literal pathspec matching, branch info refresh - [`a415b56`](https://github.com/mountain-loop/yaak/commit/a415b5603836ad5c62d8133ed351030cffe50e19) Derive staged sync-dir files at commit time instead of passing paths - [`10def00`](https://github.com/mountain-loop/yaak/commit/10def00974fa2a79bf843f2545ab43d028b47a31) Make scoped status options the constructor, scope commit and pull - [`668b22a`](https://github.com/mountain-loop/yaak/commit/668b22a34815c4ac6d8171e6d708b528a63fd16f) Revert branch-info invalidation from watch events - [`8d7a4e0`](https://github.com/mountain-loop/yaak/commit/8d7a4e058823cf9a03a444a5d06ed5382d5f04a3) Let git scope the staged-file listing, run from the repo root ### 📊 Changes **9 files changed** (+260 additions, -26 deletions) <details> <summary>View changed files</summary> 📝 `Cargo.lock` (+1 -0) 📝 `apps/yaak-client/components/git/GitCommitDialog.tsx` (+10 -2) 📝 `crates-tauri/yaak-app-client/src/git_watcher.rs` (+30 -8) 📝 `crates/yaak-git/Cargo.toml` (+4 -0) 📝 `crates/yaak-git/bindings/gen_git.ts` (+6 -1) 📝 `crates/yaak-git/src/commit.rs` (+87 -2) 📝 `crates/yaak-git/src/pull.rs` (+5 -2) 📝 `crates/yaak-git/src/repository.rs` (+8 -1) 📝 `crates/yaak-git/src/status.rs` (+109 -10) </details> ### 📄 Description ## What Fixes https://yaak.app/feedback/posts/linux-app-consistently-uses-100-cpu-when-idle With a sync folder inside a large busy repo (monorepo with vendor dirs, node_modules, build churn): - The Git watcher watched the **entire containing repository**, so every file event anywhere in the repo ran an ignore-check, and every non-ignored event triggered **two full status walks** (immediate + post-settle). On Linux (inotify, no App Nap throttling) this pegs a core constantly. Reproduced on macOS at 100.9% CPU during event bursts; macOS's FSEvents coalescing otherwise masks it. - The commit dialog's status walked the full worktree with `include_unmodified`, **loading previous blob content for every tracked file in the repo**, and listed every dirty repo file under "External file changes". - `git commit` committed the **entire index**, so files staged outside Yaak (e.g. in the containing monorepo) were silently swept into Yaak commits. - Pull refused to run whenever **anything** in the containing repo was dirty — its uncommitted-changes check walked the whole worktree, making pull permanently unusable in a busy monorepo. ## How - The watcher covers only the sync directory, plus the Git metadata that affects branch/status info: top-level gitdir (HEAD, index, packed-refs) non-recursively and `refs/` recursively — skipping the churn-heavy `objects/` - Both status functions (`git_worktree_status`, `git_status`) are pathspec-scoped to the requested directory via a shared helper — a no-op when the sync dir is the repo root, so standalone repos behave exactly as before - Commits derive the staged files under the sync dir at commit time and pass them as pathspecs (`git commit -- <files>`), so a Yaak commit contains exactly what the dialog shows; externally staged files are untouched and stay staged - Status walks are built through a single `scoped_status_options` constructor so new call sites can't forget the scoping — which is how the pull check was found; it's now scoped too (git merge still refuses to clobber uncommitted files outside the sync dir) - The "External file changes" section is renamed to "Other files" (it now only ever shows non-Yaak files within the sync folder — its original purpose) and paths display relative to the sync directory ## Testing - Unit tests for both status functions: subdir-scoped walks report only subdir files (with correct `relaDir`), repo-root walks report everything - Repro repo (React + 93k-file ignored tree + 30k-file untracked tree + 50ms churn script): commit dialog went from seconds to instant and lists only sync-dir files; sidebar git indicators still update on request changes; branch info still refreshes on terminal commits - Pending: verification on a Linux box, where the original report came from --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
GiteaMirror added the pull-request label 2026-07-15 02:03:05 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/yaak#3352