Skip to content

Commit ac782bc

Browse files
authored
Merge pull request #21941 from Homebrew/cliff-perfume
Fix `supports_linux?` for platform-agnostic casks
2 parents c6c8636 + 9d79093 commit ac782bc

File tree

8 files changed

+68
-21
lines changed

8 files changed

+68
-21
lines changed

Library/Homebrew/cask/cask.rb

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ def config=(config)
123123

124124
def refresh
125125
@dsl = DSL.new(self)
126+
@contains_os_specific_artifacts = nil
126127
return unless @block
127128

128129
@dsl.instance_eval(&@block)
@@ -185,35 +186,41 @@ def supports_linux?
185186

186187
return false if contains_os_specific_artifacts?
187188

188-
os_value.present?
189+
# Casks with OS-specific blocks rely on the os stanza for Linux support
190+
return os_value.present? if @dsl.on_os_blocks_exist?
191+
192+
# Platform-agnostic casks: reject macOS-only artifacts and manual installers
193+
artifacts.none? do |a|
194+
Artifact::MACOS_ONLY_ARTIFACTS.include?(a.class) ||
195+
(a.is_a?(Artifact::Installer) && a.manual_install)
196+
end
189197
end
190198

191199
sig { returns(T::Boolean) }
192200
def contains_os_specific_artifacts?
193201
return false unless @dsl.on_system_blocks_exist?
194202

203+
return @contains_os_specific_artifacts unless @contains_os_specific_artifacts.nil?
204+
195205
any_loaded = T.let(false, T::Boolean)
196-
@contains_os_specific_artifacts ||= begin
197-
OnSystem::VALID_OS_ARCH_TAGS.each do |bottle_tag|
198-
Homebrew::SimulateSystem.with_tag(bottle_tag) do
199-
refresh
200-
201-
any_loaded = true if artifacts.any? do |artifact|
202-
(bottle_tag.linux? && ::Cask::Artifact::MACOS_ONLY_ARTIFACTS.include?(artifact.class)) ||
203-
(bottle_tag.macos? && ::Cask::Artifact::LINUX_ONLY_ARTIFACTS.include?(artifact.class))
204-
end
205-
end
206-
rescue CaskInvalidError
207-
# Invalid for this OS/arch tag; treat as having no OS-specific artifacts.
208-
next
209-
ensure
206+
OnSystem::VALID_OS_ARCH_TAGS.each do |bottle_tag|
207+
Homebrew::SimulateSystem.with_tag(bottle_tag) do
210208
refresh
211-
end
212209

213-
any_loaded
210+
any_loaded = true if artifacts.any? do |artifact|
211+
(bottle_tag.linux? && ::Cask::Artifact::MACOS_ONLY_ARTIFACTS.include?(artifact.class)) ||
212+
(bottle_tag.macos? && ::Cask::Artifact::LINUX_ONLY_ARTIFACTS.include?(artifact.class))
213+
end
214+
end
215+
rescue CaskInvalidError
216+
# Invalid for this OS/arch tag; treat as having no OS-specific artifacts.
217+
next
218+
ensure
219+
refresh
214220
end
215221

216-
@contains_os_specific_artifacts
222+
@contains_os_specific_artifacts = T.let(any_loaded, T.nilable(T::Boolean))
223+
any_loaded
217224
end
218225

219226
# The caskfile is needed during installation when there are

Library/Homebrew/cask/dsl.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ class DSL
112112
:autobump?,
113113
:no_autobump_message,
114114
:on_system_blocks_exist?,
115+
:on_os_blocks_exist?,
115116
:on_system_block_min_os,
116117
:depends_on_set_in_block?,
117118
*ORDINARY_ARTIFACT_CLASSES.map(&:dsl_key),
@@ -168,6 +169,7 @@ def initialize(cask)
168169
@name = T.let([], T::Array[String])
169170
@no_autobump_defined = T.let(false, T::Boolean)
170171
@on_system_blocks_exist = T.let(false, T::Boolean)
172+
@on_os_blocks_exist = T.let(false, T::Boolean)
171173
@on_system_block_min_os = T.let(nil, T.nilable(MacOSVersion))
172174
@os = T.let(nil, T.nilable(String))
173175
@os_set_in_block = T.let(false, T::Boolean)
@@ -197,6 +199,9 @@ def livecheck_defined? = @livecheck_defined
197199
sig { returns(T::Boolean) }
198200
def on_system_blocks_exist? = @on_system_blocks_exist
199201

202+
sig { returns(T::Boolean) }
203+
def on_os_blocks_exist? = @on_os_blocks_exist
204+
200205
# Specifies the cask's name.
201206
#
202207
# NOTE: Multiple names can be specified.
@@ -487,6 +492,7 @@ def os(macos: nil, linux: nil)
487492

