Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sorbet: Make more files (that have public APIs defined in them) typed: strict #17636

Merged
merged 10 commits into from
Jul 12, 2024
50 changes: 26 additions & 24 deletions Library/Homebrew/development_tools.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# typed: true
# typed: strict
# frozen_string_literal: true

require "version"
Expand All @@ -16,7 +16,7 @@ def locate(tool)
# Don't call tools (cc, make, strip, etc.) directly!
# Give the name of the binary you look for as a string to this method
# in order to get the full path back as a Pathname.
(@locate ||= {}).fetch(tool) do |key|
(@locate ||= T.let({}, T.nilable(T::Hash[T.any(String, Symbol), T.untyped]))).fetch(tool) do |key|
@locate[key] = if File.executable?((path = "/usr/bin/#{tool}"))
MikeMcQuaid marked this conversation as resolved.
Show resolved Hide resolved
Pathname.new path
# Homebrew GCCs most frequently; much faster to check this before xcrun
Expand Down Expand Up @@ -62,55 +62,57 @@ def default_compiler
# @api public
sig { returns(Version) }
def clang_version
@clang_version ||= if (path = locate("clang")) &&
(build_version = `#{path} --version`[/(?:clang|LLVM) version (\d+\.\d(?:\.\d)?)/, 1])
Version.new build_version
else
Version::NULL
end
@clang_version ||= T.let(
if (path = locate("clang")) &&
(build_version = `#{path} --version`[/(?:clang|LLVM) version (\d+\.\d(?:\.\d)?)/, 1])
Version.new(build_version)
else
Version::NULL
end, T.nilable(Version)
)
end

