Speedup brew --prefix <formula>

This case is _really_ slow even although it's something we encourage
people to run often and build systems often do. The `brew --prefix`
case is really fast because it's just in Bash so: let's pull the
`brew --prefix <formula>` case into Bash too.

This doesn't handle any edge-cases like `--installed` and the formula
detection is pretty simple.

Also, to make this behaviour consistent, never output `Cellar` paths
from the (Ruby) `brew --prefix`; we never want people relying on the
Cellar paths anyway, only output them if the formula wasn't installed
(where, arguably, using a Cellar path is even worse) and the speedup is
worth this deviation in behaviour.
This commit is contained in:
Mike McQuaid 2021-02-24 16:02:00 +00:00
parent 485f73a32e
commit ca47b47f77
No known key found for this signature in database
GPG Key ID: 48A898132FD8EE70
6 changed files with 39 additions and 14 deletions

View File

@ -48,7 +48,6 @@ HOMEBREW_TEMP="${HOMEBREW_TEMP:-${HOMEBREW_DEFAULT_TEMP}}"
# Don't need shellcheck to follow these `source`. # Don't need shellcheck to follow these `source`.
# shellcheck disable=SC1090 # shellcheck disable=SC1090
case "$*" in case "$*" in
--prefix) echo "$HOMEBREW_PREFIX"; exit 0 ;;
--cellar) echo "$HOMEBREW_CELLAR"; exit 0 ;; --cellar) echo "$HOMEBREW_CELLAR"; exit 0 ;;
--repository|--repo) echo "$HOMEBREW_REPOSITORY"; exit 0 ;; --repository|--repo) echo "$HOMEBREW_REPOSITORY"; exit 0 ;;
--caskroom) echo "$HOMEBREW_PREFIX/Caskroom"; exit 0 ;; --caskroom) echo "$HOMEBREW_PREFIX/Caskroom"; exit 0 ;;
@ -56,6 +55,8 @@ case "$*" in
shellenv) source "$HOMEBREW_LIBRARY/Homebrew/cmd/shellenv.sh"; homebrew-shellenv; exit 0 ;; shellenv) source "$HOMEBREW_LIBRARY/Homebrew/cmd/shellenv.sh"; homebrew-shellenv; exit 0 ;;
formulae) source "$HOMEBREW_LIBRARY/Homebrew/cmd/formulae.sh"; homebrew-formulae; exit 0 ;; formulae) source "$HOMEBREW_LIBRARY/Homebrew/cmd/formulae.sh"; homebrew-formulae; exit 0 ;;
casks) source "$HOMEBREW_LIBRARY/Homebrew/cmd/casks.sh"; homebrew-casks; exit 0 ;; casks) source "$HOMEBREW_LIBRARY/Homebrew/cmd/casks.sh"; homebrew-casks; exit 0 ;;
# falls back to cmd/prefix.rb on a non-zero return
--prefix*) source "$HOMEBREW_LIBRARY/Homebrew/prefix.sh"; homebrew-prefix "$@" && exit 0 ;;
esac esac
##### #####

View File

@ -18,8 +18,7 @@ module Homebrew
- macOS ARM: `#{HOMEBREW_MACOS_ARM_DEFAULT_PREFIX}` - macOS ARM: `#{HOMEBREW_MACOS_ARM_DEFAULT_PREFIX}`
- Linux: `#{HOMEBREW_LINUX_DEFAULT_PREFIX}` - Linux: `#{HOMEBREW_LINUX_DEFAULT_PREFIX}`
If <formula> is provided, display the location in the Cellar where <formula> If <formula> is provided, display the location where <formula> is or would be installed.
is or would be installed.
EOS EOS
switch "--unbrewed", switch "--unbrewed",
description: "List files in Homebrew's prefix not installed by Homebrew." description: "List files in Homebrew's prefix not installed by Homebrew."
@ -45,13 +44,10 @@ module Homebrew
else else
formulae = args.named.to_resolved_formulae formulae = args.named.to_resolved_formulae
prefixes = formulae.map do |f| prefixes = formulae.map do |f|
if f.opt_prefix.exist? next nil if args.installed? && !f.opt_prefix.exist?
# this case wil be short-circuited by brew.sh logic for a single formula
f.opt_prefix f.opt_prefix
elsif args.installed?
nil
else
f.latest_installed_prefix
end
end.compact end.compact
puts prefixes puts prefixes
if args.installed? if args.installed?

View File

@ -0,0 +1,29 @@
# does the quickest output of brew --prefix possible for the basic cases:
# - `brew --prefix` (output HOMEBREW_PREFIX)
# - `brew --prefix <formula>` (output HOMEBREW_PREFIX/opt/<formula>)
# anything else? delegate to the slower cmd/--prefix.rb
homebrew-prefix() {
while [[ "$#" -gt 0 ]]; do
case $1 in
# check we actually have --prefix and not e.g. --prefixsomething
--prefix) local prefix="1"; shift ;;
# reject all other flags
-*) return 1 ;;
*) [ -n "$formula" ] && return 1; local formula="$1"; shift ;;
esac
done
[ -z "$prefix" ] && return 1
[ -z "$formula" ] && echo "$HOMEBREW_PREFIX" && return 0
local formula_path
if [ -f "$HOMEBREW_REPOSITORY/Library/Taps/homebrew/homebrew-core/${formula}.rb" ]; then
formula_path="$HOMEBREW_REPOSITORY/Library/Taps/homebrew/homebrew-core/${formula}.rb"
else
formula_path="$(find "$HOMEBREW_REPOSITORY/Library/Taps" -name "${formula}.rb" -print -quit)"
fi
[ -z "$formula_path" ] && return 1
echo "$HOMEBREW_PREFIX/opt/$formula"
return 0
}

View File

@ -8,7 +8,7 @@ describe "brew --prefix" do
it "prints a given Formula's prefix", :integration_test do it "prints a given Formula's prefix", :integration_test do
expect { brew "--prefix", testball } expect { brew "--prefix", testball }
.to output(%r{#{HOMEBREW_CELLAR}/testball}o).to_stdout .to output("#{HOMEBREW_PREFIX}/opt/testball\n").to_stdout
.and not_to_output.to_stderr .and not_to_output.to_stderr
.and be_a_success .and be_a_success
end end

View File

@ -734,8 +734,7 @@ Display Homebrew's install path. *Default:*
- macOS ARM: `/opt/homebrew` - macOS ARM: `/opt/homebrew`
- Linux: `/home/linuxbrew/.linuxbrew` - Linux: `/home/linuxbrew/.linuxbrew`
If *`formula`* is provided, display the location in the Cellar where *`formula`* If *`formula`* is provided, display the location where *`formula`* is or would be installed.
is or would be installed.
* `--unbrewed`: * `--unbrewed`:
List files in Homebrew's prefix not installed by Homebrew. List files in Homebrew's prefix not installed by Homebrew.

View File

@ -997,7 +997,7 @@ Linux: \fB/home/linuxbrew/\.linuxbrew\fR
.IP "" 0 .IP "" 0
. .
.P .P
If \fIformula\fR is provided, display the location in the Cellar where \fIformula\fR is or would be installed\. If \fIformula\fR is provided, display the location where \fIformula\fR is or would be installed\.
. .
.TP .TP
\fB\-\-unbrewed\fR \fB\-\-unbrewed\fR