488493
set_unique_stanza(:os, should_return) do
489494
@on_system_blocks_exist = true
495+
@on_os_blocks_exist = true
490496

491497
on_system_conditional(macos:, linux:)
492498
end

Library/Homebrew/on_system.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ def self.setup_base_os_methods(base)
8787
BASE_OS_OPTIONS.each do |base_os|
8888
base.define_method(:"on_#{base_os}") do |&block|
8989
@on_system_blocks_exist = T.let(true, T.nilable(TrueClass))
90+
@on_os_blocks_exist = T.let(true, T.nilable(TrueClass))
9091

9192
return unless OnSystem.os_condition_met? OnSystem.condition_from_method_name(T.must(__method__))
9293

@@ -100,6 +101,7 @@ def self.setup_base_os_methods(base)
100101

101102
base.define_method(:on_system) do |linux, macos:, &block|
102103
@on_system_blocks_exist = T.let(true, T.nilable(TrueClass))
104+
@on_os_blocks_exist = T.let(true, T.nilable(TrueClass))
103105

104106
raise ArgumentError, "The first argument to `on_system` must be `:linux`" if linux != :linux
105107

@@ -133,6 +135,7 @@ def self.setup_macos_methods(base)
133135
MacOSVersion::SYMBOLS.each_key do |os_name|
134136
base.define_method(:"on_#{os_name}") do |or_condition = nil, &block|
135137
@on_system_blocks_exist = T.let(true, T.nilable(TrueClass))
138+
@on_os_blocks_exist = T.let(true, T.nilable(TrueClass))
136139

137140
os_condition = OnSystem.condition_from_method_name T.must(__method__)
138141
return unless OnSystem.os_condition_met? os_condition, or_condition

Library/Homebrew/sorbet/rbi/dsl/cask/cask.rbi

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Library/Homebrew/test/bundle/skipper_spec.rb

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,17 @@
8484
end
8585
end
8686

87+
context "with a platform-agnostic cask on Linux", :needs_linux do
88+
let(:entry) { Homebrew::Bundle::Dsl::Entry.new(:cask, "testball") }
89+
90+
it "does not skip" do
91+
allow(Cask::CaskLoader).to receive(:load).with("testball").and_return(
92+
instance_double(Cask::Cask, supports_linux?: true),
93+
)
94+
expect(skipper.skip?(entry)).to be false
95+
end
96+
end
97+
8798
context "with a listed formula in a failed tap" do
8899
let(:entry) { Homebrew::Bundle::Dsl::Entry.new(:brew, "org/repo/formula") }
89100

Library/Homebrew/test/cask/cask_spec.rb

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -393,8 +393,24 @@
393393
end
394394

395395
describe "#supports_linux?" do
396-
it "returns false when Linux support is not explicitly declared" do
397-
expect(Cask::CaskLoader.load("with-non-executable-binary").supports_linux?).to be false
396+
it "reflects whether the cask has only platform-agnostic artifacts" do
397+
expect(Cask::CaskLoader.load("with-non-executable-binary").supports_linux?).to be true
398+
expect(Cask::CaskLoader.load("basic-cask").supports_linux?).to be false
399+
expect(Cask::CaskLoader.load("with-installer-manual").supports_linux?).to be false
400+
401+
arch_only_cask = described_class.new("arch-only-binary") do
402+
version "1.0"
403+
sha256 arm: "aaaa", intel: "bbbb"
404+
405+
url "https://brew.sh/test-#{version}.tar.gz"
406+
name "Arch Only Binary"
407+
desc "Cask with arch-only sha256 and a binary artifact"
408+
homepage "https://brew.sh"
409+
410+
binary "some-tool"
411+
end
412+
413+
expect(arch_only_cask.supports_linux?).to be true
398414
end
399415
end
400416

Library/Homebrew/test/cask/info_spec.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,7 @@ def mock_cask_installed(cask_name)
302302
https://brew.sh/with-binary
303303
Not installed
304304
From: https://github.com/Homebrew/homebrew-cask/blob/HEAD/Casks/w/with-non-executable-binary.rb
305-
#{requirements_section(installed("macOS >= 10.15"))}
305+
#{requirements_section(installed("macOS >= 10.15 (or Linux)"))}
306306
==> Artifacts
307307
naked_non_executable (Binary)
308308
EOS

Library/Homebrew/test/spec_helper.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,7 @@
287287
example.example.set_exception(e)
288288
ensure
289289
ENV.replace(@__env)
290+
Homebrew::SimulateSystem.clear
290291
Context.current = Context::ContextStruct.new
291292

292293
$stdout.reopen(@__stdout)

0 commit comments

Comments
 (0)