diff --git a/Library/Homebrew/brew.sh b/Library/Homebrew/brew.sh index 44bc124540..d57ad2e399 100644 --- a/Library/Homebrew/brew.sh +++ b/Library/Homebrew/brew.sh @@ -82,7 +82,9 @@ HOMEBREW_TEMP="${HOMEBREW_TEMP:-${HOMEBREW_DEFAULT_TEMP}}" # Don't need to handle a default case. # HOMEBREW_LIBRARY set by bin/brew # shellcheck disable=SC2249,SC2154 -case "$*" in +# +# commands that take a single or no arguments. +case "$1" in --cellar) echo "${HOMEBREW_CELLAR}" exit 0 @@ -99,12 +101,6 @@ case "$*" in echo "${HOMEBREW_CACHE}" exit 0 ;; - shellenv) - source "${HOMEBREW_LIBRARY}/Homebrew/cmd/shellenv.sh" - shift - homebrew-shellenv "$1" - exit 0 - ;; formulae) source "${HOMEBREW_LIBRARY}/Homebrew/cmd/formulae.sh" homebrew-formulae @@ -115,6 +111,21 @@ case "$*" in homebrew-casks exit 0 ;; + shellenv) + source "${HOMEBREW_LIBRARY}/Homebrew/cmd/shellenv.sh" + shift + homebrew-shellenv "$1" + exit 0 + ;; + setup-ruby) + source "${HOMEBREW_LIBRARY}/Homebrew/cmd/setup-ruby.sh" + shift + homebrew-setup-ruby "$1" + exit 0 + ;; +esac +# functions that take multiple arguments or handle multiple commands. +case "$@" in # falls back to cmd/--prefix.rb and cmd/--cellar.rb on a non-zero return --prefix* | --cellar*) source "${HOMEBREW_LIBRARY}/Homebrew/formula_path.sh" @@ -497,7 +508,8 @@ HOMEBREW_CORE_REPOSITORY="${HOMEBREW_LIBRARY}/Taps/homebrew/homebrew-core" # shellcheck disable=SC2034 HOMEBREW_CASK_REPOSITORY="${HOMEBREW_LIBRARY}/Taps/homebrew/homebrew-cask" -case "$*" in +# commands that take a single or no arguments. +case "$1" in --version | -v) source "${HOMEBREW_LIBRARY}/Homebrew/cmd/--version.sh" homebrew-version diff --git a/Library/Homebrew/cmd/setup-ruby.sh b/Library/Homebrew/cmd/setup-ruby.sh index d677899dfd..e39d893909 100644 --- a/Library/Homebrew/cmd/setup-ruby.sh +++ b/Library/Homebrew/cmd/setup-ruby.sh @@ -1,6 +1,8 @@ -#: * `setup-ruby` +#: * `setup-ruby [command]` #: #: Installs and configures Homebrew's Ruby. +#: If `command` is passed, it will only run Bundler if necessary for that +#: command. #: # HOMEBREW_LIBRARY is from the user environment. @@ -12,11 +14,29 @@ homebrew-setup-ruby() { source "${HOMEBREW_LIBRARY}/Homebrew/utils/ruby.sh" setup-ruby-path - if [[ -z "${HOMEBREW_DEVELOPER}" && -z "${HOMEBREW_RUBY3}" ]] + if [[ -z "${HOMEBREW_DEVELOPER}" ]] then return fi + # Avoid running Bundler if the command doesn't need it. + local command="$1" + if [[ -n "${command}" ]] + then + source "${HOMEBREW_LIBRARY}/Homebrew/command_path.sh" + + command_path="$(homebrew-command-path "${command}")" + if [[ -n "${command_path}" && "${command_path}" != *"/dev-cmd/"* ]] + then + return + fi + + if ! grep -q "Homebrew.install_bundler_gems\!" "${command_path}" + then + return + fi + fi + GEM_VERSION="$("${HOMEBREW_RUBY_PATH}" "${HOMEBREW_RUBY_DISABLE_OPTIONS}" /dev/stdin <<<'require "rbconfig"; puts RbConfig::CONFIG["ruby_version"]')" echo "${GEM_VERSION}" GEM_HOME="${HOMEBREW_LIBRARY}/Homebrew/vendor/bundle/ruby/${GEM_VERSION}" diff --git a/Library/Homebrew/command_path.sh b/Library/Homebrew/command_path.sh index b3288a7adc..362b654abe 100644 --- a/Library/Homebrew/command_path.sh +++ b/Library/Homebrew/command_path.sh @@ -6,7 +6,8 @@ homebrew-command-path() { case "$1" in # check we actually have command and not e.g. commandsomething command) ;; - *) return 1 ;; + command*) return 1 ;; + *) ;; esac local first_command found_command diff --git a/Library/Homebrew/rubocops/all.rb b/Library/Homebrew/rubocops/all.rb index 7c92c16e59..b42f50665e 100644 --- a/Library/Homebrew/rubocops/all.rb +++ b/Library/Homebrew/rubocops/all.rb @@ -12,6 +12,7 @@ require_relative "presence" require_relative "present" require_relative "safe_navigation_with_blank" require_relative "shell_commands" +require_relative "install_bundler_gems" # formula audit cops require_relative "bottle" diff --git a/Library/Homebrew/rubocops/extend/formula_cop.rb b/Library/Homebrew/rubocops/extend/formula_cop.rb index 02f1ad1ec1..b443c5e615 100644 --- a/Library/Homebrew/rubocops/extend/formula_cop.rb +++ b/Library/Homebrew/rubocops/extend/formula_cop.rb @@ -20,7 +20,7 @@ module RuboCop # This method is called by RuboCop and is the main entry point. def on_class(node) - @file_path = processed_source.buffer.name + @file_path = processed_source.file_path return unless file_path_allowed? return unless formula_class?(node) @@ -228,10 +228,9 @@ module RuboCop end def file_path_allowed? - paths_to_exclude = [%r{/Library/Homebrew/test/}] return true if @file_path.nil? # file_path is nil when source is directly passed to the cop, e.g. in specs - !@file_path.match?(Regexp.union(paths_to_exclude)) + !@file_path.include?("/Library/Homebrew/test/") end def on_system_methods diff --git a/Library/Homebrew/rubocops/install_bundler_gems.rb b/Library/Homebrew/rubocops/install_bundler_gems.rb new file mode 100644 index 0000000000..c65a2931a4 --- /dev/null +++ b/Library/Homebrew/rubocops/install_bundler_gems.rb @@ -0,0 +1,21 @@ +# typed: true +# frozen_string_literal: true + +module RuboCop + module Cop + module Homebrew + # Enforces the use of `Homebrew.install_bundler_gems!` in dev-cmd. + class InstallBundlerGems < Base + MSG = "Only use `Homebrew.install_bundler_gems!` in dev-cmd." + RESTRICT_ON_SEND = [:install_bundler_gems!].freeze + + def on_send(node) + file_path = processed_source.file_path + return if file_path.match?(%r{/(dev-cmd/.+|standalone/init|startup/bootsnap)\.rb\z}) + + add_offense(node) + end + end + end + end +end diff --git a/Library/Homebrew/test/rubocops/install_bundler_gems_spec.rb b/Library/Homebrew/test/rubocops/install_bundler_gems_spec.rb new file mode 100644 index 0000000000..032ddd5c25 --- /dev/null +++ b/Library/Homebrew/test/rubocops/install_bundler_gems_spec.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +require "rubocops/install_bundler_gems" + +RSpec.describe RuboCop::Cop::Homebrew::InstallBundlerGems, :config do + it "registers an offense and corrects when using `Homebrew.install_bundler_gems!`" do + expect_offense(<<~RUBY) + Homebrew.install_bundler_gems! + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Only use `Homebrew.install_bundler_gems!` in dev-cmd. + RUBY + end +end