-
Notifications
You must be signed in to change notification settings - Fork 0
fix(bash): sed replacement escaping, BSD portability, dead cleanup code #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 3 commits
8f97d7e
1661ddb
3280cd7
e4933f9
e26a1e6
414d016
aac7864
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -117,13 +117,17 @@ log_warning() { | |||||||||||||||
| echo "WARNING: $1" >&2 | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| # Track temporary files for cleanup on interrupt | ||||||||||||||||
| _CLEANUP_FILES=() | ||||||||||||||||
|
|
||||||||||||||||
| # Cleanup function for temporary files | ||||||||||||||||
| cleanup() { | ||||||||||||||||
| local exit_code=$? | ||||||||||||||||
| # Disarm traps to prevent re-entrant loop | ||||||||||||||||
| trap - EXIT INT TERM | ||||||||||||||||
| rm -f /tmp/agent_update_*_$$ | ||||||||||||||||
| rm -f /tmp/manual_additions_$$ | ||||||||||||||||
| for f in "${_CLEANUP_FILES[@]+"${_CLEANUP_FILES[@]}"}"; do | ||||||||||||||||
| rm -f "$f" "$f.bak" "$f.tmp" | ||||||||||||||||
| done | ||||||||||||||||
| exit $exit_code | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
|
|
@@ -281,10 +285,15 @@ get_language_conventions() { | |||||||||||||||
| echo "$lang: Follow standard conventions" | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| # Escape sed replacement-side specials for | delimiter. | ||||||||||||||||
| # & and \ are replacement-side specials; | is our sed delimiter. | ||||||||||||||||
| _esc_sed() { printf '%s\n' "$1" | sed 's/[\\&|]/\\&/g'; } | ||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||||||||||||||||
|
|
||||||||||||||||
| create_new_agent_file() { | ||||||||||||||||
| local target_file="$1" | ||||||||||||||||
| local temp_file="$2" | ||||||||||||||||
| local project_name="$3" | ||||||||||||||||
| local project_name | ||||||||||||||||
| project_name=$(_esc_sed "$3") | ||||||||||||||||
| local current_date="$4" | ||||||||||||||||
|
|
||||||||||||||||
| if [[ ! -f "$TEMPLATE_FILE" ]]; then | ||||||||||||||||
|
|
@@ -307,18 +316,19 @@ create_new_agent_file() { | |||||||||||||||
| # Replace template placeholders | ||||||||||||||||
| local project_structure | ||||||||||||||||
| project_structure=$(get_project_structure "$NEW_PROJECT_TYPE") | ||||||||||||||||
| project_structure=$(_esc_sed "$project_structure") | ||||||||||||||||
|
|
||||||||||||||||
| local commands | ||||||||||||||||
| commands=$(get_commands_for_language "$NEW_LANG") | ||||||||||||||||
|
|
||||||||||||||||
| local language_conventions | ||||||||||||||||
| language_conventions=$(get_language_conventions "$NEW_LANG") | ||||||||||||||||
| # Perform substitutions with error checking using safer approach | ||||||||||||||||
| # Escape special characters for sed by using a different delimiter or escaping | ||||||||||||||||
| local escaped_lang=$(printf '%s\n' "$NEW_LANG" | sed 's/[\[\.*^$()+{}|]/\\&/g') | ||||||||||||||||
| local escaped_framework=$(printf '%s\n' "$NEW_FRAMEWORK" | sed 's/[\[\.*^$()+{}|]/\\&/g') | ||||||||||||||||
| local escaped_branch=$(printf '%s\n' "$CURRENT_BRANCH" | sed 's/[\[\.*^$()+{}|]/\\&/g') | ||||||||||||||||
|
|
||||||||||||||||
| local escaped_lang=$(_esc_sed "$NEW_LANG") | ||||||||||||||||
| local escaped_framework=$(_esc_sed "$NEW_FRAMEWORK") | ||||||||||||||||
| commands=$(_esc_sed "$commands") | ||||||||||||||||
| language_conventions=$(_esc_sed "$language_conventions") | ||||||||||||||||
| local escaped_branch=$(_esc_sed "$CURRENT_BRANCH") | ||||||||||||||||
|
|
||||||||||||||||
| # Build technology stack and recent change strings conditionally | ||||||||||||||||
| local tech_stack | ||||||||||||||||
|
|
@@ -361,17 +371,17 @@ create_new_agent_file() { | |||||||||||||||
| fi | ||||||||||||||||
| done | ||||||||||||||||
|
|
||||||||||||||||
| # Convert \n sequences to actual newlines | ||||||||||||||||
| newline=$(printf '\n') | ||||||||||||||||
| sed -i.bak2 "s/\\\\n/${newline}/g" "$temp_file" | ||||||||||||||||
| # Convert literal \n sequences to actual newlines (portable — works on BSD + GNU) | ||||||||||||||||
| awk '{gsub(/\\n/,"\n")}1' "$temp_file" > "$temp_file.tmp" && mv "$temp_file.tmp" "$temp_file" | ||||||||||||||||
|
||||||||||||||||
| awk '{gsub(/\\n/,"\n")}1' "$temp_file" > "$temp_file.tmp" && mv "$temp_file.tmp" "$temp_file" | |
| awk '{gsub(/\\n/,"\\n")}1' "$temp_file" > "$temp_file.tmp" | |
| mv "$temp_file.tmp" "$temp_file" |
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The split of AGENTS_FILE updates into individual calls for Amp, Kiro CLI, IBM Bob, and Forge is redundant and causes a regression in logging. Because _update_if_new uses realpath to deduplicate updates, only the first call (Codex/opencode) will actually execute. Subsequent calls for the same file will be skipped, meaning the specific agent names like "Forge" will never be logged during a full update. Additionally, "Pi" has been removed from the list entirely. It is better to use a combined name for shared files to ensure all relevant agents are represented in the logs and no agents are missed.
| _update_if_new "$CURSOR_FILE" "Cursor IDE" || _all_ok=false | |
| _update_if_new "$QWEN_FILE" "Qwen Code" || _all_ok=false | |
| _update_if_new "$AGENTS_FILE" "Codex/opencode/Amp/Kiro/Bob/Pi/Forge" || _all_ok=false | |
| _update_if_new "$AGENTS_FILE" "Codex/opencode" || _all_ok=false | |
| _update_if_new "$AMP_FILE" "Amp" || _all_ok=false | |
| _update_if_new "$KIRO_FILE" "Kiro CLI" || _all_ok=false | |
| _update_if_new "$AGENTS_FILE" "Codex/opencode/Amp/Kiro/Bob/Pi/Forge" || _all_ok=false |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The array expansion
"${_CLEANUP_FILES[@]+"${_CLEANUP_FILES[@]}"}"inside double quotes will expand to an empty string""if the array is empty in older Bash versions (like 3.2 on macOS). This causes the loop to run once withfas an empty string, leading torm -f "" ".bak" ".tmp". This is dangerous as it will attempt to delete files named.bakand.tmpin the current working directory if they exist. To fix this, remove the outer double quotes so it expands to nothing when the array is empty.