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
52 changes: 26 additions & 26 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.untyped, T.untyped]))).fetch(tool) do |key|
@locate[key] = if File.executable?((path = "/usr/bin/#{tool}"))
issyl0 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,55 @@ 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")) && (bv = `#{path} --version`[/(?:clang|LLVM) version (\d+\.\d(?:\.\d)?)/, 1])
Version.new(bv)
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? && (bv = `#{path} --version`[/clang version (\d+\.\d\.\d)/, 1])
Version.new(bv)
issyl0 marked this conversation as resolved.
Show resolved Hide resolved
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 = if path && (bv = `#{path} --version`[/gcc(?:(?:-\d+(?:\.\d)?)? \(.+\))? (\d+\.\d\.\d)/, 1])
Version.new(bv)
else
Version::NULL
end
Expand All @@ -120,8 +120,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
84 changes: 70 additions & 14 deletions Library/Homebrew/unpack_strategy.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# typed: true
# typed: strict
# frozen_string_literal: true

require "system_command"
Expand All @@ -7,10 +7,47 @@
module UnpackStrategy
extend T::Helpers

AnyStrategy = T.type_alias do # rubocop:disable Style/MutableConstant
T.any(
issyl0 marked this conversation as resolved.
Show resolved Hide resolved
T.class_of(UnpackStrategy::Tar),
T.class_of(UnpackStrategy::Pax),
T.class_of(UnpackStrategy::Gzip),
T.class_of(UnpackStrategy::Dmg),
T.class_of(UnpackStrategy::Lzma),
T.class_of(UnpackStrategy::Xz),
T.class_of(UnpackStrategy::Zstd),
T.class_of(UnpackStrategy::Lzip),
T.class_of(UnpackStrategy::Air),
T.class_of(UnpackStrategy::Jar),
T.class_of(UnpackStrategy::LuaRock),
T.class_of(UnpackStrategy::MicrosoftOfficeXml),
T.class_of(UnpackStrategy::Zip),
T.class_of(UnpackStrategy::Pkg),
T.class_of(UnpackStrategy::Xar),
T.class_of(UnpackStrategy::Ttf),
T.class_of(UnpackStrategy::Otf),
T.class_of(UnpackStrategy::Git),
T.class_of(UnpackStrategy::Mercurial),
T.class_of(UnpackStrategy::Subversion),
T.class_of(UnpackStrategy::Cvs),
T.class_of(UnpackStrategy::SelfExtractingExecutable),
T.class_of(UnpackStrategy::Cab),
T.class_of(UnpackStrategy::Executable),
T.class_of(UnpackStrategy::Bzip2),
T.class_of(UnpackStrategy::Fossil),
T.class_of(UnpackStrategy::Bazaar),
T.class_of(UnpackStrategy::P7Zip),
T.class_of(UnpackStrategy::Sit),
T.class_of(UnpackStrategy::Rar),
T.class_of(UnpackStrategy::Lha),
)
end

include SystemCommand::Mixin

sig { returns(T.nilable(T::Array[AnyStrategy])) }
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 +80,11 @@ def self.strategies
Sit,
Rar,
Lha,
].freeze
].freeze, T.nilable(T::Array[AnyStrategy]))
end
private_class_method :strategies

sig { params(type: Symbol).returns(T.nilable(T.any(T.class_of(UnpackStrategy::Uncompressed), AnyStrategy))) }
def self.from_type(type)
type = {
naked: :uncompressed,
Expand All @@ -61,23 +99,29 @@ def self.from_type(type)
end
end

sig { params(extension: String).returns(T.nilable(AnyStrategy)) }
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) } }
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(AnyStrategy)) }
def self.from_magic(path)
strategies.find { |s| s.can_extract?(path) }
strategies&.find { |s| s.can_extract?(path) }
end

sig {
params(path: Pathname, prioritize_extension: T::Boolean, type: T.nilable(Symbol), ref_type: T.nilable(String),
ref: T.nilable(String), merge_xattrs: T.nilable(T::Boolean)).returns(T.untyped)
}
def self.detect(path, prioritize_extension: false, type: nil, ref_type: nil, ref: nil, merge_xattrs: nil)
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&.select { |s| s < Directory || s == Fossil }
&.find { |s| s.can_extract?(path) }
else
issyl0 marked this conversation as resolved.
Show resolved Hide resolved
strategy ||= from_magic(path)
strategy ||= from_extension(path.extname)
Expand All @@ -88,24 +132,32 @@ 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

sig { returns(T.nilable(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.nilable(T::Boolean)).void
}
issyl0 marked this conversation as resolved.
Show resolved Hide resolved
def initialize(path, ref_type: nil, ref: nil, merge_xattrs: nil)
@path = Pathname(path).expand_path
@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 +183,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 +204,7 @@ def extract_nestedly(to: nil, basename: nil, verbose: false, prioritize_extensio
end
end

sig { returns(T::Array[String]) }
def dependencies
[]
end
Expand Down
17 changes: 12 additions & 5 deletions Library/Homebrew/utils/shebang.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# typed: true
# typed: strict
# frozen_string_literal: true

module Utils
Expand All @@ -8,13 +8,20 @@ module Shebang

# Specification on how to rewrite a given shebang.
class RewriteInfo
attr_reader :regex, :max_length, :replacement
sig { returns(Regexp) }
attr_reader :regex

sig { returns(Integer) }
attr_reader :max_length

sig { returns(T.any(String, Pathname)) }
attr_reader :replacement

sig { params(regex: Regexp, max_length: Integer, replacement: T.any(String, Pathname)).void }
def initialize(regex, max_length, replacement)
@regex = regex
@max_length = max_length
@replacement = replacement
@regex = T.let(regex, Regexp)
@max_length = T.let(max_length, Integer)
@replacement = T.let(replacement, T.any(String, Pathname))
end
end

Expand Down
Loading