Skip to content

🐛 fix make init to support re-initialization#145

Closed
Miyamura80 wants to merge 4 commits intomainfrom
fix/idempotent-make-init
Closed

🐛 fix make init to support re-initialization#145
Miyamura80 wants to merge 4 commits intomainfrom
fix/idempotent-make-init

Conversation

@Miyamura80
Copy link
Owner

Summary

  • make init used hardcoded strings ("python-template", "Add your description here", etc.) so it silently failed when run on an already-renamed project
  • Now dynamically reads current name/description from pyproject.toml before replacing, making make init idempotent and re-runnable
  • Uses flexible regex patterns for README updates instead of exact string matches

Mirrors the fix in Miyamura80/CLI-Template#21

Test plan

  • Run make init name=foo description="bar" on a fresh template — verify pyproject.toml and README update
  • Run make init name=baz description="qux" again — verify it re-renames correctly

🤖 Generated with Claude Code

The init target used hardcoded default strings so it silently failed
when run on an already-renamed project. Now reads current name and
description from pyproject.toml dynamically.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@greptile-apps
Copy link
Contributor

greptile-apps bot commented Mar 15, 2026

Greptile Summary

This PR makes make init idempotent by dynamically reading the current name/description from pyproject.toml before substitution, and adds escaping logic for both the old (pattern) and new (replacement) values passed to sed. A minor readability improvement is also made to the running_on lambda in common/global_config.py.

  • Makefile — core logic: CURRENT_NAME and CURRENT_DESC are now extracted from pyproject.toml via sed -n '…/p' | head -1, which means if pyproject.toml is absent, renamed, or has the field in an unexpected format (e.g., extra whitespace around =), both variables will be empty strings. The subsequent sed substitutions will silently match name = "" (which does not exist in a normal file) and leave the file unchanged with no error or warning. Consider adding a guard such as if [ -z "$$CURRENT_NAME" ]; then echo "Error: could not extract current name"; exit 1; fi after each extraction.
  • Makefile — escaping: Pattern-side escaping (ESC_NAME/ESC_DESC, lines 48-49) and replacement-side escaping (ESC_NEW_NAME/ESC_NEW_DESC, lines 50-51) cover the main sed metacharacters. Notably, ESC_NEW_DESC correctly escapes both / (for line 54's /-delimited command) and | (for line 56's |-delimited command).
  • Makefile — README range: The <b>.*</b> pattern is now constrained to lines 1-10 (1,10s|…|), partially addressing the greediness concern from previous review threads.
  • common/global_config.py: The running_on lambda body was already syntactically correct (Python's lambda body extends rightward to consume the full ternary expression), so this change is a pure readability improvement with no behavioural difference.

Confidence Score: 4/5

  • Safe to merge; the changes are a meaningful improvement over the original hardcoded approach and are unlikely to regress existing behaviour.
  • The Makefile rewrite correctly handles the re-initialization use case and escaping for most realistic project name/description values. The one gap — silent failure when pyproject.toml extraction returns empty — is a robustness concern rather than a correctness bug for the intended happy path. The global_config.py change is a no-op readability improvement.
  • Makefile (lines 46-56): verify behaviour when pyproject.toml is absent or fields are formatted unexpectedly.

Important Files Changed

Filename Overview
Makefile Rewrites make init to dynamically read current name/description from pyproject.toml before substitution. Introduces escaping logic for sed patterns and replacements; some escape sequences have subtle correctness concerns (notably \* inside a character class has ambiguous semantics between GNU sed and BSD sed), and silent failure when extraction returns empty is possible but unlikely in practice.
common/global_config.py Wraps the running_on lambda body's ternary expression in explicit parentheses. While the original code was syntactically correct (Python's lambda body extends to include the full ternary), the reformatting makes the intent visually unambiguous and avoids potential confusion with top-level ternary binding.
Prompt To Fix All With AI
This is a comment left during a code review.
Path: Makefile
Line: 46-47

Comment:
**Silent failure when extraction returns empty**

If `pyproject.toml` is missing, or if either field isn't present in the exact format `^name = "…"` (e.g., TOML allows `name="…"` without spaces), `CURRENT_NAME` and/or `CURRENT_DESC` will be empty strings. The downstream sed commands will then attempt to match `name = ""` or `description = ""`, find nothing, exit 0, and leave the files silently unchanged — with no indication to the user that the rename failed.

Consider adding an explicit guard after each extraction:

```
CURRENT_NAME=$$(sed -n 's/^name = "\(.*\)"/\1/p' pyproject.toml | head -1); \
if [ -z "$$CURRENT_NAME" ]; then echo "$(RED)Error: could not read current name from pyproject.toml$(RESET)"; exit 1; fi; \
CURRENT_DESC=$$(sed -n 's/^description = "\(.*\)"/\1/p' pyproject.toml | head -1); \
if [ -z "$$CURRENT_DESC" ]; then echo "$(RED)Error: could not read current description from pyproject.toml$(RESET)"; exit 1; fi; \
```

