diff --git a/Library/Homebrew/cask/audit.rb b/Library/Homebrew/cask/audit.rb index 4f8bae5c14..caf308cd65 100644 --- a/Library/Homebrew/cask/audit.rb +++ b/Library/Homebrew/cask/audit.rb @@ -718,7 +718,7 @@ module Cask cask_min_os = [on_system_block_min_os, cask.depends_on.macos&.minimum_version].compact.max odebug "Declared minimum OS version: #{cask_min_os&.to_sym}" return if cask_min_os&.to_sym == min_os.to_sym - return if cask.on_system_blocks_exist? && + return if cask.uses_on_system.present? && OnSystem.arch_condition_met?(:arm) && cask_min_os.present? && cask_min_os < MacOSVersion.new("11") diff --git a/Library/Homebrew/cask/cask.rb b/Library/Homebrew/cask/cask.rb index ec26010e90..c1deddc9ce 100644 --- a/Library/Homebrew/cask/cask.rb +++ b/Library/Homebrew/cask/cask.rb @@ -414,7 +414,7 @@ module Cask hash = to_h variations = {} - if @dsl.on_system_blocks_exist? + if @dsl.uses_on_system.present? begin OnSystem::VALID_OS_ARCH_TAGS.each do |bottle_tag| next if bottle_tag.linux? && @dsl.os.nil? diff --git a/Library/Homebrew/cask/dsl.rb b/Library/Homebrew/cask/dsl.rb index ca35eebe39..b77003c608 100644 --- a/Library/Homebrew/cask/dsl.rb +++ b/Library/Homebrew/cask/dsl.rb @@ -106,9 +106,9 @@ module Cask :no_autobump!, :autobump?, :no_autobump_message, - :on_system_blocks_exist?, - :on_system_block_min_os, :depends_on_set_in_block?, + :on_system_block_min_os, + :uses_on_system, *ORDINARY_ARTIFACT_CLASSES.map(&:dsl_key), *ACTIVATABLE_ARTIFACT_CLASSES.map(&:dsl_key), *ARTIFACT_BLOCK_CLASSES.flat_map { |klass| [klass.dsl_key, klass.uninstall_dsl_key] }, @@ -121,6 +121,11 @@ module Cask :disable_date, :disable_reason, :disable_replacement_cask, :disable_replacement_formula, :on_system_block_min_os + # A `UsesOnSystem` object that contains boolean instance variables + # indicating whether the cask uses specific on_system methods. + sig { returns(OnSystem::UsesOnSystem) } + attr_reader :uses_on_system + sig { params(cask: Cask).void } def initialize(cask) # NOTE: Variables set by `set_unique_stanza` must be initialized to `nil`. @@ -153,13 +158,13 @@ module Cask @name = T.let([], T::Array[String]) @autobump = T.let(true, T::Boolean) @no_autobump_defined = T.let(false, T::Boolean) - @on_system_blocks_exist = T.let(false, T::Boolean) @os = T.let(nil, T.nilable(String)) @on_system_block_min_os = T.let(nil, T.nilable(MacOSVersion)) @sha256 = T.let(nil, T.nilable(T.any(Checksum, Symbol))) @staged_path = T.let(nil, T.nilable(Pathname)) @token = T.let(cask.token, String) @url = T.let(nil, T.nilable(URL)) + @uses_on_system = T.let(OnSystem::UsesOnSystem.new, OnSystem::UsesOnSystem) @version = T.let(nil, T.nilable(DSL::Version)) end @@ -175,9 +180,6 @@ module Cask sig { returns(T::Boolean) } def livecheck_defined? = @livecheck_defined - sig { returns(T::Boolean) } - def on_system_blocks_exist? = @on_system_blocks_exist - # Specifies the cask's name. # # NOTE: Multiple names can be specified. @@ -392,8 +394,15 @@ module Cask x86_64 ||= intel if intel.present? && x86_64.nil? set_unique_stanza(:sha256, should_return) do - if arm.present? || x86_64.present? || x86_64_linux.present? || arm64_linux.present? - @on_system_blocks_exist = true + @uses_on_system.arm = true if arm.present? + @uses_on_system.intel = true if x86_64.present? + if x86_64_linux.present? + @uses_on_system.intel = true + @uses_on_system.linux = true + end + if arm64_linux.present? + @uses_on_system.arm = true + @uses_on_system.linux = true end val = arg || on_system_conditional( @@ -424,7 +433,8 @@ module Cask should_return = arm.nil? && intel.nil? set_unique_stanza(:arch, should_return) do - @on_system_blocks_exist = true + @uses_on_system.arm = true if arm + @uses_on_system.intel = true if intel on_arch_conditional(arm:, intel:) end @@ -449,7 +459,8 @@ module Cask should_return = macos.nil? && linux.nil? set_unique_stanza(:os, should_return) do - @on_system_blocks_exist = true + @uses_on_system.macos = true if macos + @uses_on_system.linux = true if linux on_system_conditional(macos:, linux:) end diff --git a/Library/Homebrew/dev-cmd/bump-cask-pr.rb b/Library/Homebrew/dev-cmd/bump-cask-pr.rb index 72e20c132e..83661f4aa7 100644 --- a/Library/Homebrew/dev-cmd/bump-cask-pr.rb +++ b/Library/Homebrew/dev-cmd/bump-cask-pr.rb @@ -199,7 +199,7 @@ module Homebrew # to on_system blocks referencing macOS versions. os_values = [] arch_values = depends_on_archs.presence || [] - if cask.on_system_blocks_exist? + if cask.uses_on_system.present? OnSystem::BASE_OS_OPTIONS.each do |os| os_values << if os == :macos (current_os_is_macos ? current_os : newest_macos) @@ -235,7 +235,7 @@ module Homebrew old_cask = begin Cask::CaskLoader.load(cask.sourcefile_path) rescue Cask::CaskInvalidError, Cask::CaskUnreadableError - raise unless cask.on_system_blocks_exist? + raise unless cask.uses_on_system.present? end next if old_cask.nil? @@ -262,7 +262,7 @@ module Homebrew replacement_pairs << [/"#{old_hash}"/, ":no_check"] if old_hash != :no_check elsif old_hash == :no_check && new_hash != :no_check replacement_pairs << [":no_check", "\"#{new_hash}\""] if new_hash.is_a?(String) - elsif new_hash && !cask.on_system_blocks_exist? && cask.languages.empty? + elsif new_hash && cask.uses_on_system.blank? && cask.languages.empty? replacement_pairs << [old_hash.to_s, new_hash.to_s] elsif old_hash != :no_check opoo "Multiple checksum replacements required; ignoring specified `--sha256` argument." if new_hash diff --git a/Library/Homebrew/dev-cmd/bump.rb b/Library/Homebrew/dev-cmd/bump.rb index 1d510088fa..88f6802119 100644 --- a/Library/Homebrew/dev-cmd/bump.rb +++ b/Library/Homebrew/dev-cmd/bump.rb @@ -305,7 +305,7 @@ module Homebrew ).returns(VersionBumpInfo) } def retrieve_versions_by_arch(formula_or_cask:, repositories:, name:) - is_cask_with_blocks = formula_or_cask.is_a?(Cask::Cask) && formula_or_cask.on_system_blocks_exist? + is_cask_with_blocks = formula_or_cask.is_a?(Cask::Cask) && formula_or_cask.uses_on_system.present? type, version_name = if formula_or_cask.is_a?(Formula) [:formula, "formula version:"] else diff --git a/Library/Homebrew/extend/on_system.rb b/Library/Homebrew/extend/on_system.rb index a4426cd5e0..f881dbd3b1 100644 --- a/Library/Homebrew/extend/on_system.rb +++ b/Library/Homebrew/extend/on_system.rb @@ -22,6 +22,28 @@ module OnSystem T::Array[Utils::Bottles::Tag], ) + class UsesOnSystem < T::Struct + prop :arm, T::Boolean, default: false + prop :intel, T::Boolean, default: false + prop :linux, T::Boolean, default: false + prop :macos, T::Boolean, default: false + + alias arm? arm + alias intel? intel + alias linux? linux + alias macos? macos + + # Whether the object has only default values. + sig { returns(T::Boolean) } + def empty? + !@arm && !@intel && !@linux && !@macos + end + + # Whether the object has any non-default values. + sig { returns(T::Boolean) } + def present? = !empty? + end + sig { params(arch: Symbol).returns(T::Boolean) } def self.arch_condition_met?(arch) raise ArgumentError, "Invalid arch condition: #{arch.inspect}" if ARCH_OPTIONS.exclude?(arch) @@ -65,7 +87,8 @@ module OnSystem def self.setup_arch_methods(base) ARCH_OPTIONS.each do |arch| base.define_method(:"on_#{arch}") do |&block| - @on_system_blocks_exist = T.let(true, T.nilable(T::Boolean)) + @uses_on_system ||= T.let(OnSystem::UsesOnSystem.new, T.nilable(OnSystem::UsesOnSystem)) + @uses_on_system.send(:"#{arch}=", true) return unless OnSystem.arch_condition_met? OnSystem.condition_from_method_name(T.must(__method__)) @@ -78,7 +101,9 @@ module OnSystem end base.define_method(:on_arch_conditional) do |arm: nil, intel: nil| - @on_system_blocks_exist = true + @uses_on_system ||= T.let(OnSystem::UsesOnSystem.new, T.nilable(OnSystem::UsesOnSystem)) + @uses_on_system.arm = true if arm + @uses_on_system.intel = true if intel if OnSystem.arch_condition_met? :arm arm @@ -92,7 +117,8 @@ module OnSystem def self.setup_base_os_methods(base) BASE_OS_OPTIONS.each do |base_os| base.define_method(:"on_#{base_os}") do |&block| - @on_system_blocks_exist = true + @uses_on_system ||= T.let(OnSystem::UsesOnSystem.new, T.nilable(OnSystem::UsesOnSystem)) + @uses_on_system.send(:"#{base_os}=", true) return unless OnSystem.os_condition_met? OnSystem.condition_from_method_name(T.must(__method__)) @@ -105,7 +131,9 @@ module OnSystem end base.define_method(:on_system) do |linux, macos:, &block| - @on_system_blocks_exist = true + @uses_on_system ||= T.let(OnSystem::UsesOnSystem.new, T.nilable(OnSystem::UsesOnSystem)) + @uses_on_system.linux = true + @uses_on_system.macos = true raise ArgumentError, "The first argument to `on_system` must be `:linux`" if linux != :linux @@ -124,7 +152,9 @@ module OnSystem end base.define_method(:on_system_conditional) do |macos: nil, linux: nil| - @on_system_blocks_exist = true + @uses_on_system ||= T.let(OnSystem::UsesOnSystem.new, T.nilable(OnSystem::UsesOnSystem)) + @uses_on_system.macos = true if macos + @uses_on_system.linux = true if linux if OnSystem.os_condition_met?(:macos) && macos.present? macos @@ -138,7 +168,8 @@ module OnSystem def self.setup_macos_methods(base) MacOSVersion::SYMBOLS.each_key do |os_name| base.define_method(:"on_#{os_name}") do |or_condition = nil, &block| - @on_system_blocks_exist = true + @uses_on_system ||= T.let(OnSystem::UsesOnSystem.new, T.nilable(OnSystem::UsesOnSystem)) + @uses_on_system.macos = true os_condition = OnSystem.condition_from_method_name T.must(__method__) return unless OnSystem.os_condition_met? os_condition, or_condition diff --git a/Library/Homebrew/formula.rb b/Library/Homebrew/formula.rb index 740e258a32..3a2c31a34e 100644 --- a/Library/Homebrew/formula.rb +++ b/Library/Homebrew/formula.rb @@ -270,7 +270,7 @@ class Formula @follow_installed_alias = T.let(true, T::Boolean) @prefix_returns_versioned_prefix = T.let(false, T.nilable(T::Boolean)) @oldname_locks = T.let([], T::Array[FormulaLock]) - @on_system_blocks_exist = T.let(false, T::Boolean) + @uses_on_system = T.let(OnSystem::UsesOnSystem.new, OnSystem::UsesOnSystem) end sig { params(spec_sym: Symbol).void } @@ -2591,7 +2591,7 @@ class Formula variations = {} - if path.exist? && on_system_blocks_exist? + if path.exist? && uses_on_system.present? formula_contents = path.read OnSystem::VALID_OS_ARCH_TAGS.each do |bottle_tag| Homebrew::SimulateSystem.with_tag(bottle_tag) do @@ -2789,9 +2789,11 @@ class Formula end end - sig { returns(T.nilable(T::Boolean)) } - def on_system_blocks_exist? - self.class.on_system_blocks_exist? || @on_system_blocks_exist + # A `UsesOnSystem` object that contains boolean instance variables indicating + # whether the formula uses specific on_system methods. + sig { returns(OnSystem::UsesOnSystem) } + def uses_on_system + self.class.uses_on_system || @uses_on_system end sig { @@ -3331,7 +3333,7 @@ class Formula @skip_clean_paths = T.let(Set.new, T.nilable(T::Set[T.any(String, Symbol)])) @link_overwrite_paths = T.let(Set.new, T.nilable(T::Set[String])) @loaded_from_api = T.let(false, T.nilable(T::Boolean)) - @on_system_blocks_exist = T.let(false, T.nilable(T::Boolean)) + @uses_on_system = T.let(OnSystem::UsesOnSystem.new, T.nilable(OnSystem::UsesOnSystem)) @network_access_allowed = T.let(SUPPORTED_NETWORK_ACCESS_PHASES.to_h do |phase| [phase, DEFAULT_NETWORK_ACCESS_ALLOWED] end, T.nilable(T::Hash[Symbol, T::Boolean])) @@ -3345,6 +3347,7 @@ class Formula @conflicts.freeze @skip_clean_paths.freeze @link_overwrite_paths.freeze + @uses_on_system.freeze super end @@ -3355,10 +3358,10 @@ class Formula sig { returns(T::Boolean) } def loaded_from_api? = !!@loaded_from_api - # Whether this formula contains OS/arch-specific blocks - # (e.g. `on_macos`, `on_arm`, `on_monterey :or_older`, `on_system :linux, macos: :big_sur_or_newer`). - sig { returns(T::Boolean) } - def on_system_blocks_exist? = !!@on_system_blocks_exist + # A `UsesOnSystem` object that contains boolean instance variables + # indicating whether the formula uses specific on_system methods. + sig { returns(T.nilable(OnSystem::UsesOnSystem)) } + attr_reader :uses_on_system # The reason for why this software is not linked (by default) to {::HOMEBREW_PREFIX}. sig { returns(T.nilable(KegOnlyReason)) } diff --git a/Library/Homebrew/readall.rb b/Library/Homebrew/readall.rb index 36ae737fcf..5d2c2ae5be 100644 --- a/Library/Homebrew/readall.rb +++ b/Library/Homebrew/readall.rb @@ -66,7 +66,7 @@ module Readall readall_formula = readall_formula_class.new(formula_name, file, :stable, tap:) readall_formula.to_hash # TODO: Remove check for MACOS_MODULE_REGEX once the `MacOS` module is undefined on Linux - cache[:valid_formulae][file] = if readall_formula.on_system_blocks_exist? || + cache[:valid_formulae][file] = if readall_formula.uses_on_system.present? || formula_contents.match?(MACOS_MODULE_REGEX) [bottle_tag, *cache[:valid_formulae][file]] else diff --git a/Library/Homebrew/sorbet/rbi/dsl/cask/cask.rbi b/Library/Homebrew/sorbet/rbi/dsl/cask/cask.rbi index 1ea511aa2e..6f73b6ca5e 100644 --- a/Library/Homebrew/sorbet/rbi/dsl/cask/cask.rbi +++ b/Library/Homebrew/sorbet/rbi/dsl/cask/cask.rbi @@ -153,9 +153,6 @@ class Cask::Cask sig { params(args: T.untyped, block: T.untyped).returns(T.nilable(MacOSVersion)) } def on_system_block_min_os(*args, &block); end - sig { params(args: T.untyped, block: T.untyped).returns(T::Boolean) } - def on_system_blocks_exist?(*args, &block); end - sig { params(args: T.untyped, block: T.untyped).returns(T.untyped) } def os(*args, &block); end @@ -204,6 +201,9 @@ class Cask::Cask sig { params(args: T.untyped, block: T.untyped).returns(T.nilable(::Cask::URL)) } def url(*args, &block); end + sig { params(args: T.untyped, block: T.untyped).returns(T.untyped) } + def uses_on_system(*args, &block); end + sig { params(args: T.untyped, block: T.untyped).returns(T.untyped) } def version(*args, &block); end diff --git a/Library/Homebrew/test/cask/dsl_spec.rb b/Library/Homebrew/test/cask/dsl_spec.rb index c9b75cf482..0895cbdfb2 100644 --- a/Library/Homebrew/test/cask/dsl_spec.rb +++ b/Library/Homebrew/test/cask/dsl_spec.rb @@ -141,6 +141,10 @@ RSpec.describe Cask::DSL, :cask do it "stores only the arm checksum" do expect(cask.sha256).to eq("imasha2arm") end + + it "sets @uses_on_system.arm to true" do + expect(cask.uses_on_system.arm?).to be true + end end context "when running on intel" do @@ -151,6 +155,86 @@ RSpec.describe Cask::DSL, :cask do it "stores only the intel checksum" do expect(cask.sha256).to eq("imasha2intel") end + + it "sets @uses_on_system.intel to true" do + expect(cask.uses_on_system.intel?).to be true + end + end + end + + context "with an arm64_linux checksum" do + let(:cask_arm_linux) do + Homebrew::SimulateSystem.with os: :linux, arch: :arm do + Cask::Cask.new("arm64_linux-checksum-cask") do + sha256 arm64_linux: "imasha2armlinux" + end + end + end + + before do + allow(Hardware::CPU).to receive(:type).and_return(:arm) + end + + it "stores only the intel checksum" do + expect(cask_arm_linux.sha256).to eq("imasha2armlinux") + end + + it "sets @uses_on_system.arm to true" do + expect(cask_arm_linux.uses_on_system.arm?).to be true + end + + it "sets @uses_on_system.linux to true" do + expect(cask_arm_linux.uses_on_system.linux?).to be true + end + end + + context "with an x86_64_linux checksum" do + let(:cask_intel_linux) do + Homebrew::SimulateSystem.with os: :linux, arch: :intel do + Cask::Cask.new("x86_64_linux-checksum-cask") do + sha256 x86_64_linux: "imasha2intellinux" + end + end + end + + before do + allow(Hardware::CPU).to receive(:type).and_return(:intel) + end + + it "stores only the intel checksum" do + expect(cask_intel_linux.sha256).to eq("imasha2intellinux") + end + + it "sets @uses_on_system.intel to true" do + expect(cask_intel_linux.uses_on_system.intel?).to be true + end + + it "sets @uses_on_system.linux to true" do + expect(cask_intel_linux.uses_on_system.linux?).to be true + end + end + + context "with a :no_check checksum" do + let(:cask_no_check) do + Cask::Cask.new("no_check-checksum-cask") do + sha256 :no_check + end + end + + it "stores the :no_check symbol" do + expect(cask_no_check.sha256).to eq(:no_check) + end + end + + context "with an invalid checksum value" do + let(:cask_invalid_checksum) do + Cask::Cask.new("invalid-checksum-cask") do + sha256 :invalid_symbol + end + end + + it "refuses to load" do + expect { cask_invalid_checksum }.to raise_error(Cask::CaskInvalidError) end end end @@ -369,6 +453,10 @@ RSpec.describe Cask::DSL, :cask do it "returns the value" do expect(cask.url.to_s).to eq "file://#{TEST_FIXTURE_DIR}/cask/caffeine-arm.zip" end + + it "sets uses_on_system.arm to true" do + expect(cask.uses_on_system.arm?).to be true + end end context "when running on intel" do @@ -381,6 +469,104 @@ RSpec.describe Cask::DSL, :cask do end end end + + context "when no arm value is specified" do + let(:token) { "arch-intel-only" } + + context "when running on intel" do + before do + allow(Hardware::CPU).to receive(:type).and_return(:intel) + end + + it "returns the value" do + expect(cask.url.to_s).to eq "file://#{TEST_FIXTURE_DIR}/cask/caffeine-intel.zip" + end + + it "sets uses_on_system.intel to true" do + expect(cask.uses_on_system.intel?).to be true + end + end + + context "when running on arm" do + before do + allow(Hardware::CPU).to receive(:type).and_return(:arm) + end + + it "defaults to `nil` for the other when no arrays are passed" do + expect(cask.url.to_s).to eq "file://#{TEST_FIXTURE_DIR}/cask/caffeine.zip" + end + end + end + end + + describe "os stanza" do + context "when os is called more than once" do + let(:cask_multiple_os_calls) { Cask::CaskLoader.load(cask_path("invalid/invalid-two-os")) } + + it "prevents defining multiple oss" do + expect { cask_multiple_os_calls }.to raise_error(Cask::CaskInvalidError, /'os' stanza may only appear once/) + end + end + + context "when only a macos value is specified" do + context "when running on macos" do + let(:cask_os_macos_only) do + Homebrew::SimulateSystem.with(os: :sequoia) do + Cask::CaskLoader.load(cask_path("os-macos-only")) + end + end + + it "returns the value" do + expect(cask_os_macos_only.url.to_s).to eq "file://#{TEST_FIXTURE_DIR}/cask/caffeine-darwin.zip" + end + + it "sets uses_on_system.macos to true" do + expect(cask_os_macos_only.uses_on_system.macos?).to be true + end + end + + context "when running on linux" do + let(:cask_os_macos_only) do + Homebrew::SimulateSystem.with(os: :linux) do + Cask::CaskLoader.load(cask_path("os-macos-only")) + end + end + + it "defaults to `nil`" do + expect(cask_os_macos_only.url.to_s).to eq "file://#{TEST_FIXTURE_DIR}/cask/caffeine.zip" + end + end + end + + context "when only a linux value is specified" do + context "when running on linux" do + let(:cask_os_linux_only) do + Homebrew::SimulateSystem.with(os: :linux) do + Cask::CaskLoader.load(cask_path("os-linux-only")) + end + end + + it "returns the value" do + expect(cask_os_linux_only.url.to_s).to eq "file://#{TEST_FIXTURE_DIR}/cask/caffeine-linux.zip" + end + + it "sets uses_on_system.linux to true" do + expect(cask_os_linux_only.uses_on_system.linux?).to be true + end + end + + context "when running on macos" do + let(:cask_os_linux_only) do + Homebrew::SimulateSystem.with(os: :sequoia) do + Cask::CaskLoader.load(cask_path("os-linux-only")) + end + end + + it "defaults to `nil`" do + expect(cask_os_linux_only.url.to_s).to eq "file://#{TEST_FIXTURE_DIR}/cask/caffeine.zip" + end + end + end end describe "depends_on stanza" do @@ -598,4 +784,112 @@ RSpec.describe Cask::DSL, :cask do ] end end + + describe "#uses_on_system" do + context "when cask uses on_arm" do + let(:token) { "with-on-arch-blocks" } + + it "sets @uses_on_system.arm to true" do + expect(cask.uses_on_system.arm?).to be true + end + end + + context "when cask uses on_intel" do + let(:token) { "with-on-arch-blocks" } + + it "sets @uses_on_system.intel to true" do + expect(cask.uses_on_system.intel?).to be true + end + end + + context "when cask uses on_arch_conditional" do + context "when arm argument is provided" do + let(:token) { "with-on-arch-conditional" } + + it "sets @uses_on_system.arm to true" do + expect(cask.uses_on_system.arm?).to be true + end + end + + context "when intel argument is provided" do + let(:token) { "with-on-arch-conditional" } + + it "sets @uses_on_system.intel to true" do + expect(cask.uses_on_system.intel?).to be true + end + end + + context "when no arguments are provided" do + let(:token) { "with-on-arch-conditional-no-args" } + + it "doesn't set @uses_on_system.arm or .intel to true" do + expect(cask.uses_on_system.arm?).to be false + expect(cask.uses_on_system.intel?).to be false + end + end + end + + context "when cask uses on_linux" do + let(:token) { "with-on-os-blocks" } + + it "sets @uses_on_system.linux to true" do + expect(cask.uses_on_system.linux?).to be true + end + end + + context "when cask uses on_macos" do + let(:token) { "with-on-os-blocks" } + + it "sets @uses_on_system.macos to true" do + expect(cask.uses_on_system.macos?).to be true + end + end + + context "when cask uses on_system" do + let(:token) { "with-on-system-blocks" } + + it "sets @uses_on_system.linux to true" do + expect(cask.uses_on_system.linux?).to be true + end + + it "sets @uses_on_system.macos to true" do + expect(cask.uses_on_system.macos?).to be true + end + end + + context "when cask uses on_system_conditional" do + context "when linux argument is provided" do + let(:token) { "with-on-system-conditional" } + + it "sets @uses_on_system.linux to true" do + expect(cask.uses_on_system.linux?).to be true + end + end + + context "when macos argument is provided" do + let(:token) { "with-on-system-conditional" } + + it "sets @uses_on_system.macos to true" do + expect(cask.uses_on_system.macos?).to be true + end + end + + context "when no arguments are provided" do + let(:token) { "with-on-system-conditional-no-args" } + + it "doesn't set @uses_on_system.linux or .macos to true" do + expect(cask.uses_on_system.linux?).to be false + expect(cask.uses_on_system.macos?).to be false + end + end + end + + context "when cask uses on_* macos version methods" do + let(:token) { "with-on-macos-version-blocks" } + + it "sets @uses_on_system.macos to true" do + expect(cask.uses_on_system.macos?).to be true + end + end + end end diff --git a/Library/Homebrew/test/extend/on_system_spec.rb b/Library/Homebrew/test/extend/on_system_spec.rb index 605c37f0d8..84fc72c006 100644 --- a/Library/Homebrew/test/extend/on_system_spec.rb +++ b/Library/Homebrew/test/extend/on_system_spec.rb @@ -27,6 +27,31 @@ RSpec.describe OnSystem do end end + describe "UsesOnSystem" do + uses_on_system_empty = described_class::UsesOnSystem.new + uses_on_system_present = described_class::UsesOnSystem.new(arm: true) + + describe "#empty?" do + it "returns true if all properties are default values" do + expect(uses_on_system_empty.empty?).to be true + end + + it "returns false if any properties have a non-default value" do + expect(uses_on_system_present.empty?).to be false + end + end + + describe "#present?" do + it "returns true if object is not empty" do + expect(uses_on_system_present.present?).to be true + end + + it "returns false if object is empty" do + expect(uses_on_system_empty.present?).to be false + end + end + end + describe "::arch_condition_met?" do it "returns true if current arch equals provided arch" do Homebrew::SimulateSystem.with(arch: :arm) do diff --git a/Library/Homebrew/test/formula_spec.rb b/Library/Homebrew/test/formula_spec.rb index ada1618966..f9d2aa28ab 100644 --- a/Library/Homebrew/test/formula_spec.rb +++ b/Library/Homebrew/test/formula_spec.rb @@ -1951,6 +1951,189 @@ RSpec.describe Formula do end end + describe "#uses_on_system" do + # These formula definitions use a different way of creating the formula, + # as the `Class.new` approach doesn't seem to work as expected for + # `uses_on_system`. + context "when formula uses on_arm" do + let(:f_on_arm) do + formula("on-arm") do + on_arm do + url "https://brew.sh/foo-1.0-arm.tar.gz" + end + + url "https://brew.sh/foo-1.0.tar.gz" + end + end + + it "sets @uses_on_system.arm to true" do + expect(f_on_arm.uses_on_system.arm?).to be true + end + end + + context "when formula uses on_intel" do + let(:f_on_intel) do + formula("on-intel") do + on_intel do + url "https://brew.sh/foo-1.0-arm.tar.gz" + end + + url "https://brew.sh/foo-1.0.tar.gz" + end + end + + it "sets @uses_on_system.intel to true" do + expect(f_on_intel.uses_on_system.intel?).to be true + end + end + + context "when formula uses on_arch_conditional" do + let(:f_on_arch_conditional) do + formula("on-arch-conditional") do + folder = on_arch_conditional arm: "arm/", intel: "intel/" + + url "https://brew.sh/#{folder}foo-1.0.tar.gz" + end + end + let(:f_on_arch_conditional_no_args) do + formula("on-arch-conditional-no-args") do + folder = on_arch_conditional + + url "https://brew.sh/#{folder}foo-1.0.tar.gz" + end + end + + context "when arm argument is provided" do + it "sets @uses_on_system.arm to true" do + expect(f_on_arch_conditional.uses_on_system.arm?).to be true + end + end + + context "when intel argument is provided" do + it "sets @uses_on_system.intel to true" do + expect(f_on_arch_conditional.uses_on_system.intel?).to be true + end + end + + context "when no arguments are provided" do + it "doesn't set @uses_on_system.arm or .intel to true" do + expect(f_on_arch_conditional_no_args.uses_on_system.arm?).to be false + expect(f_on_arch_conditional_no_args.uses_on_system.intel?).to be false + end + end + end + + context "when formula uses on_linux" do + let(:f_on_linux) do + formula("on-linux") do + on_linux do + url "https://brew.sh/foo-1.0-linux.tar.gz" + end + + url "https://brew.sh/foo-1.0.tar.gz" + end + end + + it "sets @uses_on_system.linux to true" do + expect(f_on_linux.uses_on_system.linux?).to be true + end + end + + context "when formula uses on_macos" do + let(:f_on_macos) do + formula("on-macos") do + on_macos do + url "https://brew.sh/foo-1.0-macos.tar.gz" + end + + url "https://brew.sh/foo-1.0.tar.gz" + end + end + + it "sets @uses_on_system.macos to true" do + expect(f_on_macos.uses_on_system.macos?).to be true + end + end + + context "when formula uses on_system" do + let(:f_on_system) do + formula("on-system") do + on_system :linux, macos: :sequoia_or_newer do + url "https://brew.sh/foo-1.0-new.tar.gz" + end + + url "https://brew.sh/foo-1.0.tar.gz" + end + end + + it "sets @uses_on_system.linux to true" do + expect(f_on_system.uses_on_system.linux?).to be true + end + + it "sets @uses_on_system.macos to true" do + expect(f_on_system.uses_on_system.macos?).to be true + end + end + + context "when formula uses on_system_conditional" do + let(:f_on_system_conditional) do + formula("on-system-conditional") do + folder = on_system_conditional linux: "linux/", macos: "macos/" + + url "https://brew.sh/#{folder}foo-1.0.tar.gz" + end + end + let(:f_on_system_conditional_no_args) do + formula("on-system-conditional-no-args") do + folder = on_system_conditional + + url "https://brew.sh/#{folder}foo-1.0.tar.gz" + end + end + + context "when linux argument is provided" do + it "sets @uses_on_system.linux to true" do + expect(f_on_system_conditional.uses_on_system.linux?).to be true + end + end + + context "when macos argument is provided" do + it "sets @uses_on_system.macos to true" do + expect(f_on_system_conditional.uses_on_system.macos?).to be true + end + end + + context "when no arguments are provided" do + it "doesn't set @uses_on_system.linux or .macos to true" do + expect(f_on_system_conditional_no_args.uses_on_system.linux?).to be false + expect(f_on_system_conditional_no_args.uses_on_system.macos?).to be false + end + end + end + + context "when formula uses on_* macos version methods" do + let(:f_on_macos_versions) do + formula("on-macos-versions") do + url "https://brew.sh/foo-1.0.tar.gz" + + on_big_sur :or_older do + depends_on "abc" + end + on_monterey do + depends_on "def" + end + on_ventura :or_newer do + depends_on "ghi" + end + end + end + + it "sets @uses_on_system.macos to true" do + expect(f_on_macos_versions.uses_on_system.macos?).to be true + end + end + end + describe "#network_access_allowed?" do it "throws an error when passed an invalid symbol" do f = Testball.new diff --git a/Library/Homebrew/test/support/fixtures/cask/Casks/arch-intel-only.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/arch-intel-only.rb new file mode 100644 index 0000000000..477c6fea25 --- /dev/null +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/arch-intel-only.rb @@ -0,0 +1,11 @@ +cask "arch-intel-only" do + arch intel: "-intel" + + version "1.2.3" + sha256 "67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94" + + url "file://#{TEST_FIXTURE_DIR}/cask/caffeine#{arch}.zip" + homepage "https://brew.sh/" + + app "Caffeine.app" +end diff --git a/Library/Homebrew/test/support/fixtures/cask/Casks/invalid/invalid-two-os.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/invalid/invalid-two-os.rb new file mode 100644 index 0000000000..bd83bab1dc --- /dev/null +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/invalid/invalid-two-os.rb @@ -0,0 +1,12 @@ +cask "invalid-two-os" do + os linux: "linux", macos: "darwin" + os linux: "linux2", macos: "darwin2" + + version "1.2.3" + sha256 "67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94" + + url "file://#{TEST_FIXTURE_DIR}/cask/caffeine.zip" + homepage "https://brew.sh/" + + app "Caffeine.app" +end diff --git a/Library/Homebrew/test/support/fixtures/cask/Casks/os-linux-only.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/os-linux-only.rb new file mode 100644 index 0000000000..ad03208574 --- /dev/null +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/os-linux-only.rb @@ -0,0 +1,11 @@ +cask "os-linux-only" do + os linux: "-linux" + + version "1.2.3" + sha256 "67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94" + + url "file://#{TEST_FIXTURE_DIR}/cask/caffeine#{os}.zip" + homepage "https://brew.sh/" + + app "Caffeine.app" +end diff --git a/Library/Homebrew/test/support/fixtures/cask/Casks/os-macos-only.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/os-macos-only.rb new file mode 100644 index 0000000000..1dccf7ae6f --- /dev/null +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/os-macos-only.rb @@ -0,0 +1,11 @@ +cask "os-macos-only" do + os macos: "-darwin" + + version "1.2.3" + sha256 "67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94" + + url "file://#{TEST_FIXTURE_DIR}/cask/caffeine#{os}.zip" + homepage "https://brew.sh/" + + app "Caffeine.app" +end diff --git a/Library/Homebrew/test/support/fixtures/cask/Casks/with-on-arch-blocks.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-on-arch-blocks.rb new file mode 100644 index 0000000000..6017046dfd --- /dev/null +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-on-arch-blocks.rb @@ -0,0 +1,15 @@ +cask "with-on-arch-blocks" do + on_arm do + version "1.2.4" + sha256 "67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94" + end + on_intel do + version "1.2.3" + sha256 "8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b" + end + + url "https://brew.sh/TestCask-#{version}.dmg" + homepage "https://brew.sh/" + + app "TestCask.app" +end diff --git a/Library/Homebrew/test/support/fixtures/cask/Casks/with-on-arch-conditional-no-args.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-on-arch-conditional-no-args.rb new file mode 100644 index 0000000000..8451837397 --- /dev/null +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-on-arch-conditional-no-args.rb @@ -0,0 +1,8 @@ +cask "with-on-arch-conditional-no-args" do + folder = on_arch_conditional + + url "https://brew.sh/#{folder}TestCask-#{version}.dmg" + homepage "https://brew.sh/" + + app "TestCask.app" +end diff --git a/Library/Homebrew/test/support/fixtures/cask/Casks/with-on-arch-conditional.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-on-arch-conditional.rb new file mode 100644 index 0000000000..935c92e4b8 --- /dev/null +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-on-arch-conditional.rb @@ -0,0 +1,8 @@ +cask "with-on-arch-conditional" do + folder = on_arch_conditional arm: "arm-dir/", intel: "intel-dir/" + + url "https://brew.sh/#{folder}TestCask-#{version}.dmg" + homepage "https://brew.sh/" + + app "TestCask.app" +end diff --git a/Library/Homebrew/test/support/fixtures/cask/Casks/with-on-macos-version-blocks.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-on-macos-version-blocks.rb new file mode 100644 index 0000000000..5a56046897 --- /dev/null +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-on-macos-version-blocks.rb @@ -0,0 +1,19 @@ +cask "with-on-macos-version-blocks" do + on_big_sur :or_older do + version "1.2.3" + sha256 "8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b" + end + on_monterey do + version "1.2.4" + sha256 "67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94" + end + on_ventura :or_newer do + version "1.2.5" + sha256 "306c6ca7407560340797866e077e053627ad409277d1b9da58106fce4cf717cb" + end + + url "https://brew.sh/TestCask-#{version}.dmg" + homepage "https://brew.sh/" + + app "TestCask.app" +end diff --git a/Library/Homebrew/test/support/fixtures/cask/Casks/with-on-os-blocks.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-on-os-blocks.rb new file mode 100644 index 0000000000..68915e1a86 --- /dev/null +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-on-os-blocks.rb @@ -0,0 +1,15 @@ +cask "with-on-os-blocks" do + on_linux do + version "1.2.3" + sha256 "8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b" + end + on_macos do + version "1.2.4" + sha256 "67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94" + end + + url "https://brew.sh/TestCask-#{version}.zip" + homepage "https://brew.sh/" + + binary "testcask" +end diff --git a/Library/Homebrew/test/support/fixtures/cask/Casks/with-on-system-blocks.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-on-system-blocks.rb new file mode 100644 index 0000000000..e47885dbc9 --- /dev/null +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-on-system-blocks.rb @@ -0,0 +1,11 @@ +cask "with-on-system-blocks" do + on_system :linux, macos: :sequoia_or_newer do + version "1.2.4" + sha256 "67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94" + end + + url "https://brew.sh/TestCask-#{version}.dmg" + homepage "https://brew.sh/" + + app "TestCask.app" +end diff --git a/Library/Homebrew/test/support/fixtures/cask/Casks/with-on-system-conditional-no-args.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-on-system-conditional-no-args.rb new file mode 100644 index 0000000000..1e4bf32f4c --- /dev/null +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-on-system-conditional-no-args.rb @@ -0,0 +1,8 @@ +cask "with-on-system-conditional-no-args" do + folder = on_system_conditional + + url "https://brew.sh/#{folder}TestCask-#{version}.dmg" + homepage "https://brew.sh/" + + app "TestCask.app" +end diff --git a/Library/Homebrew/test/support/fixtures/cask/Casks/with-on-system-conditional.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-on-system-conditional.rb new file mode 100644 index 0000000000..3dae56528d --- /dev/null +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-on-system-conditional.rb @@ -0,0 +1,8 @@ +cask "with-on-system-conditional" do + folder = on_system_conditional linux: "linux-dir/", macos: "macos-dir/" + + url "https://brew.sh/#{folder}TestCask-#{version}.dmg" + homepage "https://brew.sh/" + + app "TestCask.app" +end