From 431d8f1ff748228aab9407811bf70594f8c565e5 Mon Sep 17 00:00:00 2001 From: Rylan Polster Date: Sat, 21 Jun 2025 21:40:57 -0400 Subject: [PATCH] Consistently use `ClassMethods` sub-module for prepending class methods --- .../extend/os/linux/cask/quarantine.rb | 16 ++- .../extend/os/linux/development_tools.rb | 106 +++++++------- .../extend/os/linux/simulate_system.rb | 30 ++-- .../extend/os/mac/development_tools.rb | 134 +++++++++--------- .../Homebrew/extend/os/mac/hardware/cpu.rb | 76 +++++----- Library/Homebrew/extend/os/mac/readall.rb | 62 ++++---- .../Homebrew/extend/os/mac/simulate_system.rb | 20 +-- .../Homebrew/extend/os/mac/utils/socket.rb | 28 ++-- 8 files changed, 244 insertions(+), 228 deletions(-) diff --git a/Library/Homebrew/extend/os/linux/cask/quarantine.rb b/Library/Homebrew/extend/os/linux/cask/quarantine.rb index 0fb015f07e..5adcbd2eec 100644 --- a/Library/Homebrew/extend/os/linux/cask/quarantine.rb +++ b/Library/Homebrew/extend/os/linux/cask/quarantine.rb @@ -5,18 +5,20 @@ module OS module Linux module Cask module Quarantine - extend T::Helpers + module ClassMethods + extend T::Helpers - requires_ancestor { ::Cask::Quarantine } + requires_ancestor { ::Cask::Quarantine } - sig { returns(Symbol) } - def check_quarantine_support = :linux + sig { returns(Symbol) } + def check_quarantine_support = :linux - sig { returns(T::Boolean) } - def available? = false + sig { returns(T::Boolean) } + def available? = false + end end end end end -Cask::Quarantine.singleton_class.prepend(OS::Linux::Cask::Quarantine) +Cask::Quarantine.singleton_class.prepend(OS::Linux::Cask::Quarantine::ClassMethods) diff --git a/Library/Homebrew/extend/os/linux/development_tools.rb b/Library/Homebrew/extend/os/linux/development_tools.rb index d725933391..1036d79d5e 100644 --- a/Library/Homebrew/extend/os/linux/development_tools.rb +++ b/Library/Homebrew/extend/os/linux/development_tools.rb @@ -4,69 +4,71 @@ module OS module Linux module DevelopmentTools - extend T::Helpers + module ClassMethods + extend T::Helpers - requires_ancestor { ::DevelopmentTools } + requires_ancestor { ::DevelopmentTools } - sig { params(tool: T.any(String, Symbol)).returns(T.nilable(Pathname)) } - def locate(tool) - @locate ||= T.let({}, T.nilable(T::Hash[T.any(String, Symbol), Pathname])) - @locate.fetch(tool) do |key| - @locate[key] = if ::DevelopmentTools.needs_build_formulae? && - (binutils_path = HOMEBREW_PREFIX/"opt/binutils/bin/#{tool}").executable? - binutils_path - elsif ::DevelopmentTools.needs_build_formulae? && - (glibc_path = HOMEBREW_PREFIX/"opt/glibc/bin/#{tool}").executable? - glibc_path - elsif (homebrew_path = HOMEBREW_PREFIX/"bin/#{tool}").executable? - homebrew_path - elsif File.executable?(system_path = "/usr/bin/#{tool}") - Pathname.new system_path + sig { params(tool: T.any(String, Symbol)).returns(T.nilable(Pathname)) } + def locate(tool) + @locate ||= T.let({}, T.nilable(T::Hash[T.any(String, Symbol), Pathname])) + @locate.fetch(tool) do |key| + @locate[key] = if ::DevelopmentTools.needs_build_formulae? && + (binutils_path = HOMEBREW_PREFIX/"opt/binutils/bin/#{tool}").executable? + binutils_path + elsif ::DevelopmentTools.needs_build_formulae? && + (glibc_path = HOMEBREW_PREFIX/"opt/glibc/bin/#{tool}").executable? + glibc_path + elsif (homebrew_path = HOMEBREW_PREFIX/"bin/#{tool}").executable? + homebrew_path + elsif File.executable?(system_path = "/usr/bin/#{tool}") + Pathname.new system_path + end end end - end - sig { returns(Symbol) } - def default_compiler = :gcc + sig { returns(Symbol) } + def default_compiler = :gcc - sig { returns(T::Boolean) } - def needs_libc_formula? - return @needs_libc_formula unless @needs_libc_formula.nil? + sig { returns(T::Boolean) } + def needs_libc_formula? + return @needs_libc_formula unless @needs_libc_formula.nil? - @needs_libc_formula = T.let(OS::Linux::Glibc.below_ci_version?, T.nilable(T::Boolean)) - @needs_libc_formula = !!@needs_libc_formula - end - - # Keep this method around for now to make it easier to add this functionality later. - # rubocop:disable Lint/UselessMethodDefinition - sig { returns(Pathname) } - def host_gcc_path - # TODO: override this if/when we to pick the GCC based on e.g. the Ubuntu version. - super - end - # rubocop:enable Lint/UselessMethodDefinition - - sig { returns(T::Boolean) } - def needs_compiler_formula? - return @needs_compiler_formula unless @needs_compiler_formula.nil? - - @needs_compiler_formula = T.let(nil, T.nilable(T::Boolean)) - @needs_compiler_formula = if host_gcc_path.exist? - ::DevelopmentTools.gcc_version(host_gcc_path.to_s) < OS::LINUX_GCC_CI_VERSION - else - true + @needs_libc_formula = T.let(OS::Linux::Glibc.below_ci_version?, T.nilable(T::Boolean)) + @needs_libc_formula = !!@needs_libc_formula end - end - sig { returns(T::Hash[String, T.nilable(String)]) } - def build_system_info - super.merge({ - "glibc_version" => OS::Linux::Glibc.version.to_s.presence, - "oldest_cpu_family" => ::Hardware.oldest_cpu.to_s, - }) + # Keep this method around for now to make it easier to add this functionality later. + # rubocop:disable Lint/UselessMethodDefinition + sig { returns(Pathname) } + def host_gcc_path + # TODO: override this if/when we to pick the GCC based on e.g. the Ubuntu version. + super + end + # rubocop:enable Lint/UselessMethodDefinition + + sig { returns(T::Boolean) } + def needs_compiler_formula? + return @needs_compiler_formula unless @needs_compiler_formula.nil? + + @needs_compiler_formula = T.let(nil, T.nilable(T::Boolean)) + @needs_compiler_formula = if host_gcc_path.exist? + ::DevelopmentTools.gcc_version(host_gcc_path.to_s) < OS::LINUX_GCC_CI_VERSION + else + true + end + end + + sig { returns(T::Hash[String, T.nilable(String)]) } + def build_system_info + super.merge({ + "glibc_version" => OS::Linux::Glibc.version.to_s.presence, + "oldest_cpu_family" => ::Hardware.oldest_cpu.to_s, + }) + end end end end end -DevelopmentTools.singleton_class.prepend(OS::Linux::DevelopmentTools) +DevelopmentTools.singleton_class.prepend(OS::Linux::DevelopmentTools::ClassMethods) diff --git a/Library/Homebrew/extend/os/linux/simulate_system.rb b/Library/Homebrew/extend/os/linux/simulate_system.rb index 248ee7e2a5..4e79bf7a2c 100644 --- a/Library/Homebrew/extend/os/linux/simulate_system.rb +++ b/Library/Homebrew/extend/os/linux/simulate_system.rb @@ -4,25 +4,27 @@ module OS module Linux module SimulateSystem - sig { returns(T.nilable(Symbol)) } - def os - @os ||= T.let(nil, T.nilable(Symbol)) - return :macos if @os.blank? && Homebrew::EnvConfig.simulate_macos_on_linux? + module ClassMethods + sig { returns(T.nilable(Symbol)) } + def os + @os ||= T.let(nil, T.nilable(Symbol)) + return :macos if @os.blank? && Homebrew::EnvConfig.simulate_macos_on_linux? - @os - end + @os + end - sig { returns(T::Boolean) } - def simulating_or_running_on_linux? - os.blank? || os == :linux - end + sig { returns(T::Boolean) } + def simulating_or_running_on_linux? + os.blank? || os == :linux + end - sig { returns(Symbol) } - def current_os - os || :linux + sig { returns(Symbol) } + def current_os + os || :linux + end end end end end -Homebrew::SimulateSystem.singleton_class.prepend(OS::Linux::SimulateSystem) +Homebrew::SimulateSystem.singleton_class.prepend(OS::Linux::SimulateSystem::ClassMethods) diff --git a/Library/Homebrew/extend/os/mac/development_tools.rb b/Library/Homebrew/extend/os/mac/development_tools.rb index 95b2b8ec48..3a87930135 100644 --- a/Library/Homebrew/extend/os/mac/development_tools.rb +++ b/Library/Homebrew/extend/os/mac/development_tools.rb @@ -6,86 +6,88 @@ require "os/mac/xcode" module OS module Mac module DevelopmentTools - extend T::Helpers + module ClassMethods + extend T::Helpers - requires_ancestor { ::DevelopmentTools } + requires_ancestor { ::DevelopmentTools } - sig { params(tool: T.any(String, Symbol)).returns(T.nilable(Pathname)) } - def locate(tool) - @locate ||= T.let({}, T.nilable(T::Hash[T.any(String, Symbol), Pathname])) - @locate.fetch(tool) do |key| - @locate[key] = if (located_tool = super(tool)) - located_tool - else - path = Utils.popen_read("/usr/bin/xcrun", "-no-cache", "-find", tool, err: :close).chomp - Pathname.new(path) if File.executable?(path) + sig { params(tool: T.any(String, Symbol)).returns(T.nilable(Pathname)) } + def locate(tool) + @locate ||= T.let({}, T.nilable(T::Hash[T.any(String, Symbol), Pathname])) + @locate.fetch(tool) do |key| + @locate[key] = if (located_tool = super(tool)) + located_tool + else + path = Utils.popen_read("/usr/bin/xcrun", "-no-cache", "-find", tool, err: :close).chomp + Pathname.new(path) if File.executable?(path) + end end end - end - # Checks if the user has any developer tools installed, either via Xcode - # or the CLT. Convenient for guarding against formula builds when building - # is impossible. - sig { returns(T::Boolean) } - def installed? - MacOS::Xcode.installed? || MacOS::CLT.installed? - end + # Checks if the user has any developer tools installed, either via Xcode + # or the CLT. Convenient for guarding against formula builds when building + # is impossible. + sig { returns(T::Boolean) } + def installed? + MacOS::Xcode.installed? || MacOS::CLT.installed? + end - sig { returns(Symbol) } - def default_compiler - :clang - end + sig { returns(Symbol) } + def default_compiler + :clang + end - sig { returns(Version) } - def ld64_version - @ld64_version ||= T.let(begin - json = Utils.popen_read("/usr/bin/ld", "-version_details") - if $CHILD_STATUS.success? - Version.parse(JSON.parse(json)["version"]) - else - Version::NULL - end - end, T.nilable(Version)) - end + sig { returns(Version) } + def ld64_version + @ld64_version ||= T.let(begin + json = Utils.popen_read("/usr/bin/ld", "-version_details") + if $CHILD_STATUS.success? + Version.parse(JSON.parse(json)["version"]) + else + Version::NULL + end + end, T.nilable(Version)) + end - sig { returns(T::Boolean) } - def curl_handles_most_https_certificates? - # The system Curl is too old for some modern HTTPS certificates on - # older macOS versions. - ENV["HOMEBREW_SYSTEM_CURL_TOO_OLD"].nil? - end + sig { returns(T::Boolean) } + def curl_handles_most_https_certificates? + # The system Curl is too old for some modern HTTPS certificates on + # older macOS versions. + ENV["HOMEBREW_SYSTEM_CURL_TOO_OLD"].nil? + end - sig { returns(T::Boolean) } - def subversion_handles_most_https_certificates? - # The system Subversion is too old for some HTTPS certificates on - # older macOS versions. - MacOS.version >= :sierra - end + sig { returns(T::Boolean) } + def subversion_handles_most_https_certificates? + # The system Subversion is too old for some HTTPS certificates on + # older macOS versions. + MacOS.version >= :sierra + end - sig { returns(String) } - def installation_instructions - MacOS::CLT.installation_instructions - end + sig { returns(String) } + def installation_instructions + MacOS::CLT.installation_instructions + end - sig { returns(String) } - def custom_installation_instructions - <<~EOS - Install GNU's GCC: - brew install gcc - EOS - end + sig { returns(String) } + def custom_installation_instructions + <<~EOS + Install GNU's GCC: + brew install gcc + EOS + end - sig { returns(T::Hash[String, T.nilable(String)]) } - def build_system_info - build_info = { - "xcode" => MacOS::Xcode.version.to_s.presence, - "clt" => MacOS::CLT.version.to_s.presence, - "preferred_perl" => MacOS.preferred_perl_version, - } - super.merge build_info + sig { returns(T::Hash[String, T.nilable(String)]) } + def build_system_info + build_info = { + "xcode" => MacOS::Xcode.version.to_s.presence, + "clt" => MacOS::CLT.version.to_s.presence, + "preferred_perl" => MacOS.preferred_perl_version, + } + super.merge build_info + end end end end end -DevelopmentTools.singleton_class.prepend(OS::Mac::DevelopmentTools) +DevelopmentTools.singleton_class.prepend(OS::Mac::DevelopmentTools::ClassMethods) diff --git a/Library/Homebrew/extend/os/mac/hardware/cpu.rb b/Library/Homebrew/extend/os/mac/hardware/cpu.rb index 05116e8d84..ce1b5bf9ae 100644 --- a/Library/Homebrew/extend/os/mac/hardware/cpu.rb +++ b/Library/Homebrew/extend/os/mac/hardware/cpu.rb @@ -7,56 +7,58 @@ module OS module Mac module Hardware module CPU - extend T::Helpers + module ClassMethods + extend T::Helpers - # These methods use info spewed out by sysctl. - # Look in for decoding info. - def type - case ::Hardware::CPU.sysctl_int("hw.cputype") - when MachO::Headers::CPU_TYPE_I386 - :intel - when MachO::Headers::CPU_TYPE_ARM64 - :arm - else - :dunno + # These methods use info spewed out by sysctl. + # Look in for decoding info. + def type + case ::Hardware::CPU.sysctl_int("hw.cputype") + when MachO::Headers::CPU_TYPE_I386 + :intel + when MachO::Headers::CPU_TYPE_ARM64 + :arm + else + :dunno + end end - end - def family - if ::Hardware::CPU.arm? - ::Hardware::CPU.arm_family - elsif ::Hardware::CPU.intel? - ::Hardware::CPU.intel_family - else - :dunno + def family + if ::Hardware::CPU.arm? + ::Hardware::CPU.arm_family + elsif ::Hardware::CPU.intel? + ::Hardware::CPU.intel_family + else + :dunno + end end - end - # True when running under an Intel-based shell via Rosetta 2 on an - # Apple Silicon Mac. This can be detected via seeing if there's a - # conflict between what `uname` reports and the underlying `sysctl` flags, - # since the `sysctl` flags don't change behaviour under Rosetta 2. - def in_rosetta2? - ::Hardware::CPU.sysctl_bool("sysctl.proc_translated") - end + # True when running under an Intel-based shell via Rosetta 2 on an + # Apple Silicon Mac. This can be detected via seeing if there's a + # conflict between what `uname` reports and the underlying `sysctl` flags, + # since the `sysctl` flags don't change behaviour under Rosetta 2. + def in_rosetta2? + ::Hardware::CPU.sysctl_bool("sysctl.proc_translated") + end - def features - @features ||= ::Hardware::CPU.sysctl_n( - "machdep.cpu.features", - "machdep.cpu.extfeatures", - "machdep.cpu.leaf7_features", - ).split.map { |s| s.downcase.to_sym } - end + def features + @features ||= ::Hardware::CPU.sysctl_n( + "machdep.cpu.features", + "machdep.cpu.extfeatures", + "machdep.cpu.leaf7_features", + ).split.map { |s| s.downcase.to_sym } + end - def sse4? - ::Hardware::CPU.sysctl_bool("hw.optional.sse4_1") + def sse4? + ::Hardware::CPU.sysctl_bool("hw.optional.sse4_1") + end end end end end end -Hardware::CPU.singleton_class.prepend(OS::Mac::Hardware::CPU) +Hardware::CPU.singleton_class.prepend(OS::Mac::Hardware::CPU::ClassMethods) module Hardware class CPU diff --git a/Library/Homebrew/extend/os/mac/readall.rb b/Library/Homebrew/extend/os/mac/readall.rb index 90e89c17d5..6d926a87f3 100644 --- a/Library/Homebrew/extend/os/mac/readall.rb +++ b/Library/Homebrew/extend/os/mac/readall.rb @@ -4,44 +4,46 @@ module OS module Mac module Readall - extend T::Helpers + module ClassMethods + extend T::Helpers - requires_ancestor { Kernel } + requires_ancestor { Kernel } - sig { params(tap: ::Tap, os_name: T.nilable(Symbol), arch: T.nilable(Symbol)).returns(T::Boolean) } - def valid_casks?(tap, os_name: nil, arch: ::Hardware::CPU.type) - return true if os_name == :linux + sig { params(tap: ::Tap, os_name: T.nilable(Symbol), arch: T.nilable(Symbol)).returns(T::Boolean) } + def valid_casks?(tap, os_name: nil, arch: ::Hardware::CPU.type) + return true if os_name == :linux - current_macos_version = if os_name.is_a?(Symbol) - MacOSVersion.from_symbol(os_name) - else - MacOS.version - end - - success = T.let(true, T::Boolean) - tap.cask_files.each do |file| - cask = ::Cask::CaskLoader.load(file) - - # Fine to have missing URLs for unsupported macOS - macos_req = cask.depends_on.macos - next if macos_req&.version && Array(macos_req.version).none? do |macos_version| - current_macos_version.compare(macos_req.comparator, macos_version) + current_macos_version = if os_name.is_a?(Symbol) + MacOSVersion.from_symbol(os_name) + else + MacOS.version end - raise "Missing URL" if cask.url.nil? - rescue Interrupt - raise - # Handle all possible exceptions reading Casks. - rescue Exception => e # rubocop:disable Lint/RescueException - os_and_arch = "macOS #{current_macos_version} on #{arch}" - onoe "Invalid cask (#{os_and_arch}): #{file}" - $stderr.puts e - success = false + success = T.let(true, T::Boolean) + tap.cask_files.each do |file| + cask = ::Cask::CaskLoader.load(file) + + # Fine to have missing URLs for unsupported macOS + macos_req = cask.depends_on.macos + next if macos_req&.version && Array(macos_req.version).none? do |macos_version| + current_macos_version.compare(macos_req.comparator, macos_version) + end + + raise "Missing URL" if cask.url.nil? + rescue Interrupt + raise + # Handle all possible exceptions reading Casks. + rescue Exception => e # rubocop:disable Lint/RescueException + os_and_arch = "macOS #{current_macos_version} on #{arch}" + onoe "Invalid cask (#{os_and_arch}): #{file}" + $stderr.puts e + success = false + end + success end - success end end end end -Readall.singleton_class.prepend(OS::Mac::Readall) +Readall.singleton_class.prepend(OS::Mac::Readall::ClassMethods) diff --git a/Library/Homebrew/extend/os/mac/simulate_system.rb b/Library/Homebrew/extend/os/mac/simulate_system.rb index a8e3329e19..3786d8f413 100644 --- a/Library/Homebrew/extend/os/mac/simulate_system.rb +++ b/Library/Homebrew/extend/os/mac/simulate_system.rb @@ -4,19 +4,21 @@ module OS module Mac module SimulateSystem - sig { returns(T::Boolean) } - def simulating_or_running_on_macos? - return true if Homebrew::SimulateSystem.os.blank? + module ClassMethods + sig { returns(T::Boolean) } + def simulating_or_running_on_macos? + return true if Homebrew::SimulateSystem.os.blank? - [:macos, *MacOSVersion::SYMBOLS.keys].include?(Homebrew::SimulateSystem.os) - end + [:macos, *MacOSVersion::SYMBOLS.keys].include?(Homebrew::SimulateSystem.os) + end - sig { returns(Symbol) } - def current_os - ::Homebrew::SimulateSystem.os || MacOS.version.to_sym + sig { returns(Symbol) } + def current_os + ::Homebrew::SimulateSystem.os || MacOS.version.to_sym + end end end end end -Homebrew::SimulateSystem.singleton_class.prepend(OS::Mac::SimulateSystem) +Homebrew::SimulateSystem.singleton_class.prepend(OS::Mac::SimulateSystem::ClassMethods) diff --git a/Library/Homebrew/extend/os/mac/utils/socket.rb b/Library/Homebrew/extend/os/mac/utils/socket.rb index 563a9b86d4..b9bb4265d2 100644 --- a/Library/Homebrew/extend/os/mac/utils/socket.rb +++ b/Library/Homebrew/extend/os/mac/utils/socket.rb @@ -7,24 +7,26 @@ module OS module Mac # Wrapper around UNIXSocket to allow > 104 characters on macOS. module UNIXSocketExt - extend T::Helpers + module ClassMethods + extend T::Helpers - requires_ancestor { Kernel } + requires_ancestor { Kernel } - sig { params(path: String).returns(String) } - def sockaddr_un(path) - if path.bytesize > 252 # largest size that can fit into a single-byte length - raise ArgumentError, "too long unix socket path (#{path.bytesize} bytes given but 252 bytes max)" + sig { params(path: String).returns(String) } + def sockaddr_un(path) + if path.bytesize > 252 # largest size that can fit into a single-byte length + raise ArgumentError, "too long unix socket path (#{path.bytesize} bytes given but 252 bytes max)" + end + + [ + path.bytesize + 3, # = length (1 byte) + family (1 byte) + path (variable) + null terminator (1 byte) + 1, # AF_UNIX + path, + ].pack("CCZ*") end - - [ - path.bytesize + 3, # = length (1 byte) + family (1 byte) + path (variable) + null terminator (1 byte) - 1, # AF_UNIX - path, - ].pack("CCZ*") end end end end -Utils::UNIXSocketExt.singleton_class.prepend(OS::Mac::UNIXSocketExt) +Utils::UNIXSocketExt.singleton_class.prepend(OS::Mac::UNIXSocketExt::ClassMethods)