- Parse `.git/config` once in Bash for the `devcmdrun` and analytics
settings rather than forking `git config` via the shim four times.
- Read `.git/HEAD`, loose refs and `packed-refs` directly and keep
`git rev-parse` only as a fallback for worktrees and symrefs.
- Only run the slow `git diff` describe-cache dirty check for
developers as they are the only users likely to have dirty trees.
- Parse `SystemVersion.plist` rather than forking `sw_vers`, which
reads the same file; keep `sw_vers` as a fallback.
- Check locale names rather than forking `locale charmap`; the
filtered environment can never report UTF-8 anyway.
- Fork `sysctl` only when Rosetta is possible and run
`${HOMEBREW_CURL}` directly rather than through the `curl` shim.
- Prefer builtins to `cat`, `readlink`, `dirname`, `tee` and
subshells on the startup path.
- Extract the OS, auto-update, curl and Git logic from `brew.sh`
into new `utils/os.sh`, `utils/auto-update.sh`, `utils/curl.sh`
and `utils/git.sh` files; the same work happens in the same order.
- Warm no-op timings: `brew shellenv` 16ms to 9.5ms, `brew --version`
62ms to 11ms and full command dispatch 275ms to 83ms.
- The formulae.brew.sh env-config table was hard to interpret: unset
and explicitly-set-to-default runs were merged as "default events",
nothing showed what a variable's default was and variables brew
exports itself (`HOMEBREW_UPDATE_TO_TAG` in `cmd/update.sh`,
`HOMEBREW_EDITOR`/`HOMEBREW_DISPLAY` etc. copied from the user
environment in `bin/brew`) dominated the chart as fake user
configuration.
- Record `HOMEBREW_USER_SET_VARS` at `bin/brew` startup, after
`brew.env` files load but before any exports, so sampling and
`brew config` can tell deliberate configuration apart; sub-brews
inherit the list.
- Replace the `env_config_non_default` tag with a single
`env_config_state` tag (`unset`/`default`/`non_default`) computed
from user-set values only.
- Compute previously `default_text`-only defaults so explicitly-set
default values are ignored everywhere: `HOMEBREW_AUTO_UPDATE_SECS`
(mirroring `brew.sh`), `HOMEBREW_FORBID_PACKAGES_FROM_PATHS` (now
`boolean: :set`, matching its accessor), `HOMEBREW_PIP_INDEX_URL`
and `HOMEBREW_SSH_CONFIG_PATH`; generated accessors and
`non_default_variable?` call callable defaults and treat blank
booleans as unset like their accessors.
- `brew config` now only prints user-set non-default variables and
`Resource#determine_url_mirrors` only rewrites PyPI URLs for
non-default `$HOMEBREW_PIP_INDEX_URL` values.
- Sanitise `formula-analytics` results: only current variables and
valid states are accepted and the query requires the new tag,
which drops the contaminated data already collected.
- Stop excluding CI events from `command_run_options`: CI users are
normal users so CI-only usage should stay visible.
- Output `non_default_count`, `set_default_count`, `unset_count` and
`default_value` per variable in JSON, using the human
`default_text` summary for varying defaults via
`EnvConfig.default_description`, now shared with the manpage.
We rely on being able to `unset` this environment variable when handing
back to Ruby, but we won't be able to unset this if we got it from an
env file.
Move some stuff around to improve cold startup performance.
`brew --prefix` went from about 16.5 ms to 9.0 ms
`brew help` went from about 16.5 ms to 8.7 ms.
This will ensure that we don't inadvertently filter out future
environment variables that start with text contained in
`BIN_BREW_EXPORTED_VARS` (e.g. `HOMEBREW_REPOSITORY_*`).
Looping over `BIN_BREW_EXPORTED_VARS` for each line of an env file is
relatively inefficient. We can avoid this by constructing a regex before
the loop and using that regex to match against the lines we want to
skip.
Add `XDG_CONFIG_HOME` to `USED_BY_HOMEBREW_VARS` so it is copied to
`HOMEBREW_XDG_CONFIG_HOME` and survives the `env -i` filter, matching
the existing pattern for `XDG_CACHE_HOME`, `XDG_DATA_DIRS` and
`XDG_RUNTIME_DIR`.
Also fall back to `HOMEBREW_XDG_CONFIG_HOME` when computing
`HOMEBREW_USER_CONFIG_HOME`, so that the value is correct when
`bin/brew` is re-executed after auto-update (via `exec` in `brew.sh`)
and the original `XDG_CONFIG_HOME` has been filtered out.
Without this fix, `brew bundle --global` fails with "No Brewfile found"
for users whose Brewfile is at `$XDG_CONFIG_HOME/homebrew/Brewfile`
whenever auto-update triggers a re-exec.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Visual Studio Code, when run from WSL (Windows
Subsystem for Linux) uses WSL_DISTRO_NAME presence
to detect it. When it fails to do so its spawn the
GUI instead of running the CLI application.
This now requires `HOMEBREW_DISABLE_NO_FORCE_BREW_WRAPPER` to be unset.
If it is set (but only in a `brew.env` file), then we use the new
functionality of checking the path of the parent process.
`HOMEBREW_FORCE_BREW_WRAPPER` can be used as a security/compliance
feature, but allowing it to be disabled by setting
`HOMEBREW_NO_FORCE_BREW_WRAPPER` leaves a pretty large hole in it that
allows it to be sidestepped.
Let's fix that by actually checking the path of the process that called
`brew`, and the verify that that path matches the configured value of
`HOMEBREW_NO_FORCE_BREW_WRAPPER`.
Let's move this from `bin/brew` to make things like e.g. `brew --prefix`
or `brew shellenv` not reset the sudo timestamp.
This is still in a place that ensures that e.g. no untrusted formula or
tap code has been run yet so should have no security implications but
provide mild usability improvements.
It's both unexpected and undesirable for `brew bundle (exec|env|sh)` to
filter the environment and makes these tools less useful.
Not filtering the environment, though, causes issues with the
`brew bundle sh` shell. Fix this up and, while we're here, also improve
the formatting for both `zsh` and `bash` (the default) to use nicer and
more consistent prompts and colours.
To simplify this, consolidate some logic in a new
`Utils::Shell.shell_with_prompt` method and add tests for it and a
similar notice for `brew bundle sh`.
Finally, avoid printing out the notice when `HOMEBREW_NO_ENV_HINTS` is
set.
Allow the ability for a system administrator to use
`HOMEBREW_BREW_WRAPPER` and `HOMEBREW_FORCE_BREW_WRAPPER` variables to
enforce the usage of a particular `brew` command for non-trivial (e.g.
`brew --prefix` is considered trivial, it doesn't need to write to the
prefix) Homebrew commands.
This also introduces a `HOMEBREW_ORIGINAL_BREW_FILE` variable for some
internal usage; `HOMEBREW_BREW_FILE` was being used internally for
both "how should we shell out to Homebrew" and "what should we use
to check permissions on Homebrew". `HOMEBREW_ORIGINAL_BREW_FILE` is
now used just for the latter case.
Inspired by conversation in
https://github.com/Homebrew/homebrew-bundle/pull/1551 which suggested
this was worth fixing in wider than just `brew bundle`.
The current glob check will accept lines like
HOMEBREW_FOO=bar BAD_ENV_VAR=baz
and happily export them, but we don't want that.
Let's tighten up the check to reject lines like the above.
In #17694, a call to `sudo --reset-timestamp` was added to prevent
cached credentials being run. Unfortunately, this breaks `brew`
invocation under `sandbox-exec`, which forbids any attempts to
exec setuid executables. This in turn breaks the OCaml opam
package manager, which sandboxes its build commands (including
brew prefix queries): see https://github.com/ocaml/opam/issues/6117
for that error.
This commit just changes the sudo invocation to suppress errors
and continue if it fails, which should be harmless in normal
operation as sudo doesn't emit an error for this option when
invoked normally.
The CDPATH environment variable can affect the behavior of
`cd`, and `cd` takes the `-P`, `-L` and `-e` flags.
(I didn't know about `-e` until looking at the source)
Make quietcd more robust by setting the CDPATH to ''.
I tested this change by running the following commands from a nonstandard
directory, which caused some of tcsh's and perl's dependencies to be recompiled.
$ [path to brew] install tcsh
$ [path to brew] install perl
Here's a link to the source code of `cd` in a mirror of the bash repo.
https://github.com/bminor/bash/blob/ec8113b9861375e4e17b3307372569d429dec814/builtins/cd.def#L267
This variable was getting filtered out before so it wasn't possible
for us to use it as the default for HOMEBREW_DEFAULT_CACHE
and HOMEBREW_DEFAULT_LOGS.