Fix/oom guards and gui improvements - #10
Conversation
- Add DEFAULT_IGNORE_DIR_NAMES to skip node_modules/.git/.next/etc during -r walk - Add DEFAULT_MAX_TOTAL_BYTES (20MB) hard ceiling on total glued content size - Add skip_default_ignore_dirs and max_total_bytes to GlueConfig - Implement pre-flight file size check before reading to avoid loading huge files - Add post-read encoded size verification to catch UTF-8 replacement bloat - Thread safety guards through collect_files() and glue_files() - Export new constants and config fields in __init__.py Prevents system freeze/swap-thrash when recursing into dependency directories without explicit --exclude patterns. Fixes: system freeze requiring hard restart when gluing JS/build-heavy projects
- Add --no-default-ignore to disable auto-skip of node_modules/.git/etc - Add --max-size <MB> to set custom content size limit (0 disables) - Wire flags through to GlueConfig.skip_default_ignore_dirs and max_total_bytes - Default behavior preserves safety guards (20MB cap, default ignores enabled) Allows users to override safety defaults when intentionally gluing dependency directories or large codebases.
- Implement FlowBox with removable chips for exclude patterns - Add manual entry field that commits patterns on Enter - Add Browse button with multi-select file picker (GTK 4.10+ FileDialog, FileChooserNative fallback for older versions) - Implement _normalize_exclude_pattern() to strip ./ and trailing / for dedup - Add _looks_heavy() heuristic to prevent file picker freeze on heavy directories - Add _active_picker reference to prevent GC during async dialog interaction - Fix Pango.EllipsizeMode import (was incorrectly Gtk.EllipsizeMode) - Add CODEGLUER_DEBUG env var for verbose logging - Implement _show_error_dialog() with GTK version-aware fallback - Surface file picker errors instead of silent failures Improves UX by making exclude patterns visible and removable, prevents common mistakes with comma separation, and avoids GTK file chooser freezes on node_modules-heavy directories.
|
Warning Review limit reached
Next review available in: 25 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughThis PR adds safety guards to prevent OOM/freeze during recursive glue operations: ChangesCore Safety Guards and CLI/Package Wiring
GUI Exclude-Chip Interface and Heavy-Directory Detection
Estimated code review effort: 4 (Complex) | ~60 minutes Sequence Diagram(s)sequenceDiagram
participant CLI
participant GlueConfig
participant collect_files
participant glue_files
CLI->>GlueConfig: set skip_default_ignore_dirs, max_total_bytes
glue_files->>collect_files: pass skip_default_ignore_dirs
collect_files->>collect_files: filter DEFAULT_IGNORE_DIR_NAMES during traversal
glue_files->>glue_files: track total_bytes per file
glue_files->>glue_files: raise CodeGluerError if limit exceeded
sequenceDiagram
participant User
participant BrowseButton
participant FileDialog
participant CodeGluerWindow
User->>BrowseButton: click Browse
BrowseButton->>CodeGluerWindow: _on_browse_clicked()
CodeGluerWindow->>FileDialog: open dialog (with _looks_heavy guard)
FileDialog-->>CodeGluerWindow: selected files
CodeGluerWindow->>CodeGluerWindow: extract basenames, add exclude chips
Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
codegluer/__init__.py (1)
30-54: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueOptional: Ruff RUF022 flags
__all__as unsorted.The list is intentionally grouped (version → constants → errors → config → functions), which conflicts with the isort-style ordering RUF022 wants. If this rule is enforced in CI, either apply the sort or add a
# noqa: RUF022to preserve the current grouping.🤖 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 `@codegluer/__init__.py` around lines 30 - 54, The __all__ export list is intentionally grouped but violates Ruff RUF022’s sorted-order expectation. Update the __all__ definition in the module-level export block to either match the required sort order or add a targeted noqa for RUF022 if you want to preserve the current grouping; use the existing __all__ symbol and the adjacent import/export block as the reference point.Source: Linters/SAST tools
codegluer_gui.py (1)
534-534: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winGate debug prints behind
CODEGLUER_DEBUG.The PR describes debug logging via
CODEGLUER_DEBUG=1, but theseprint(..., file=sys.stderr)statements (throughout_add_exclude_chip,_on_browse_clicked, and the picker response handlers) are unconditional, so normal runs emit verbose stderr output. Route them through a small helper that checks the env var (orlogging) to match the stated design.♻️ Example gating helper
import os _DEBUG = os.environ.get("CODEGLUER_DEBUG") == "1" def _dbg(msg: str) -> None: if _DEBUG: print(msg, file=sys.stderr)Also applies to: 571-571, 610-611, 684-684, 695-695, 751-751
🤖 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 `@codegluer_gui.py` at line 534, The debug prints in the GUI code are unconditional, so normal runs still emit stderr noise instead of respecting CODEGLUER_DEBUG. Update the related paths in codegluer_gui.py, especially _add_exclude_chip, _on_browse_clicked, and the picker response handlers, to use a shared debug helper (or logging) that checks CODEGLUER_DEBUG before printing. Keep the existing debug messages but route them through that helper so only debug-enabled runs produce output.
🤖 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 `@codegluer_gui.py`:
- Around line 591-592: The empty-state branch in the chip update logic hides
self.chip_flowbox after the last chip is removed, which can trigger the same
hidden→visible reflow issue called out in the add path. Update the chip
management code around the self.excludes check to keep self.chip_flowbox visible
even when there are no chips, or remove the earlier warning only if the reflow
behavior is no longer relevant. Use the existing chip add/remove flow in
codegluer_gui.py to locate the affected logic.
---
Nitpick comments:
In `@codegluer_gui.py`:
- Line 534: The debug prints in the GUI code are unconditional, so normal runs
still emit stderr noise instead of respecting CODEGLUER_DEBUG. Update the
related paths in codegluer_gui.py, especially _add_exclude_chip,
_on_browse_clicked, and the picker response handlers, to use a shared debug
helper (or logging) that checks CODEGLUER_DEBUG before printing. Keep the
existing debug messages but route them through that helper so only debug-enabled
runs produce output.
In `@codegluer/__init__.py`:
- Around line 30-54: The __all__ export list is intentionally grouped but
violates Ruff RUF022’s sorted-order expectation. Update the __all__ definition
in the module-level export block to either match the required sort order or add
a targeted noqa for RUF022 if you want to preserve the current grouping; use the
existing __all__ symbol and the adjacent import/export block as the reference
point.
🪄 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: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: d2fc6e5e-f97d-4369-a2d7-b1503430c11e
📒 Files selected for processing (4)
codegluer/__init__.pycodegluer/cli.pycodegluer/core.pycodegluer_gui.py
…re chip colors - Sort __all__ list alphabetically to satisfy Ruff RUF022 - Remove flowbox visibility toggle in _remove_exclude_chip to prevent chips from silently not appearing after first add (reflow issue) - Route all debug output through debug_print() helper that respects CODEGLUER_DEBUG environment variable - Move chip colors from shared CHIP_CSS_BASE to per-theme THEME_CSS blocks so chips match the active theme palette: * Light: dark blue #1e3a5f with white text * Dark: lighter blue #4a6fa5 with white text * Roselle: theme red #C62734 with #fff0f0 text
Summary
This PR addresses a critical system freeze bug and improves the GUI UX for exclude patterns.
Changes
🔒 Safety Guards (Critical Fix)
DEFAULT_IGNORE_DIR_NAMESto automatically skipnode_modules,.git,.next,dist,build, etc. during recursive traversalDEFAULT_MAX_TOTAL_BYTES(20MB) hard ceiling on total glued content size with pre-flight and post-read size verification--no-default-ignoreand--max-size <MB>flags to override safety defaults when needed--excludepatterns caused system swap-thrashing requiring hard restart🎨 GUI Improvements
./and trailing/for better deduplication_looks_heavy()heuristic to prevent file picker freezes on node_modules-heavy directoriesCODEGLUER_DEBUG=1environment variable for verbose logging🐛 Bug Fixes
Pango.EllipsizeModeimport (was incorrectlyGtk.EllipsizeMode)_active_pickerreferenceMigration Notes
No breaking changes. Default behavior is safer (auto-skips dependency directories, 20MB cap). Users can override with:
--no-default-ignoreto disable auto-skip--max-size 0to disable memory cap--max-size <MB>to set custom limitFiles Changed
codegluer/core.py- Safety guards, size checks, config fieldscodegluer/cli.py- New CLI flagscodegluer/__init__.py- Export new constantscodegluer_gui.py- Chip UI, browse button, error handlingSummary by CodeRabbit
New Features
Bug Fixes