fix: use gitignore-aware selective watching to reduce memory usage (#1399)
* fix: skip watching heavy directories to avoid memory leak * fix: reduce memory usage in filesystem watcher for pnpm projects Use gitignore-aware directory collection to prevent OS-level watchers from being set up on heavy directories like node_modules. Changes: - Use WalkBuilder's git_ignore(true) to respect .gitignore when collecting watch directories - Use NonRecursive watch mode for each directory instead of single Recursive watch - Simplify ALWAYS_SKIP_DIRS to only contain .git (not in .gitignore but should be skipped) This fixes high memory usage when running vibe-kanban on pnpm-managed repositories, which contain many symlinks in node_modules. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * fix: simplify filesystem watcher error handling and fix clippy warnings - Remove debug logs that were added during development - Fail fast on watch errors instead of continuing in a partially broken state - Collapse nested if statements to satisfy clippy::collapsible_if 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * fix: check only parent directories in path_allowed Only check parent directory names against ALWAYS_SKIP_DIRS since should_skip_dir is meant for directories, not file names. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * fix: add watch directories changes * Stop leaking filesystem watcher Use weak references so the background thread exits once the diff stream releases the debouncer. * Memoize ignored-descendant scan Cache per-directory results so collecting watch targets stays linear. * Improve watcher gitignore classification Use real metadata when available, fall back to the old heuristic only when the file is already gone, and document the limitation. * Handle directory renames in watcher * Deduplicate watch directories more efficiently Sort once and do a single sweep instead of quadratic filtering. * Document gitignore watcher limitation * Cascade watcher removal on directory delete Drop all descendant watchers when a parent directory disappears so stale handles don’t linger. * Watch subdirectories when new directories are added Track recursive parent watchers so we skip redundant child watches and prune them when a parent becomes recursive. * Always ignore node_modules * Use a high-performance line count diff implementation The `similar` diff stat implementation was causing cpu spikes of up to 600% over 10 seconds. * exclude node_modules from git diff commands --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Solomon <abcpro11051@disroot.org>
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
use std::borrow::Cow;
|
||||
|
||||
use git2::{DiffOptions, Patch};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use similar::{ChangeTag, TextDiff};
|
||||
use similar::TextDiff;
|
||||
use ts_rs::TS;
|
||||
|
||||
// Structs compatable with props: https://github.com/MrWangJustToDo/git-diff-view
|
||||
@@ -74,19 +75,18 @@ pub fn compute_line_change_counts(old: &str, new: &str) -> (usize, usize) {
|
||||
let old = ensure_newline(old);
|
||||
let new = ensure_newline(new);
|
||||
|
||||
let diff = TextDiff::from_lines(&old, &new);
|
||||
let mut opts = DiffOptions::new();
|
||||
opts.context_lines(0);
|
||||
|
||||
let mut additions = 0usize;
|
||||
let mut deletions = 0usize;
|
||||
for change in diff.iter_all_changes() {
|
||||
match change.tag() {
|
||||
ChangeTag::Insert => additions += 1,
|
||||
ChangeTag::Delete => deletions += 1,
|
||||
ChangeTag::Equal => {}
|
||||
match Patch::from_buffers(old.as_bytes(), None, new.as_bytes(), None, Some(&mut opts))
|
||||
.and_then(|patch| patch.line_stats())
|
||||
{
|
||||
Ok((_, adds, dels)) => (adds, dels),
|
||||
Err(e) => {
|
||||
tracing::error!("git2 diff failed: {}", e);
|
||||
(0, 0)
|
||||
}
|
||||
}
|
||||
|
||||
(additions, deletions)
|
||||
}
|
||||
|
||||
// ensure a line ends with a newline character
|
||||
|
||||
Reference in New Issue
Block a user