How can I resolve this? If you propose a fix, please make it concise.

Last reviewed commit: 71cac05

Address review feedback:
- Escape regex special chars in extracted name/description before
  using them in sed patterns
- Restrict <b> tag replacement to first 10 lines of README to avoid
  clobbering unrelated bold markup

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@Miyamura80
Copy link
Owner Author

Addressed both review comments in 179189d:

  1. Greedy <b> pattern: Scoped the replacement to lines 1-10 of README with 1,10s|...|...|, so it won't touch bold markup elsewhere in the file.

  2. Regex metacharacters: Extracted values are now escaped for sed special chars (.[\\*^$/) before being used as patterns, so names like my.project won't cause mismatches.

New name/description values also need escaping for sed replacement
special chars (& / | \) to handle names like "acme/my-project" or
descriptions containing "&".

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@Miyamura80
Copy link
Owner Author

Addressed in 0c144f3 — new values ($(name) and $(description)) are now also escaped for sed replacement-string specials:

  • ESC_NEW_NAME escapes &, /, and \
  • ESC_NEW_DESC escapes &, | (its delimiter), and \

So make init name="acme/my-project" description="foo & bar" now works correctly.

ESC_NEW_DESC is used in both a /-delimited sed (pyproject.toml) and
a |-delimited sed (README), so it needs to escape both delimiters.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@Miyamura80
Copy link
Owner Author

Fixed in 71cac05 — added / to the ESC_NEW_DESC character class so it now escapes &, /, |, and \. This covers both the /-delimited sed for pyproject.toml and the |-delimited sed for README.

Comment on lines +46 to +47
@CURRENT_NAME=$$(sed -n 's/^name = "\(.*\)"/\1/p' pyproject.toml | head -1); \
CURRENT_DESC=$$(sed -n 's/^description = "\(.*\)"/\1/p' pyproject.toml | head -1); \
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Silent failure when extraction returns empty

If pyproject.toml is missing, or if either field isn't present in the exact format ^name = "…" (e.g., TOML allows name="…" without spaces), CURRENT_NAME and/or CURRENT_DESC will be empty strings. The downstream sed commands will then attempt to match name = "" or description = "", find nothing, exit 0, and leave the files silently unchanged — with no indication to the user that the rename failed.

Consider adding an explicit guard after each extraction:

CURRENT_NAME=$$(sed -n 's/^name = "\(.*\)"/\1/p' pyproject.toml | head -1); \
if [ -z "$$CURRENT_NAME" ]; then echo "$(RED)Error: could not read current name from pyproject.toml$(RESET)"; exit 1; fi; \
CURRENT_DESC=$$(sed -n 's/^description = "\(.*\)"/\1/p' pyproject.toml | head -1); \
if [ -z "$$CURRENT_DESC" ]; then echo "$(RED)Error: could not read current description from pyproject.toml$(RESET)"; exit 1; fi; \
Prompt To Fix With AI
This is a comment left during a code review.
Path: Makefile
Line: 46-47

Comment:
**Silent failure when extraction returns empty**

If `pyproject.toml` is missing, or if either field isn't present in the exact format `^name = "…"` (e.g., TOML allows `name="…"` without spaces), `CURRENT_NAME` and/or `CURRENT_DESC` will be empty strings. The downstream sed commands will then attempt to match `name = ""` or `description = ""`, find nothing, exit 0, and leave the files silently unchanged — with no indication to the user that the rename failed.

Consider adding an explicit guard after each extraction:

```
CURRENT_NAME=$$(sed -n 's/^name = "\(.*\)"/\1/p' pyproject.toml | head -1); \
if [ -z "$$CURRENT_NAME" ]; then echo "$(RED)Error: could not read current name from pyproject.toml$(RESET)"; exit 1; fi; \
CURRENT_DESC=$$(sed -n 's/^description = "\(.*\)"/\1/p' pyproject.toml | head -1); \
if [ -z "$$CURRENT_DESC" ]; then echo "$(RED)Error: could not read current description from pyproject.toml$(RESET)"; exit 1; fi; \
```

How can I resolve this? If you propose a fix, please make it concise.

@Miyamura80
Copy link
Owner Author

Closing — main has already replaced make init with make onboard (interactive CLI via onboard.py), which includes the re-initialization/re-rename fixes this PR aimed to add. This PR is superseded.

@Miyamura80 Miyamura80 closed this Mar 15, 2026
@Miyamura80 Miyamura80 deleted the fix/idempotent-make-init branch March 15, 2026 20:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant