Skip to content

shell: single-quote the profile line before echoing it - #24042

Merged
MikeMcQuaid merged 1 commit into
Homebrew:mainfrom
rawsun007:fix/shell-profile-single-quote
Sep 20, 2026
Merged

MikeMcQuaid merged 1 commit into
Homebrew:mainfrom
rawsun007:fix/shell-profile-single-quote

Conversation

@rawsun007

Copy link
Copy Markdown
Contributor

  • Have you followed our Contributing guidelines?
  • Have you checked for other open Pull Requests for the same change?
  • Have you explained what your changes do? Performance claims (e.g. "this is faster") must include brew benchmark results.
  • Have you explained why you'd like these changes included, not just what they do?
  • For bug fixes, have you given step-by-step brew commands to reproduce the bug?
  • Have you written new tests (excluding integration tests)? Here's an example.
  • Have you successfully run brew lgtm (style, typechecking and tests) locally?

  • I did not use AI/LLM to create this PR, or I disclosed the tool/model below and reviewed its output; I did not attribute commits to AI and will answer maintainer questions and review comments myself without AI/LLM.

Follow-up to #24035, which named this as the part it deliberately left alone.

set_variable_in_profile and prepend_path_in_profile build a command for the user to paste, wrapping the whole profile line in literal single quotes. A single quote in the value closes that string early:

$ brew ruby -e 'require "utils/shell"; ENV["SHELL"]="/bin/bash"; puts Utils::Shell.prepend_path_in_profile("/Users/o'brien/bin")'
echo 'export PATH=/Users/o\'brien/bin:$PATH' >> /Users/me/.bash_profile

$ bash --norc -c "echo 'export PATH=/Users/o\'brien/bin:\$PATH' >> prof"
bash: -c: line 0: unexpected EOF while looking for matching `''

Nothing is written. The \ that sh_quote adds is literal inside single quotes, so it does not escape anything; a single-quoted string can only be interrupted, escaped and resumed.

The pwsh branch already passes its whole line through pwsh_quote. sh_single_quote does the same for the Bourne, rc, csh and fish branches.

Emitting the command for five values (apostrophe, space, $, double quote, plain) under bash, zsh, sh, ksh and tcsh, then running it and sourcing the profile it writes: before, the five apostrophe cases fail to run at all, one per shell; after, all 30 run and source back the exact value. The output is byte-identical to today's for every value that does not contain a quote, so nothing that works now changes.

Reachable wherever HOMEBREW_PREFIX or a keg path contains an apostrophe, which on Linux means a home-directory install for someone whose username has one. The callers are brew link for keg-only formulae, the keg-only caveats, and the HOMEBREW_TEMP advice in the Linux diagnostic.

Three new examples, one per changed behaviour; reverting only utils/shell.rb fails exactly those three and nothing else. brew tests also passes for caveats, diagnostic, cmd/link and cmd/--env.

rc is covered by the same change but I have no rc to run it under, so that branch is reasoned from the shared echo '...' shape rather than measured. Saying so rather than implying I tested it.

AI disclosure: written with Claude Code (Claude Opus 5) on my account. The before/after counts come from a harness that ran each emitted command in the real shell and sourced the profile it produced. I answer review comments myself.

The profile helpers wrapped the whole line in literal single quotes, so
a value containing one closed the string early and the emitted command
was a syntax error that wrote nothing. The pwsh branch already quoted
the line through pwsh_quote; sh_single_quote gives the Bourne, rc, csh
and fish branches the same treatment.

@MikeMcQuaid MikeMcQuaid left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks!

@MikeMcQuaid
MikeMcQuaid added this pull request to the merge queue Sep 20, 2026
Merged via the queue into Homebrew:main with commit f00137e Sep 20, 2026
82 of 83 checks passed
@rawsun007 rawsun007 mentioned this pull request Sep 29, 2026
7 of 8 tasks
MikeMcQuaid added a commit to rawsun007/brew that referenced this pull request Oct 3, 2026
- Revert speculative quoting from Homebrew#24035, Homebrew#24042, Homebrew#24105, Homebrew#24114
  and Homebrew#24154 after the author confirmed it lacked user reports.
- Revert Homebrew#24053 and Homebrew#24144: repeated singleton headers and rounding
  boundaries have no reported user failures in their discussions.
- Use `Shellwords.escape` and `Process.spawn` instead of maintaining
  duplicate escaping and process setup logic.
- Preserve tilde expansion and csh newline quoting, and reuse the
  profile map as the supported-shell list.
- Inline redirect resolution and headline formatting into their
  sole callers; exercise redirects through the download strategy.
- Retain ordinary PowerShell and mksh fixes, archive validation and
  runtime migrations that avoid duplicating existing functionality.
MikeMcQuaid added a commit to rawsun007/brew that referenced this pull request Oct 3, 2026
- Revert speculative quoting from Homebrew#24035, Homebrew#24042, Homebrew#24105, Homebrew#24114
  and Homebrew#24154 after the author confirmed it lacked user reports.
- Use `Shellwords.escape` and `Process.spawn` instead of maintaining
  duplicate escaping and process setup logic.
- Preserve tilde expansion and convert Ruby's quoted newlines for
  csh without changing the backslashes already escaped by Ruby.
- Reuse the profile map as the supported-shell list and inline
  single-use locals while retaining ordinary PowerShell support.
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.

2 participants