From dc1fdc9f8d31a72b9f02ba76348b75d63f827d84 Mon Sep 17 00:00:00 2001 From: Mike McQuaid Date: Wed, 3 Mar 2021 10:22:54 +0000 Subject: [PATCH] Speedup `brew --version`. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Port `brew --version` to Bash to speed it up. While we're here: - remove (now) unused `Tap` Git methods - use `--quiet` instead of `-q` to be more verbose Benchmarks: ``` $ hyperfine --min-runs=3 --warmup=2 "git checkout origin/master; brew --version" "git checkout speedup_brew_version; brew --version" Benchmark #1: git checkout origin/master; brew --version Time (mean ± σ): 2.083 s ± 0.004 s [User: 396.8 ms, System: 597.2 ms] Range (min … max): 2.080 s … 2.088 s 3 runs Benchmark #2: git checkout speedup_brew_version; brew --version Time (mean ± σ): 847.9 ms ± 35.2 ms [User: 100.0 ms, System: 247.9 ms] Range (min … max): 824.1 ms … 888.3 ms 3 runs Summary 'git checkout speedup_brew_version; brew --version' ran 2.46 ± 0.10 times faster than 'git checkout origin/master; brew --version' ``` --- Library/Homebrew/brew.sh | 13 ++++++-- Library/Homebrew/cmd/--version.rb | 30 ----------------- Library/Homebrew/cmd/--version.sh | 31 ++++++++++++++++++ Library/Homebrew/extend/git_repository.rb | 4 +-- Library/Homebrew/tap.rb | 24 -------------- Library/Homebrew/test/cmd/--version_spec.rb | 6 ++-- .../spec/shared_context/integration_test.rb | 9 ++++++ Library/Homebrew/test/tap_spec.rb | 2 -- completions/bash/brew | 32 ------------------- completions/fish/brew.fish | 14 -------- completions/zsh/_brew | 18 ----------- docs/Manpage.md | 3 +- 12 files changed, 56 insertions(+), 130 deletions(-) delete mode 100644 Library/Homebrew/cmd/--version.rb create mode 100644 Library/Homebrew/cmd/--version.sh diff --git a/Library/Homebrew/brew.sh b/Library/Homebrew/brew.sh index b93fff0117..8b5de64369 100644 --- a/Library/Homebrew/brew.sh +++ b/Library/Homebrew/brew.sh @@ -188,9 +188,9 @@ update-preinstall() { # last $HOMEBREW_AUTO_UPDATE_SECS. if [[ "$HOMEBREW_COMMAND" = "cask" ]] then - tap_fetch_head="$HOMEBREW_LIBRARY/Taps/homebrew/homebrew-cask/.git/FETCH_HEAD" + tap_fetch_head="$HOMEBREW_CASK_REPOSITORY/.git/FETCH_HEAD" else - tap_fetch_head="$HOMEBREW_LIBRARY/Taps/homebrew/homebrew-core/.git/FETCH_HEAD" + tap_fetch_head="$HOMEBREW_CORE_REPOSITORY/.git/FETCH_HEAD" fi if [[ -f "$tap_fetch_head" && -n "$(find "$tap_fetch_head" -type f -mtime -"${HOMEBREW_AUTO_UPDATE_SECS}"s 2>/dev/null)" ]] @@ -314,6 +314,15 @@ then HOMEBREW_USER_AGENT_VERSION="2.X.Y" fi +HOMEBREW_CASK_REPOSITORY="$HOMEBREW_LIBRARY/Taps/homebrew/homebrew-cask" +HOMEBREW_CORE_REPOSITORY="$HOMEBREW_LIBRARY/Taps/homebrew/homebrew-core" + +# Don't need shellcheck to follow these `source`. +# shellcheck disable=SC1090 +case "$*" in + --version|-v) source "$HOMEBREW_LIBRARY/Homebrew/cmd/--version.sh"; homebrew-version; exit 0 ;; +esac + if [[ -n "$HOMEBREW_MACOS" ]] then HOMEBREW_PRODUCT="Homebrew" diff --git a/Library/Homebrew/cmd/--version.rb b/Library/Homebrew/cmd/--version.rb deleted file mode 100644 index f423cc7c0c..0000000000 --- a/Library/Homebrew/cmd/--version.rb +++ /dev/null @@ -1,30 +0,0 @@ -# typed: true -# frozen_string_literal: true - -require "cli/parser" - -module Homebrew - extend T::Sig - - module_function - - sig { returns(CLI::Parser) } - def __version_args - Homebrew::CLI::Parser.new do - description <<~EOS - Print the version numbers of Homebrew, Homebrew/homebrew-core and Homebrew/homebrew-cask - (if tapped) to standard output. - EOS - - named_args :none - end - end - - def __version - __version_args.parse - - puts "Homebrew #{HOMEBREW_VERSION}" - puts "#{CoreTap.instance.full_name} #{CoreTap.instance.version_string}" - puts "#{Tap.default_cask_tap.full_name} #{Tap.default_cask_tap.version_string}" if Tap.default_cask_tap.installed? - end -end diff --git a/Library/Homebrew/cmd/--version.sh b/Library/Homebrew/cmd/--version.sh new file mode 100644 index 0000000000..c1d92a7a0d --- /dev/null +++ b/Library/Homebrew/cmd/--version.sh @@ -0,0 +1,31 @@ +#: * `--version`, `-v` +#: +#: Print the version numbers of Homebrew, Homebrew/homebrew-core and Homebrew/homebrew-cask (if tapped) to standard output. + +version_string() { + local repo="$1" + if ! [ -d "$repo" ]; then + echo "N/A" + return + fi + + local pretty_revision + pretty_revision="$(git -C "$repo" rev-parse --short --verify --quiet HEAD)" + if [ -z "$pretty_revision" ]; then + echo "(no Git repository)" + return + fi + + local git_last_commit_date + git_last_commit_date=$(git -C "$repo" show -s --format='%cd' --date=short HEAD) + echo "(git revision ${pretty_revision}; last commit ${git_last_commit_date})" +} + +homebrew-version() { + echo "Homebrew $HOMEBREW_VERSION" + echo "Homebrew/homebrew-core $(version_string "$HOMEBREW_CORE_REPOSITORY")" + + if [ -d "$HOMEBREW_CASK_REPOSITORY" ]; then + echo "Homebrew/homebrew-cask $(version_string "$HOMEBREW_CASK_REPOSITORY")" + fi +} diff --git a/Library/Homebrew/extend/git_repository.rb b/Library/Homebrew/extend/git_repository.rb index b5a54742f8..a91ec91704 100644 --- a/Library/Homebrew/extend/git_repository.rb +++ b/Library/Homebrew/extend/git_repository.rb @@ -32,14 +32,14 @@ module GitRepositoryExtension # Gets the full commit hash of the HEAD commit. sig { params(safe: T::Boolean).returns(T.nilable(String)) } def git_head(safe: false) - popen_git("rev-parse", "--verify", "-q", "HEAD", safe: safe) + popen_git("rev-parse", "--verify", "--quiet", "HEAD", safe: safe) end # Gets a short commit hash of the HEAD commit. sig { params(length: T.nilable(Integer), safe: T::Boolean).returns(T.nilable(String)) } def git_short_head(length: nil, safe: false) short_arg = length.present? ? "--short=#{length}" : "--short" - popen_git("rev-parse", short_arg, "--verify", "-q", "HEAD", safe: safe) + popen_git("rev-parse", short_arg, "--verify", "--quiet", "HEAD", safe: safe) end # Gets the relative date of the last commit, e.g. "1 hour ago" diff --git a/Library/Homebrew/tap.rb b/Library/Homebrew/tap.rb index dc67a56ddf..ea4b535a03 100644 --- a/Library/Homebrew/tap.rb +++ b/Library/Homebrew/tap.rb @@ -170,13 +170,6 @@ class Tap path.git_head end - # git HEAD in short format for this {Tap}. - def git_short_head - raise TapUnavailableError, name unless installed? - - path.git_short_head(length: 4) - end - # Time since last git commit for this {Tap}. def git_last_commit raise TapUnavailableError, name unless installed? @@ -184,13 +177,6 @@ class Tap path.git_last_commit end - # Last git commit date for this {Tap}. - def git_last_commit_date - raise TapUnavailableError, name unless installed? - - path.git_last_commit_date - end - # The issues URL of this {Tap}. # e.g. `https://github.com/user/homebrew-repo/issues` sig { returns(T.nilable(String)) } @@ -204,16 +190,6 @@ class Tap name end - sig { returns(String) } - def version_string - return "N/A" unless installed? - - pretty_revision = git_short_head - return "(no Git repository)" unless pretty_revision - - "(git revision #{pretty_revision}; last commit #{git_last_commit_date})" - end - # True if this {Tap} is an official Homebrew tap. def official? user == "Homebrew" diff --git a/Library/Homebrew/test/cmd/--version_spec.rb b/Library/Homebrew/test/cmd/--version_spec.rb index 0717854349..944ff2981f 100644 --- a/Library/Homebrew/test/cmd/--version_spec.rb +++ b/Library/Homebrew/test/cmd/--version_spec.rb @@ -4,10 +4,8 @@ require "cmd/shared_examples/args_parse" describe "brew --version" do - it_behaves_like "parseable arguments" - - it "prints the Homebrew version", :integration_test do - expect { brew "--version" } + it "prints the Homebrew's version", :integration_test do + expect { brew_sh "--version" } .to output(/^Homebrew #{Regexp.escape(HOMEBREW_VERSION)}\n/o).to_stdout .and not_to_output.to_stderr .and be_a_success diff --git a/Library/Homebrew/test/support/helper/spec/shared_context/integration_test.rb b/Library/Homebrew/test/support/helper/spec/shared_context/integration_test.rb index f926ffb979..88ea92b7f3 100644 --- a/Library/Homebrew/test/support/helper/spec/shared_context/integration_test.rb +++ b/Library/Homebrew/test/support/helper/spec/shared_context/integration_test.rb @@ -124,6 +124,15 @@ RSpec.shared_context "integration test" do # rubocop:disable RSpec/ContextWordin end end + def brew_sh(*args) + Bundler.with_clean_env do + stdout, stderr, status = Open3.capture3("#{ENV["HOMEBREW_PREFIX"]}/bin/brew", *args) + $stdout.print stdout + $stderr.print stderr + status + end + end + def setup_test_formula(name, content = nil, bottle_block: nil) case name when /^testball/ diff --git a/Library/Homebrew/test/tap_spec.rb b/Library/Homebrew/test/tap_spec.rb index a9b63210bc..c762680710 100644 --- a/Library/Homebrew/test/tap_spec.rb +++ b/Library/Homebrew/test/tap_spec.rb @@ -210,9 +210,7 @@ describe Tap do setup_git_repo expect(homebrew_foo_tap.git_head).to eq("0453e16c8e3fac73104da50927a86221ca0740c2") - expect(homebrew_foo_tap.git_short_head).to eq("0453") expect(homebrew_foo_tap.git_last_commit).to match(/\A\d+ .+ ago\Z/) - expect(homebrew_foo_tap.git_last_commit_date).to eq("2017-01-22") end specify "#private?" do diff --git a/completions/bash/brew b/completions/bash/brew index d54fd07b4d..02345f433a 100644 --- a/completions/bash/brew +++ b/completions/bash/brew @@ -245,21 +245,6 @@ _brew___repository() { __brew_complete_tapped } -_brew___version() { - local cur="${COMP_WORDS[COMP_CWORD]}" - case "$cur" in - -*) - __brewcomp " - --debug - --help - --quiet - --verbose - " - return - ;; - esac -} - _brew__s() { local cur="${COMP_WORDS[COMP_CWORD]}" case "$cur" in @@ -287,21 +272,6 @@ _brew__s() { esac } -_brew__v() { - local cur="${COMP_WORDS[COMP_CWORD]}" - case "$cur" in - -*) - __brewcomp " - --debug - --help - --quiet - --verbose - " - return - ;; - esac -} - _brew_abv() { local cur="${COMP_WORDS[COMP_CWORD]}" case "$cur" in @@ -2316,9 +2286,7 @@ _brew() { --prefix) _brew___prefix ;; --repo) _brew___repo ;; --repository) _brew___repository ;; - --version) _brew___version ;; -S) _brew__s ;; - -v) _brew__v ;; abv) _brew_abv ;; analytics) _brew_analytics ;; audit) _brew_audit ;; diff --git a/completions/fish/brew.fish b/completions/fish/brew.fish index 6571c5d3a6..18fca766f4 100644 --- a/completions/fish/brew.fish +++ b/completions/fish/brew.fish @@ -271,13 +271,6 @@ __fish_brew_complete_arg '--repository' -l verbose -d 'Make some output more ver __fish_brew_complete_arg '--repository' -a '(__fish_brew_suggest_taps_installed)' -__fish_brew_complete_cmd '--version' 'Print the version numbers of Homebrew, Homebrew/homebrew-core and Homebrew/homebrew-cask (if tapped) to standard output' -__fish_brew_complete_arg '--version' -l debug -d 'Display any debugging information' -__fish_brew_complete_arg '--version' -l help -d 'Show this message' -__fish_brew_complete_arg '--version' -l quiet -d 'Make some output more quiet' -__fish_brew_complete_arg '--version' -l verbose -d 'Make some output more verbose' - - __fish_brew_complete_cmd '-S' 'Perform a substring search of cask tokens and formula names for text' __fish_brew_complete_arg '-S' -l cask -d 'Without text, list all locally available casks (including tapped ones, no online search is performed). With text, search online and locally for casks' __fish_brew_complete_arg '-S' -l closed -d 'Search for only closed GitHub pull requests' @@ -297,13 +290,6 @@ __fish_brew_complete_arg '-S' -l ubuntu -d 'Search for text in the given package __fish_brew_complete_arg '-S' -l verbose -d 'Make some output more verbose' -__fish_brew_complete_cmd '-v' 'Print the version numbers of Homebrew, Homebrew/homebrew-core and Homebrew/homebrew-cask (if tapped) to standard output' -__fish_brew_complete_arg '-v' -l debug -d 'Display any debugging information' -__fish_brew_complete_arg '-v' -l help -d 'Show this message' -__fish_brew_complete_arg '-v' -l quiet -d 'Make some output more quiet' -__fish_brew_complete_arg '-v' -l verbose -d 'Make some output more verbose' - - __fish_brew_complete_cmd 'abv' 'Display brief statistics for your Homebrew installation' __fish_brew_complete_arg 'abv' -l all -d 'Print JSON of all available formulae' __fish_brew_complete_arg 'abv' -l analytics -d 'List global Homebrew analytics data or, if specified, installation and build error data for formula (provided neither `HOMEBREW_NO_ANALYTICS` nor `HOMEBREW_NO_GITHUB_API` are set)' diff --git a/completions/zsh/_brew b/completions/zsh/_brew index d4bb71cf27..f4bfe2c4a5 100644 --- a/completions/zsh/_brew +++ b/completions/zsh/_brew @@ -337,15 +337,6 @@ _brew___repository() { '::tap:__brew_any_tap' } -# brew --version -_brew___version() { - _arguments \ - '--debug[Display any debugging information]' \ - '--help[Show this message]' \ - '--quiet[Make some output more quiet]' \ - '--verbose[Make some output more verbose]' -} - # brew -S _brew__s() { _arguments \ @@ -367,15 +358,6 @@ _brew__s() { '--verbose[Make some output more verbose]' } -# brew -v -_brew__v() { - _arguments \ - '--debug[Display any debugging information]' \ - '--help[Show this message]' \ - '--quiet[Make some output more quiet]' \ - '--verbose[Make some output more verbose]' -} - # brew abv _brew_abv() { _arguments \ diff --git a/docs/Manpage.md b/docs/Manpage.md index d747d2ceb3..83143520d9 100644 --- a/docs/Manpage.md +++ b/docs/Manpage.md @@ -749,8 +749,7 @@ If *`user`*`/`*`repo`* are provided, display where tap *`user`*`/`*`repo`*'s dir ### `--version`, `-v` -Print the version numbers of Homebrew, Homebrew/homebrew-core and Homebrew/homebrew-cask -(if tapped) to standard output. +Print the version numbers of Homebrew, Homebrew/homebrew-core and Homebrew/homebrew-cask (if tapped) to standard output. ## DEVELOPER COMMANDS