From f3c25498f8ef8c7c8317883e1c7b12dfe236d124 Mon Sep 17 00:00:00 2001 From: Carlo Cabrera Date: Fri, 28 Mar 2025 17:21:28 +0800 Subject: [PATCH] bundle/commands/exec: check that `Brewfile` is installed with `--check` `brew bundle exec` behaves correctly only after doing `brew bundle install`. Running `brew bundle check` can be slow, so let's add a `--check` flag to `brew bundle exec` which will also run `brew bundle check` before `brew bundle exec` to ensure that the `Brewfile` has been installed before proceeding. --- Library/Homebrew/bundle/commands/check.rb | 6 +++--- Library/Homebrew/bundle/commands/exec.rb | 7 ++++++- Library/Homebrew/cmd/bundle.rb | 17 +++++++++++++---- .../sorbet/rbi/dsl/homebrew/cmd/bundle.rbi | 3 +++ 4 files changed, 25 insertions(+), 8 deletions(-) diff --git a/Library/Homebrew/bundle/commands/check.rb b/Library/Homebrew/bundle/commands/check.rb index 0432d96f18..fa5d31eebf 100644 --- a/Library/Homebrew/bundle/commands/check.rb +++ b/Library/Homebrew/bundle/commands/check.rb @@ -7,7 +7,7 @@ module Homebrew module Bundle module Commands module Check - def self.run(global: false, file: nil, no_upgrade: false, verbose: false) + def self.run(global: false, file: nil, no_upgrade: false, verbose: false, quiet: false) output_errors = verbose exit_on_first_error = !verbose check_result = Homebrew::Bundle::Checker.check( @@ -37,9 +37,9 @@ module Homebrew puts "Satisfy missing dependencies with `brew bundle install`." exit 1 - else - puts "The Brewfile's dependencies are satisfied." end + + puts "The Brewfile's dependencies are satisfied." unless quiet end end end diff --git a/Library/Homebrew/bundle/commands/exec.rb b/Library/Homebrew/bundle/commands/exec.rb index e84764383c..1de4687d15 100644 --- a/Library/Homebrew/bundle/commands/exec.rb +++ b/Library/Homebrew/bundle/commands/exec.rb @@ -13,7 +13,12 @@ module Homebrew module Exec PATH_LIKE_ENV_REGEX = /.+#{File::PATH_SEPARATOR}/ - def self.run(*args, global: false, file: nil, subcommand: "", services: false) + def self.run(*args, global: false, file: nil, subcommand: "", services: false, check: false) + if check + require "bundle/commands/check" + Homebrew::Bundle::Commands::Check.run(global:, file:, quiet: true) + end + # Store the old environment so we can check if things were already set # before we start mutating it. old_env = ENV.to_h diff --git a/Library/Homebrew/cmd/bundle.rb b/Library/Homebrew/cmd/bundle.rb index 27c5ece7c8..6d01ba4ac3 100755 --- a/Library/Homebrew/cmd/bundle.rb +++ b/Library/Homebrew/cmd/bundle.rb @@ -51,15 +51,15 @@ module Homebrew `brew bundle remove` [...]: Remove entries that match `name` from your `Brewfile`. Use `--formula`, `--cask`, `--tap`, `--mas`, `--whalebrew` or `--vscode` to remove only entries of the corresponding type. Passing `--formula` also removes matches against formula aliases and old formula names. - `brew bundle exec` : + `brew bundle exec` [--check] : Run an external command in an isolated build environment based on the `Brewfile` dependencies. This sanitized build environment ignores unrequested dependencies, which makes sure that things you didn't specify in your `Brewfile` won't get picked up by commands like `bundle install`, `npm install`, etc. It will also add compiler flags which will help with finding keg-only dependencies like `openssl`, `icu4c`, etc. - `brew bundle sh`: + `brew bundle sh` [--check]: Run your shell in a `brew bundle exec` environment. - `brew bundle env`: + `brew bundle env` [--check]: Print the environment variables that would be set in a `brew bundle exec` environment. EOS flag "--file=", @@ -126,6 +126,9 @@ module Homebrew description: "`dump` does not add `restart_service` to formula lines." switch "--zap", description: "`cleanup` casks using the `zap` command instead of `uninstall`." + switch "--check", + description: "Check that all dependencies in the Brewfile are installed before " \ + "running `exec`, `sh`, or `env`." conflicts "--all", "--no-vscode" conflicts "--vscode", "--no-vscode" @@ -134,6 +137,8 @@ module Homebrew named_args %w[install dump cleanup check exec list sh env edit] end + BUNDLE_EXEC_COMMANDS = %w[exec sh env].freeze + sig { override.void } def run # Keep this inside `run` to keep --help fast. @@ -144,6 +149,10 @@ module Homebrew raise UsageError, "This command does not take more than 1 subcommand argument." end + if args.check? && BUNDLE_EXEC_COMMANDS.exclude?(subcommand) + raise UsageError, "`--check` can be used only with #{BUNDLE_EXEC_COMMANDS.join(", ")}." + end + global = args.global? file = args.file args.zap? @@ -219,7 +228,7 @@ module Homebrew when "check" require "bundle/commands/check" Homebrew::Bundle::Commands::Check.run(global:, file:, no_upgrade:, verbose:) - when "exec", "sh", "env" + when *BUNDLE_EXEC_COMMANDS named_args = case subcommand when "exec" _subcommand, *named_args = args.named diff --git a/Library/Homebrew/sorbet/rbi/dsl/homebrew/cmd/bundle.rbi b/Library/Homebrew/sorbet/rbi/dsl/homebrew/cmd/bundle.rbi index b9fe56b358..7e19689a21 100644 --- a/Library/Homebrew/sorbet/rbi/dsl/homebrew/cmd/bundle.rbi +++ b/Library/Homebrew/sorbet/rbi/dsl/homebrew/cmd/bundle.rbi @@ -23,6 +23,9 @@ class Homebrew::Cmd::Bundle::Args < Homebrew::CLI::Args sig { returns(T::Boolean) } def casks?; end + sig { returns(T::Boolean) } + def check?; end + sig { returns(T::Boolean) } def cleanup?; end