fix: prevent recursive sourcing in zsh migration overlays#26
Conversation
When the user's old ~/.zshenv was a symlink to the repo's canonical zsh/zshenv, the migration copied framework sourcing infrastructure into the local overlay file. This included a line that sources the overlay itself, causing infinite recursion and "too many open files" errors on every shell startup. Add strip patterns for framework-owned lines (dotfiles_source_*, lib.sh bootstrap, DOTFILES_HOME defaults, managed wrapper boilerplate) and skip creating overlay files when sanitised content is effectively empty (only whitespace and comments remain). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add unit tests verifying that canonical zshenv, zshrc, and zprofile content is fully stripped during migration, that user content mixed with framework lines is preserved, and that managed wrapper content is stripped. Add integration test confirming apply skips overlay creation when legacy content is pure framework. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Code reviewFound 2 issues:
dotfiles/scripts/migrate_zsh.py Lines 274 to 276 in ead8409
dotfiles/scripts/migrate_zsh.py Lines 131 to 133 in ead8409 🤖 Generated with Claude Code - If this code review was useful, please react with 👍. Otherwise, react with 👎. |
…stripping The auto-migration header still read "Known-obsolete patterns (antidote, prezto, GLOBAL_RCS) were stripped" after cb0c03e added framework-owned line stripping. Update the user-facing header and module docstring to cover both categories so migrated overlay files accurately describe what was removed. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Review comment resolution & manual test resultsWhat was addressedIssue 1 (stale header comment) — Fixed (74f7d0a)
Issue 2 (
Manual test simulation results (3/3 PASS)Simulated in isolated temp HOME directories using Test A: clean HOME + canonical
Test B: clean HOME + mixed framework+user
Test C: no recursive sourcing errors ✅
Temp directories cleaned up after testing. 🤖 Generated with Claude Code |
Summary
dotfiles_source_*,lib.shbootstrap,DOTFILES_HOMEdefaults, managed wrapper boilerplate) during zsh content migration to prevent infinite recursionProblem
When the user's old
~/.zshenvwas a symlink to the repo's canonicalzsh/zshenv, the migration copied framework sourcing infrastructure intolocal.zshenv.sh. This includeddotfiles_source_optional_relaxed "...local.zshenv.sh", causing the file to source itself infinitely (same for.zshrc→local.zsh.zshand.zprofile→local.zprofile.sh).Symptoms on every shell startup:
Root cause
sanitize_migrated_zsh_content()stripped obsolete plugin manager patterns (antidote, prezto, zinit) but not the framework's own sourcing lines. When the backed-up file was the framework's canonical file, every line passed through the sanitiser unchanged — including the self-referencing overlay source.Changes
scripts/migrate_zsh.py:_has_meaningful_content()helper to detect empty-after-sanitisation resultstests/test_dotfiles_apply.py:SanitizeMigratedZshContentTests(canonical zshenv/zshrc/zprofile stripping, mixed content preservation, managed wrapper stripping)DotfilesApplyTests(apply skips migration for pure-framework content)Test plan
python3 -m unittest discover -s tests -p 'test_*.py'— all 88 tests pass.zshenvas symlink tozsh/zshenv, rundotfiles apply→ verifylocal.zshenv.shis NOT created.zshenvcontaining framework + user PATH lines → verify overlay has only user lines🤖 Generated with Claude Code