From ca47b47f77d126d1f41c44253e98baa29ccb75f1 Mon Sep 17 00:00:00 2001 From: Mike McQuaid Date: Wed, 24 Feb 2021 16:02:00 +0000 Subject: [PATCH] Speedup `brew --prefix ` 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 ` 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. --- Library/Homebrew/brew.sh | 3 ++- Library/Homebrew/cmd/--prefix.rb | 14 ++++------- Library/Homebrew/prefix.sh | 29 ++++++++++++++++++++++ Library/Homebrew/test/cmd/--prefix_spec.rb | 2 +- docs/Manpage.md | 3 +-- manpages/brew.1 | 2 +- 6 files changed, 39 insertions(+), 14 deletions(-) create mode 100644 Library/Homebrew/prefix.sh diff --git a/Library/Homebrew/brew.sh b/Library/Homebrew/brew.sh index 9c4326f309..ae3f701820 100644 --- a/Library/Homebrew/brew.sh +++ b/Library/Homebrew/brew.sh @@ -48,7 +48,6 @@ HOMEBREW_TEMP="${HOMEBREW_TEMP:-${HOMEBREW_DEFAULT_TEMP}}" # Don't need shellcheck to follow these `source`. # shellcheck disable=SC1090 case "$*" in - --prefix) echo "$HOMEBREW_PREFIX"; exit 0 ;; --cellar) echo "$HOMEBREW_CELLAR"; exit 0 ;; --repository|--repo) echo "$HOMEBREW_REPOSITORY"; 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 ;; formulae) source "$HOMEBREW_LIBRARY/Homebrew/cmd/formulae.sh"; homebrew-formulae; 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 ##### diff --git a/Library/Homebrew/cmd/--prefix.rb b/Library/Homebrew/cmd/--prefix.rb index 90c6bbe36b..b68571c442 100644 --- a/Library/Homebrew/cmd/--prefix.rb +++ b/Library/Homebrew/cmd/--prefix.rb @@ -18,8 +18,7 @@ module Homebrew - macOS ARM: `#{HOMEBREW_MACOS_ARM_DEFAULT_PREFIX}` - Linux: `#{HOMEBREW_LINUX_DEFAULT_PREFIX}` - If is provided, display the location in the Cellar where - is or would be installed. + If is provided, display the location where is or would be installed. EOS switch "--unbrewed", description: "List files in Homebrew's prefix not installed by Homebrew." @@ -45,13 +44,10 @@ module Homebrew else formulae = args.named.to_resolved_formulae prefixes = formulae.map do |f| - if f.opt_prefix.exist? - f.opt_prefix - elsif args.installed? - nil - else - f.latest_installed_prefix - end + 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 end.compact puts prefixes if args.installed? diff --git a/Library/Homebrew/prefix.sh b/Library/Homebrew/prefix.sh new file mode 100644 index 0000000000..5da567bd6c --- /dev/null +++ b/Library/Homebrew/prefix.sh @@ -0,0 +1,29 @@ +# does the quickest output of brew --prefix possible for the basic cases: +# - `brew --prefix` (output HOMEBREW_PREFIX) +# - `brew --prefix ` (output HOMEBREW_PREFIX/opt/) +# 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 +} diff --git a/Library/Homebrew/test/cmd/--prefix_spec.rb b/Library/Homebrew/test/cmd/--prefix_spec.rb index 4759af5954..d1e0875874 100644 --- a/Library/Homebrew/test/cmd/--prefix_spec.rb +++ b/Library/Homebrew/test/cmd/--prefix_spec.rb @@ -8,7 +8,7 @@ describe "brew --prefix" do it "prints a given Formula's prefix", :integration_test do 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 be_a_success end diff --git a/docs/Manpage.md b/docs/Manpage.md index f0c66b6cd4..37953ca162 100644 --- a/docs/Manpage.md +++ b/docs/Manpage.md @@ -734,8 +734,7 @@ Display Homebrew's install path. *Default:* - macOS ARM: `/opt/homebrew` - Linux: `/home/linuxbrew/.linuxbrew` -If *`formula`* is provided, display the location in the Cellar where *`formula`* -is or would be installed. +If *`formula`* is provided, display the location where *`formula`* is or would be installed. * `--unbrewed`: List files in Homebrew's prefix not installed by Homebrew. diff --git a/manpages/brew.1 b/manpages/brew.1 index 1ed285dd4e..7125d4bbd5 100644 --- a/manpages/brew.1 +++ b/manpages/brew.1 @@ -997,7 +997,7 @@ Linux: \fB/home/linuxbrew/\.linuxbrew\fR .IP "" 0 . .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 \fB\-\-unbrewed\fR