diff --git a/Library/Homebrew/formula.rb b/Library/Homebrew/formula.rb index 5953b36097..d5c9730fb0 100644 --- a/Library/Homebrew/formula.rb +++ b/Library/Homebrew/formula.rb @@ -2918,8 +2918,32 @@ class Formula # # If `satisfy` returns `false` then a bottle will not be used and instead # the {Formula} will be built from source and `reason` will be printed. - def pour_bottle?(&block) + # + # Alternatively, a preset reason can be passed as a symbol: + #
pour_bottle? reason: :clt_required+ def pour_bottle?(reason: nil, &block) @pour_bottle_check = PourBottleCheck.new(self) + + if reason.present? && block.present? + raise ArgumentError, "Do not pass both a reason and a block to `pour_bottle?`" + end + + block ||= case reason + when :clt_required + lambda do |_| + on_macos do + T.cast(self, PourBottleCheck).reason(+<<~EOS) + The bottle needs the Apple Command Line Tools to be installed. + You can install them, if desired, with: + xcode-select --install + EOS + T.cast(self, PourBottleCheck).satisfy { MacOS::CLT.installed? } + end + end + else + raise ArgumentError, "Invalid `pour_bottle?` reason" if reason.present? + end + @pour_bottle_check.instance_eval(&block) end diff --git a/Library/Homebrew/test/formula_spec.rb b/Library/Homebrew/test/formula_spec.rb index 2cdb36c091..79f484096e 100644 --- a/Library/Homebrew/test/formula_spec.rb +++ b/Library/Homebrew/test/formula_spec.rb @@ -995,6 +995,65 @@ describe Formula do expect(f).to pour_bottle end + + it "returns false with `reason: :clt_required` on macOS", :needs_macos do + # Pretend CLT is not installed + allow(MacOS::CLT).to receive(:installed?).and_return(false) + + f = formula "foo" do + url "foo-1.0" + + pour_bottle? reason: :clt_required + end + + expect(f).not_to pour_bottle + end + + it "returns true with `reason: :clt_required` on macOS", :needs_macos do + # Pretend CLT is installed + allow(MacOS::CLT).to receive(:installed?).and_return(true) + + f = formula "foo" do + url "foo-1.0" + + pour_bottle? reason: :clt_required + end + + expect(f).to pour_bottle + end + + it "returns true with `reason: :clt_required` on Linux", :needs_linux do + f = formula "foo" do + url "foo-1.0" + + pour_bottle? reason: :clt_required + end + + expect(f).to pour_bottle + end + + it "throws an error if passed both a symbol and a block" do + expect do + formula "foo" do + url "foo-1.0" + + pour_bottle? reason: :clt_required do + reason "true reason" + satisfy { true } + end + end + end.to raise_error(ArgumentError, "Do not pass both a reason and a block to `pour_bottle?`") + end + + it "throws an error if passed an invalid symbol" do + expect do + formula "foo" do + url "foo-1.0" + + pour_bottle? reason: :foo + end + end.to raise_error(ArgumentError, "Invalid `pour_bottle?` reason") + end end describe "alias changes" do