# Get the Clang build version.
#
# @api public
sig { returns(Version) }
def clang_build_version
@clang_build_version ||= if (path = locate("clang")) &&
(build_version = `#{path} --version`[
%r{clang(-| version [^ ]+ \(tags/RELEASE_)(\d{2,})}, 2])
Version.new build_version
else
Version::NULL
end
@clang_build_version ||= T.let(
if (path = locate("clang")) &&
(build_version = `#{path} --version`[%r{clang(-| version [^ ]+ \(tags/RELEASE_)(\d{2,})}, 2])
Version.new(build_version)
else
Version::NULL
end, T.nilable(Version)
)
end

# Get the LLVM Clang build version.
#
# @api public
sig { returns(Version) }
def llvm_clang_build_version
@llvm_clang_build_version ||= begin
@llvm_clang_build_version ||= T.let(begin
path = Formulary.factory("llvm").opt_prefix/"bin/clang"
if path.executable? &&
(build_version = `#{path} --version`[/clang version (\d+\.\d\.\d)/, 1])
Version.new build_version
if path.executable? && (build_version = `#{path} --version`[/clang version (\d+\.\d\.\d)/, 1])
Version.new(build_version)
else
Version::NULL
end
end
end, T.nilable(Version))
end

# Get the GCC version.
#
# @api internal
sig { params(cc: String).returns(Version) }
def gcc_version(cc)
(@gcc_version ||= {}).fetch(cc) do
(@gcc_version ||= T.let({}, T.nilable(T::Hash[String, Version]))).fetch(cc) do
path = HOMEBREW_PREFIX/"opt/#{CompilerSelector.preferred_gcc}/bin"/cc
path = locate(cc) unless path.exist?
version = if path &&
(build_version = `#{path} --version`[/gcc(?:(?:-\d+(?:\.\d)?)? \(.+\))? (\d+\.\d\.\d)/, 1])
Version.new build_version
Version.new(build_version)
else
Version::NULL
end
Expand All @@ -120,8 +122,8 @@ def gcc_version(cc)

sig { void }
def clear_version_cache
@clang_version = @clang_build_version = nil
@gcc_version = {}
@clang_version = @clang_build_version = T.let(nil, T.nilable(Version))
@gcc_version = T.let({}, T.nilable(T::Hash[String, Version]))
end

sig { returns(T::Boolean) }
Expand Down
8 changes: 6 additions & 2 deletions Library/Homebrew/formula_assertions.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# typed: true
# typed: strict
# frozen_string_literal: true

module Homebrew
Expand All @@ -10,15 +10,18 @@ module Assertions
require "minitest/assertions"
include ::Minitest::Assertions

sig { params(assertions: Integer).returns(Integer) }
attr_writer :assertions

sig { returns(Integer) }
def assertions
@assertions ||= 0
@assertions ||= T.let(0, T.nilable(Integer))
end

# Returns the output of running cmd and asserts the exit status.
#
# @api public
sig { params(cmd: String, result: Integer).returns(String) }
def shell_output(cmd, result = 0)
ohai cmd
output = `#{cmd}`
Expand All @@ -33,6 +36,7 @@ def shell_output(cmd, result = 0)
# optionally asserts the exit status.
#
# @api public
sig { params(cmd: String, input: T.nilable(String), result: T.nilable(Integer)).returns(String) }
def pipe_output(cmd, input = nil, result = nil)
ohai cmd
output = IO.popen(cmd, "w+") do |pipe|
Expand Down
75 changes: 57 additions & 18 deletions Library/Homebrew/unpack_strategy.rb
Original file line number Diff line number Diff line change
@@ -1,16 +1,35 @@
# typed: true
# typed: strict
# frozen_string_literal: true

require "system_command"

# Module containing all available strategies for unpacking archives.
module UnpackStrategy
extend T::Helpers

include SystemCommand::Mixin
abstract!

# FIXME: Enable cop again when https://github.com/sorbet/sorbet/issues/3532 is fixed.
# rubocop:disable Style/MutableConstant
UnpackStrategyType = T.type_alias { T.all(T::Class[UnpackStrategy], UnpackStrategy::ClassMethods) }
# rubocop:enable Style/MutableConstant

module ClassMethods
extend T::Helpers
abstract!

sig { abstract.returns(T::Array[String]) }
def extensions; end

sig { abstract.params(path: Pathname).returns(T::Boolean) }
def can_extract?(path); end
end

mixes_in_class_methods(ClassMethods)

sig { returns(T.nilable(T::Array[UnpackStrategyType])) }
def self.strategies
@strategies ||= [
@strategies ||= T.let([
Tar, # Needs to be before Bzip2/Gzip/Xz/Lzma/Zstd.
Pax,
Gzip,
Expand Down Expand Up @@ -43,10 +62,11 @@ def self.strategies
Sit,
Rar,
Lha,
].freeze
].freeze, T.nilable(T::Array[UnpackStrategyType]))
end
private_class_method :strategies

sig { params(type: Symbol).returns(T.nilable(UnpackStrategyType)) }
def self.from_type(type)
type = {
naked: :uncompressed,
Expand All @@ -61,23 +81,31 @@ def self.from_type(type)
end
end

sig { params(extension: String).returns(T.nilable(UnpackStrategyType)) }
def self.from_extension(extension)
strategies.sort_by { |s| s.extensions.map(&:length).max || 0 }
.reverse
.find { |s| s.extensions.any? { |ext| extension.end_with?(ext) } }
return unless strategies

strategies&.sort_by { |s| s.extensions.map(&:length).max || 0 }
&.reverse
&.find { |s| s.extensions.any? { |ext| extension.end_with?(ext) } }
end
issyl0 marked this conversation as resolved.
Show resolved Hide resolved

sig { params(path: Pathname).returns(T.nilable(UnpackStrategyType)) }
def self.from_magic(path)
strategies.find { |s| s.can_extract?(path) }
strategies&.find { |s| s.can_extract?(path) }
end

def self.detect(path, prioritize_extension: false, type: nil, ref_type: nil, ref: nil, merge_xattrs: nil)
sig {
params(path: Pathname, prioritize_extension: T::Boolean, type: T.nilable(Symbol), ref_type: T.nilable(String),
ref: T.nilable(String), merge_xattrs: T::Boolean).returns(T.untyped)
}
def self.detect(path, prioritize_extension: false, type: nil, ref_type: nil, ref: nil, merge_xattrs: false)
strategy = from_type(type) if type

if prioritize_extension && path.extname.present?
strategy ||= from_extension(path.extname)
strategy ||= strategies.select { |s| s < Directory || s == Fossil }
.find { |s| s.can_extract?(path) }

strategy ||= strategies&.find { |s| (s < Directory || s == Fossil) && s.can_extract?(path) }
else
strategy ||= from_magic(path)
strategy ||= from_extension(path.extname)
Expand All @@ -88,24 +116,31 @@ def self.detect(path, prioritize_extension: false, type: nil, ref_type: nil, ref
strategy.new(path, ref_type:, ref:, merge_xattrs:)
end

attr_reader :path, :merge_xattrs
sig { returns(Pathname) }
attr_reader :path

def initialize(path, ref_type: nil, ref: nil, merge_xattrs: nil)
@path = Pathname(path).expand_path
sig { returns(T::Boolean) }
attr_reader :merge_xattrs

sig {
params(path: T.any(String, Pathname), ref_type: T.nilable(String), ref: T.nilable(String),
merge_xattrs: T::Boolean).void
}
def initialize(path, ref_type: nil, ref: nil, merge_xattrs: false)
@path = T.let(Pathname(path).expand_path, Pathname)
@ref_type = ref_type
@ref = ref
@merge_xattrs = merge_xattrs
end

abstract!
sig { abstract.params(unpack_dir: Pathname, basename: Pathname, verbose: T::Boolean).returns(T.untyped) }
sig { abstract.params(unpack_dir: Pathname, basename: Pathname, verbose: T::Boolean).void }
def extract_to_dir(unpack_dir, basename:, verbose:); end
issyl0 marked this conversation as resolved.
Show resolved Hide resolved
private :extract_to_dir

sig {
params(
to: T.nilable(Pathname), basename: T.nilable(T.any(String, Pathname)), verbose: T::Boolean,
).returns(T.untyped)
).void
}
def extract(to: nil, basename: nil, verbose: false)
basename ||= path.basename
Expand All @@ -131,7 +166,10 @@ def extract_nestedly(to: nil, basename: nil, verbose: false, prioritize_extensio
children = tmp_unpack_dir.children

if children.size == 1 && !children.fetch(0).directory?
s = UnpackStrategy.detect(children.first, prioritize_extension:)
first_child = children.first
next if first_child.nil?

s = UnpackStrategy.detect(first_child, prioritize_extension:)

s.extract_nestedly(to:, verbose:, prioritize_extension:)

Expand All @@ -149,6 +187,7 @@ def extract_nestedly(to: nil, basename: nil, verbose: false, prioritize_extensio
end
end

sig { returns(T::Array[String]) }
def dependencies
[]
end
Expand Down
2 changes: 1 addition & 1 deletion Library/Homebrew/unpack_strategy/air.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ module UnpackStrategy
class Air
include UnpackStrategy

sig { returns(T::Array[String]) }
sig { override.returns(T::Array[String]) }
def self.extensions
[".air"]
end
Expand Down
2 changes: 1 addition & 1 deletion Library/Homebrew/unpack_strategy/bzip2.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ module UnpackStrategy
class Bzip2
include UnpackStrategy

sig { returns(T::Array[String]) }
sig { override.returns(T::Array[String]) }
def self.extensions
[".bz2"]
end
Expand Down
2 changes: 1 addition & 1 deletion Library/Homebrew/unpack_strategy/cab.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ module UnpackStrategy
class Cab
include UnpackStrategy

sig { returns(T::Array[String]) }
sig { override.returns(T::Array[String]) }
def self.extensions
[".cab"]
end
Expand Down
2 changes: 1 addition & 1 deletion Library/Homebrew/unpack_strategy/compress.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
module UnpackStrategy
# Strategy for unpacking compress archives.
class Compress < Tar
sig { returns(T::Array[String]) }
sig { override.returns(T::Array[String]) }
def self.extensions
[".Z"]
end
Expand Down
2 changes: 1 addition & 1 deletion Library/Homebrew/unpack_strategy/directory.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ module UnpackStrategy
class Directory
include UnpackStrategy

sig { returns(T::Array[String]) }
sig { override.returns(T::Array[String]) }
def self.extensions
[]
end
Expand Down
8 changes: 7 additions & 1 deletion Library/Homebrew/unpack_strategy/dmg.rb
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,12 @@ def eject(verbose: false)
end
end

sig { override.returns(T::Array[String]) }
def self.extensions = []

sig { override.params(_path: Pathname).returns(T::Boolean) }
def self.can_extract?(_path) = false

private

sig { override.params(unpack_dir: Pathname, basename: Pathname, verbose: T::Boolean).returns(T.untyped) }
Expand Down Expand Up @@ -165,7 +171,7 @@ def extract_to_dir(unpack_dir, basename:, verbose:)
end
private_constant :Mount

sig { returns(T::Array[String]) }
sig { override.returns(T::Array[String]) }
def self.extensions
[".dmg"]
end
Expand Down
2 changes: 1 addition & 1 deletion Library/Homebrew/unpack_strategy/executable.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
module UnpackStrategy
# Strategy for unpacking executables.
class Executable < Uncompressed
sig { returns(T::Array[String]) }
sig { override.returns(T::Array[String]) }
def self.extensions
[".sh", ".bash"]
end
Expand Down
2 changes: 1 addition & 1 deletion Library/Homebrew/unpack_strategy/fossil.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class Fossil
include UnpackStrategy
extend SystemCommand::Mixin

sig { returns(T::Array[String]) }
sig { override.returns(T::Array[String]) }
def self.extensions
[]
end
Expand Down
2 changes: 1 addition & 1 deletion Library/Homebrew/unpack_strategy/generic_unar.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ module UnpackStrategy
class GenericUnar
include UnpackStrategy

sig { returns(T::Array[String]) }
sig { override.returns(T::Array[String]) }
def self.extensions
[]
end
Expand Down
2 changes: 1 addition & 1 deletion Library/Homebrew/unpack_strategy/gzip.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ module UnpackStrategy
class Gzip
include UnpackStrategy

sig { returns(T::Array[String]) }
sig { override.returns(T::Array[String]) }
def self.extensions
[".gz"]
end
Expand Down
2 changes: 1 addition & 1 deletion Library/Homebrew/unpack_strategy/jar.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
module UnpackStrategy
# Strategy for unpacking Java archives.
class Jar < Uncompressed
sig { returns(T::Array[String]) }
sig { override.returns(T::Array[String]) }
def self.extensions
[".apk", ".jar"]
end
Expand Down
Loading
Loading