Skip to content

Commit 01825ac

Browse files
committed
UsesOnSystem: Collect macOS requirements
When determining macOS requirements for a cask, we may need to reference requirements from related on_system blocks (e.g., `on_monterey :or_older`, `on_ventura`, `on_sonoma :or_newer`) when `depends_on macos` isn't adequate. Sometimes casks specify different `depends_on macos` values in macOS on_system blocks but that value is only set when the cask is loaded in an environment that satisfies the on_system block's requirements. There are other casks that contain macOS on_system blocks and use `depends_on macos` outside of the on_system blocks but it may only use the macOS version of the lowest on_system block (e.g., `>= :monterey`), which isn't sufficient if the cask's values vary based on macOS version. To be able to simulate macOS versions that meet the requirements of all the on_system blocks in a cask, we need to collect the macOS requirements in a way that doesn't require OS simulation. This is also something that's easy to do in on_system methods, so this adds a `macos_requirements` array to `UsesOnSystem`, containing `MacOSRequirement` objects created from the cask's macOS on_system block conditions.
1 parent 3df8f70 commit 01825ac

File tree

4 files changed

+69
-1
lines changed

4 files changed

+69
-1
lines changed

Library/Homebrew/extend/on_system.rb

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# typed: strict
22
# frozen_string_literal: true
33

4+
require "requirements/macos_requirement"
45
require "simulate_system"
56

67
module OnSystem
@@ -27,6 +28,7 @@ class UsesOnSystem < T::Struct
2728
prop :intel, T::Boolean, default: false
2829
prop :linux, T::Boolean, default: false
2930
prop :macos, T::Boolean, default: false
31+
prop :macos_requirements, T::Set[MacOSRequirement], default: Set[]
3032

3133
alias arm? arm
3234
alias intel? intel
@@ -36,14 +38,28 @@ class UsesOnSystem < T::Struct
3638
# Whether the object has only default values.
3739
sig { returns(T::Boolean) }
3840
def empty?
39-
!@arm && !@intel && !@linux && !@macos
41+
!@arm && !@intel && !@linux && !@macos && @macos_requirements.empty?
4042
end
4143

4244
# Whether the object has any non-default values.
4345
sig { returns(T::Boolean) }
4446
def present? = !empty?
4547
end
4648

49+
# Converts an `or_condition` value to a suitable `MacOSRequirements`
50+
# `comparator` string, defaulting to `==` if the provided argument is `nil`.
51+
sig { params(symbol: T.nilable(Symbol)).returns(String) }
52+
def self.comparator_from_or_condition(symbol)
53+
case symbol
54+
when :or_newer
55+
">="
56+
when :or_older
57+
"<="
58+
else
59+
"=="
60+
end
61+
end
62+
4763
sig { params(arch: Symbol).returns(T::Boolean) }
4864
def self.arch_condition_met?(arch)
4965
raise ArgumentError, "Invalid arch condition: #{arch.inspect}" if ARCH_OPTIONS.exclude?(arch)
@@ -142,6 +158,9 @@ def self.setup_base_os_methods(base)
142158
else
143159
[macos.to_sym, nil]
144160
end
161+
162+
comparator = OnSystem.comparator_from_or_condition(or_condition)
163+
@uses_on_system.macos_requirements << MacOSRequirement.new([os_version], comparator:)
145164
return if !OnSystem.os_condition_met?(os_version, or_condition) && !OnSystem.os_condition_met?(:linux)
146165

147166
@called_in_on_system_block = true
@@ -172,6 +191,9 @@ def self.setup_macos_methods(base)
172191
@uses_on_system.macos = true
173192

174193
os_condition = OnSystem.condition_from_method_name T.must(__method__)
194+
comparator = OnSystem.comparator_from_or_condition(or_condition)
195+
@uses_on_system.macos_requirements << MacOSRequirement.new([os_condition], comparator:)
196+
175197
return unless OnSystem.os_condition_met? os_condition, or_condition
176198

177199
@on_system_block_min_os = T.let(

Library/Homebrew/test/cask/dsl_spec.rb

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -855,6 +855,12 @@ def caveats
855855
it "sets @uses_on_system.macos to true" do
856856
expect(cask.uses_on_system.macos?).to be true
857857
end
858+
859+
it "sets @uses_on_system.macos_requirements using macos argument" do
860+
expect(cask.uses_on_system.macos_requirements).to eq(Set[
861+
MacOSRequirement.new([:sequoia], comparator: ">="),
862+
])
863+
end
858864
end
859865

860866
context "when cask uses on_system_conditional" do
@@ -890,6 +896,14 @@ def caveats
890896
it "sets @uses_on_system.macos to true" do
891897
expect(cask.uses_on_system.macos?).to be true
892898
end
899+
900+
it "sets @uses_on_system.macos_requirements using on_* macos version conditions" do
901+
expect(cask.uses_on_system.macos_requirements).to eq(Set[
902+
MacOSRequirement.new([:big_sur], comparator: "<="),
903+
MacOSRequirement.new([:monterey], comparator: "=="),
904+
MacOSRequirement.new([:ventura], comparator: ">="),
905+
])
906+
end
893907
end
894908
end
895909
end

Library/Homebrew/test/extend/on_system_spec.rb

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,24 @@
5252
end
5353
end
5454

55+
describe "::comparator_from_or_condition" do
56+
it 'returns ">=" for `:or_newer` symbol' do
57+
expect(described_class.comparator_from_or_condition(:or_newer)).to eq(">=")
58+
end
59+
60+
it 'returns "<=" for `:or_older` symbol' do
61+
expect(described_class.comparator_from_or_condition(:or_older)).to eq("<=")
62+
end
63+
64+
it 'returns "==" for an unsupported symbol' do
65+
expect(described_class.comparator_from_or_condition(:nonexistent)).to eq("==")
66+
end
67+
68+
it 'returns "==" for `nil`' do
69+
expect(described_class.comparator_from_or_condition(nil)).to eq("==")
70+
end
71+
end
72+
5573
describe "::arch_condition_met?" do
5674
it "returns true if current arch equals provided arch" do
5775
Homebrew::SimulateSystem.with(arch: :arm) do

Library/Homebrew/test/formula_spec.rb

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2073,6 +2073,12 @@ def install
20732073
it "sets @uses_on_system.macos to true" do
20742074
expect(f_on_system.uses_on_system.macos?).to be true
20752075
end
2076+
2077+
it "sets @uses_on_system.macos_requirements using macos argument" do
2078+
expect(f_on_system.uses_on_system.macos_requirements).to eq(Set[
2079+
MacOSRequirement.new([:sequoia], comparator: ">="),
2080+
])
2081+
end
20762082
end
20772083

20782084
context "when formula uses on_system_conditional" do
@@ -2131,6 +2137,14 @@ def install
21312137
it "sets @uses_on_system.macos to true" do
21322138
expect(f_on_macos_versions.uses_on_system.macos?).to be true
21332139
end
2140+
2141+
it "sets @uses_on_system.macos_requirements using on_* macos version conditions" do
2142+
expect(f_on_macos_versions.uses_on_system.macos_requirements).to eq(Set[
2143+
MacOSRequirement.new([:big_sur], comparator: "<="),
2144+
MacOSRequirement.new([:monterey], comparator: "=="),
2145+
MacOSRequirement.new([:ventura], comparator: ">="),
2146+
])
2147+
end
21342148
end
21352149
end
21362150

0 commit comments

Comments
 (0)