fix: apply init-script renames in a single pass per file - #277
Open
beeman wants to merge 1 commit into
Open
Conversation
🦋 Changeset detectedLatest commit: 60f0db9 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
commit: |
Greptile SummaryThis PR applies project, template-entry, and option renames together in one pass per file, preventing replacement output from being processed again.
Confidence Score: 5/5The PR appears safe to merge. No blocking failure remains; the previously reported excluded-directory regression is fixed, and the earlier commit-signature report was already established as invalid for an SSH-signed commit verified by GitHub. Important Files Changed
Reviews (3): Last reviewed commit: "fix: apply init-script renames in a sing..." | Re-trigger Greptile |
beeman
force-pushed
the
beeman/single-pass-init-rename
branch
from
August 6, 2026 00:28
6c76af0 to
f4c6c54
Compare
Replacing one search term at a time re-scanned the output of earlier substitutions, so a project name containing a template term compounded on every pass: naming a counter-template project `mycountergill` produced `mymymycountergillgillgill` in program names, file names, and the IDL path the setup script then failed to resolve. `searchAndReplace` now combines all substitutions into one alternation regex (longest match first) and applies them in a single pass over each file's contents and name, so no replacement output is ever re-matched. The same compounding existed across calls: the package.json project rename, each rename entry, and template option renames each walked overlapping trees in sequence. These are now collected as scopes and applied together through `searchAndReplaceScopes`, which unions the substitutions per file with the narrowest scope winning on conflicting terms. `initScriptOptions` returns its rename scopes instead of applying them, and `initScriptRename` folds them into the same pass after the entry scopes. An unreadable scope root now logs and continues instead of aborting the remaining scopes, and dry runs no longer recurse into directories under the paths they only pretended to rename. Fixes #192, fixes #193
beeman
force-pushed
the
beeman/single-pass-init-rename
branch
from
August 7, 2026 13:48
f4c6c54 to
60f0db9
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Replacing one search term at a time re-scanned the output of earlier substitutions, so a project name containing a template term compounded on every pass: naming a counter-template project
mycountergillproducedmymymycountergillgillgillin program names, file names, and the IDL path the setup script then failed to resolve. The same compounding existed across calls — the package.json project rename, each rename entry, and template option renames each walked overlapping trees in sequence, so even a single-pass replacement per call would still re-scan what a previous call wrote.What
searchAndReplacecombines all substitutions into one alternation regex (longest match first) and applies them in a single pass over each file's contents and name, so no replacement output is ever re-matchedsearchAndReplaceScopesapplies multiple rename sources together: substitutions are unioned per file, with the narrowest scope winning on conflicting termsinitScriptRenamecollects the project rename and all rename entries as scopes and applies them in one callinitScriptOptionsreturns its rename scopes instead of applying them, andinitScriptRenamefolds them into the same pass after the entry scopestest/init-script-rename-files.test.ts) reproduces the issue scenario end to end, plus unit tests for compounding, duplicated substitutions, scope precedence, and error isolationNotes
Verified against the real CLI with live templates using hostile names (
my-scaffold-counteronkit/nextjs,counter-scaffoldonweb3js/web3js-next-tailwind-counter) — no doubling in either. Two known issues are intentionally out of scope: a single lowercase rename term still maps to its kebab form in Rust contexts (pub mod my-counter), and the project-wide rename rewrites the template's own README install command; both predate this change.Fixes #192, fixes #193