Previously, the default temporary directory was /tmp on Linux and
/private/tmp on macOS. On many Linux distros, including at least Fedora,
/tmp is stored in RAM. This diverges from the behavior on macOS and has
led to bugs, most notably the inability to install large bottles on
memory-limited machines.
- if HOMEBREW_TEMP is not writable, use the default temp directory
- when running `brew bundle exec`, strip various temporary directories
from the environment if they are not writable
This uses the logic in `brew.sh` for deciding whether or not to run
`brew update --auto-update` and makes it a dedicated command that can
be used instead of `brew update` in scripts to be really fast in the
no-op case.
`brew update` will always do at least some updating which is a nicer
default but is much slower.
Today if you are in developer mode then `HOMEBREW_NO_SORBET_RUNTIME`
doesn't take effect. But when doing development it's often useful to be
able to disable type-checking, so have that env var take effect even in
developer mode.
- handle reading from variables that may not be defined yet
- avoid unnecessary handling of defined variables
- fix incorrect `env_config.rbi` file entry
- add `HOMEBREW_NO_FORCE_BREW_WRAPPER` to disable
`HOMEBREW_FORCE_BREW_WRAPPER` functionality if needed
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 order matters here (in a way that I can't explain, unfortunately).
Example:
bash-3.2$ read -r FOO <nonexistent 2>/dev/null
bash: nonexistent: No such file or directory
bash-3.2$ read -r FOO 2>/dev/null <nonexistent
# no output
FixesHomebrew/discussions#5653.
This provides a >3x speedup for `brew tap` with no arguments (i.e., when
listing taps). It also makes the completion significantly faster.
$ hyperfine --warmup=3 --setup 'git checkout {branch}' --parameter-list branch master,brew-tap-speedup 'brew tap'
Benchmark 1: brew tap (branch = master)
Time (mean ± σ): 1.405 s ± 0.080 s [User: 0.561 s, System: 0.238 s]
Range (min … max): 1.332 s … 1.549 s 10 runs
Benchmark 2: brew tap (branch = brew-tap-speedup)
Time (mean ± σ): 404.1 ms ± 124.8 ms [User: 107.9 ms, System: 200.7 ms]
Range (min … max): 308.8 ms … 693.7 ms 10 runs
Summary
brew tap (branch = brew-tap-speedup) ran
3.48 ± 1.09 times faster than brew tap (branch = master)
On macOS 14 and newer, `/usr/libexec/path_helper` supports setting a
`PATH_HELPER_ROOT` environment variable.
With this set, `path_helper` checks `$PATH_HELPER_ROOT/etc/paths` and
`$PATH_HELPER_ROOT/etc/paths.d` in the same way it checks `/etc/paths`
and `/etc/paths.d`.
We can use this to simplify management of the user's `PATH` variable
when they do `brew shellenv`. In particular, if their system supports
it, we delegate setting the `PATH` environment variable to `path_helper`
instead of our own code. We also write a default `etc/paths` file if one
is not already present.
This is nicer because it simplifies management of the user's `PATH`
variable. For example, if a user wants a keg-only formula to be in their
`PATH`, they can simply add the necessary path to `/etc/paths` or
`/etc/paths.d` without having to do something like `brew link --force`
or adding to `PATH` themselves.
When `/usr/libexec/path_helper` is not available, we just fall back to
the existing code.
- Use a safe fallback in case git rev-parse fails, e.g. if this is not
considered a safe git directory. For hopefully obvious reasons: be
super careful and strict with the inputs we'll accept here.
- Better handle more permission errors when reading or writing to/from
the git describe cache. We don't care about these errors because they
are likely a result of a multiuser configuration where Homebrew is run
as several different users and this is just a (small) performance
improvement.
`GIT_DESCRIBE_CACHE` is a performance optimisation that doesn't clean
up consistently when run with different Homebrew users. Instead of
doing user detection: let's just hide these errors that we don't care
about.
Reported in:
https://github.com/orgs/Homebrew/discussions/5479
`brew -v` was previously equivalent to `brew --version`, but it
currently returns the output of `brew help`. (This also occurs with
`brew -x`, where x is any single character.)
This is because the `-?` pattern matches `-` followed by any single
character. We need to quote it to capture the intended meaning.
This provides a decent speedup:
```
$ hyperfine 'git checkout master; brew help' 'git checkout help_bash; brew help'
Benchmark 1: git checkout master; brew help
Time (mean ± σ): 506.4 ms ± 50.9 ms [User: 223.7 ms, System: 99.9 ms]
Range (min … max): 454.6 ms … 634.1 ms 10 runs
Benchmark 2: git checkout help_bash; brew help
Time (mean ± σ): 109.5 ms ± 57.1 ms [User: 1
```
and compares favourably to `pip3 help`:
```
$ hyperfine 'brew help' 'pip3 help'
Benchmark 1: brew help
Time (mean ± σ): 72.9 ms ± 15.9 ms [User: 4.9 ms, System: 6.3 ms]
Range (min … max): 53.6 ms … 126.6 ms 31 runs
Benchmark 2: pip3 help
Time (mean ± σ): 171.5 ms ± 6.1 ms [User: 131.6 ms, System: 24.7 ms]
Range (min … max): 164.2 ms … 189.3 ms 15 runs
Summary
brew help ran
2.35 ± 0.52 times faster than pip3 help
```
Similarly to have we have with other commands, use Bash to speed it up.
Before:
```
$ hyperfine "brew list"
Benchmark 1: brew list
Time (mean ± σ): 559.9 ms ± 122.8 ms [User: 176.2 ms, System: 126.2 ms]
Range (min … max): 503.2 ms … 907.3 ms 10 runs
```
After:
```
$ hyperfine "brew list"
Benchmark 1: brew list
Time (mean ± σ): 223.7 ms ± 31.9 ms [User: 35.0 ms, System: 53.4 ms]
Range (min … max): 198.1 ms … 302.4 ms 10
```
Petty after comparison because someone on Homebrew/discussions compared
them:
```
$ hyperfine "brew list" "pip3 list"
Benchmark 1: brew list
Time (mean ± σ): 213.1 ms ± 22.8 ms [User: 34.2 ms, System: 49.2 ms]
Range (min … max): 191.2 ms … 272.3 ms 13 runs
Benchmark 2: pip3 list
Time (mean ± σ): 271.7 ms ± 4.6 ms [User: 191.9 ms, System: 40.0 ms]
Range (min … max): 264.7 ms … 281.4 ms 10 runs
Summary
brew list ran
1.28 ± 0.14 times faster than pip3 list
```
---
While we're here, also add the `HOMEBREW_CASKROOM` environment variable
to make things a bit cleaner and use `--caskroom` in documentation.
Co-authored-by: Carlo Cabrera <30379873+carlocab@users.noreply.github.com>
This is a (relatively, for this Bash script) expensive operation that
can be trivially cached so: let's do so.
Speedup on my machine:
```
$ hyperfine "brew --version" "HOMEBREW_VERSION_CACHE=1 brew --version"
Benchmark 1: brew --version
Time (mean ± σ): 173.4 ms ± 5.1 ms [User: 28.7 ms, System: 67.0 ms]
Range (min … max): 167.3 ms … 182.9 ms 15 runs
Benchmark 2: HOMEBREW_VERSION_CACHE=1 brew --version
Time (mean ± σ): 145.9 ms ± 4.0 ms [User: 22.4 ms, System: 33.9 ms]
Range (min … max): 140.0 ms … 154.5 ms 17 runs
Summary
HOMEBREW_VERSION_CACHE=1 brew --version ran
1.19 ± 0.05 times faster than brew --version
```
Co-authored-by: Bo Anderson <mail@boanderson.me>
This avoids can avoid UID/EUID related issues with Ruby scripts passed
over `stdin` clashing with Ruby security features.
It's also just a bit nicer to have Ruby scripts in files instead.
While we're here:
- refactor some shared logic into a new `setup-gem-home-bundle-gemfile`
function in `ruby.sh`
- do some general cleanup of `lock.sh`
- prioritise `flock` over `python` in `lock.sh`