diff --git a/Library/Homebrew/bottle_specification.rb b/Library/Homebrew/bottle_specification.rb index 83d81f62cc..540a8fc5fd 100644 --- a/Library/Homebrew/bottle_specification.rb +++ b/Library/Homebrew/bottle_specification.rb @@ -9,7 +9,7 @@ class BottleSpecification attr_reader :collector - sig { returns(T::Hash[String, T.untyped]) } + sig { returns(T::Hash[Symbol, T.untyped]) } attr_reader :root_url_specs sig { returns(String) } @@ -20,7 +20,7 @@ class BottleSpecification @rebuild = T.let(0, Integer) @repository = T.let(Homebrew::DEFAULT_REPOSITORY, String) @collector = T.let(Utils::Bottles::Collector.new, Utils::Bottles::Collector) - @root_url_specs = T.let({}, T::Hash[String, T.untyped]) + @root_url_specs = T.let({}, T::Hash[Symbol, T.untyped]) @root_url = T.let(nil, T.nilable(String)) end diff --git a/Library/Homebrew/build.rb b/Library/Homebrew/build.rb index 702517fd03..fee6ecd7ff 100644 --- a/Library/Homebrew/build.rb +++ b/Library/Homebrew/build.rb @@ -135,9 +135,9 @@ class Build end new_env = { - "TMPDIR" => HOMEBREW_TEMP, - "TEMP" => HOMEBREW_TEMP, - "TMP" => HOMEBREW_TEMP, + "TMPDIR" => HOMEBREW_TEMP.to_s, + "TEMP" => HOMEBREW_TEMP.to_s, + "TMP" => HOMEBREW_TEMP.to_s, } with_env(new_env) do diff --git a/Library/Homebrew/bundle/skipper.rb b/Library/Homebrew/bundle/skipper.rb index c6b4ccd8f1..1261b5a621 100644 --- a/Library/Homebrew/bundle/skipper.rb +++ b/Library/Homebrew/bundle/skipper.rb @@ -37,11 +37,11 @@ module Homebrew private - sig { returns(T::Hash[Symbol, T::Array[String]]) } + sig { returns(T::Hash[Symbol, T.nilable(T::Array[String])]) } def skipped_entries return @skipped_entries if @skipped_entries - @skipped_entries ||= T.let({}, T.nilable(T::Hash[Symbol, T::Array[String]])) + @skipped_entries ||= T.let({}, T.nilable(T::Hash[Symbol, T.nilable(T::Array[String])])) [:brew, :cask, :mas, :tap, :whalebrew].each do |type| @skipped_entries[type] = ENV["HOMEBREW_BUNDLE_#{type.to_s.upcase}_SKIP"]&.split diff --git a/Library/Homebrew/cask/config.rb b/Library/Homebrew/cask/config.rb index 68b0f91e95..fbf5a426d1 100644 --- a/Library/Homebrew/cask/config.rb +++ b/Library/Homebrew/cask/config.rb @@ -12,6 +12,7 @@ module Cask # # @api internal class Config + ConfigHash = T.type_alias { T::Hash[Symbol, T.any(LazyObject, String, Pathname, T::Array[String])] } DEFAULT_DIRS = T.let( { appdir: "/Applications", @@ -33,7 +34,8 @@ module Cask T::Hash[Symbol, String], ) - sig { returns(T::Hash[Symbol, String]) } + # runtime recursive evaluation forces the LazyObject to be evaluated + T::Sig::WithoutRuntime.sig { returns(T::Hash[Symbol, T.any(LazyObject, String)]) } def self.defaults { languages: LazyObject.new { ::OS::Mac.languages }, @@ -67,35 +69,25 @@ module Cask sig { params(json: String, ignore_invalid_keys: T::Boolean).returns(T.attached_class) } def self.from_json(json, ignore_invalid_keys: false) - config = JSON.parse(json) + config = JSON.parse(json, symbolize_names: true) new( - default: config.fetch("default", {}), - env: config.fetch("env", {}), - explicit: config.fetch("explicit", {}), + default: config.fetch(:default, {}), + env: config.fetch(:env, {}), + explicit: config.fetch(:explicit, {}), ignore_invalid_keys:, ) end - sig { - params( - config: T::Enumerable[ - [T.any(String, Symbol), T.any(String, Pathname, T::Array[String])], - ], - ).returns( - T::Hash[Symbol, T.any(String, Pathname, T::Array[String])], - ) - } + sig { params(config: ConfigHash).returns(ConfigHash) } def self.canonicalize(config) config.to_h do |k, v| - key = k.to_sym - - if DEFAULT_DIRS.key?(key) + if DEFAULT_DIRS.key?(k) raise TypeError, "Invalid path for default dir #{k}: #{v.inspect}" if v.is_a?(Array) - [key, Pathname(v).expand_path] + [k, Pathname(v.to_s).expand_path] else - [key, v] + [k, v] end end end @@ -103,14 +95,14 @@ module Cask # Get the explicit configuration. # # @api internal - sig { returns(T::Hash[Symbol, T.any(String, Pathname, T::Array[String])]) } + sig { returns(ConfigHash) } attr_accessor :explicit sig { params( - default: T.nilable(T::Hash[Symbol, T.any(String, Pathname, T::Array[String])]), - env: T.nilable(T::Hash[Symbol, T.any(String, Pathname, T::Array[String])]), - explicit: T::Hash[Symbol, T.any(String, Pathname, T::Array[String])], + default: T.nilable(ConfigHash), + env: T.nilable(ConfigHash), + explicit: ConfigHash, ignore_invalid_keys: T::Boolean, ).void } @@ -118,18 +110,18 @@ module Cask if default @default = T.let( self.class.canonicalize(self.class.defaults.merge(default)), - T.nilable(T::Hash[Symbol, T.any(String, Pathname, T::Array[String])]), + T.nilable(ConfigHash), ) end if env @env = T.let( self.class.canonicalize(env), - T.nilable(T::Hash[Symbol, T.any(String, Pathname, T::Array[String])]), + T.nilable(ConfigHash), ) end @explicit = T.let( self.class.canonicalize(explicit), - T::Hash[Symbol, T.any(String, Pathname, T::Array[String])], + ConfigHash, ) if ignore_invalid_keys @@ -142,18 +134,18 @@ module Cask @explicit.assert_valid_keys(*self.class.defaults.keys) end - sig { returns(T::Hash[Symbol, T.any(String, Pathname, T::Array[String])]) } + sig { returns(ConfigHash) } def default @default ||= self.class.canonicalize(self.class.defaults) end - sig { returns(T::Hash[Symbol, T.any(String, Pathname, T::Array[String])]) } + sig { returns(ConfigHash) } def env @env ||= self.class.canonicalize( Homebrew::EnvConfig.cask_opts .select { |arg| arg.include?("=") } .map { |arg| T.cast(arg.split("=", 2), [String, String]) } - .map do |(flag, value)| + .to_h do |(flag, value)| key = flag.sub(/^--/, "") # converts --language flag to :languages config key if key == "language" @@ -161,7 +153,7 @@ module Cask value = value.split(",") end - [key, value] + [key.to_sym, value] end, ) end diff --git a/Library/Homebrew/cask/tab.rb b/Library/Homebrew/cask/tab.rb index b6bc7a54da..d9804fa70c 100644 --- a/Library/Homebrew/cask/tab.rb +++ b/Library/Homebrew/cask/tab.rb @@ -11,7 +11,7 @@ module Cask sig { returns(T.nilable(T::Array[T.untyped])) } attr_accessor :uninstall_artifacts - sig { params(attributes: T::Hash[String, T.untyped]).void } + sig { params(attributes: T.any(T::Hash[String, T.untyped], T::Hash[Symbol, T.untyped])).void } def initialize(attributes = {}) @uninstall_flight_blocks = T.let(nil, T.nilable(T::Boolean)) @uninstall_artifacts = T.let(nil, T.nilable(T::Array[T.untyped])) diff --git a/Library/Homebrew/cask/url.rb b/Library/Homebrew/cask/url.rb index 71489fcdde..c87a7b2198 100644 --- a/Library/Homebrew/cask/url.rb +++ b/Library/Homebrew/cask/url.rb @@ -54,7 +54,7 @@ module Cask revisions: T.nilable(T::Hash[T.any(Symbol, String), String]), revision: T.nilable(String), trust_cert: T.nilable(T::Boolean), - cookies: T.nilable(T::Hash[String, String]), + cookies: T.nilable(T::Hash[T.any(String, Symbol), String]), referer: T.nilable(T.any(URI::Generic, String)), header: T.nilable(T.any(String, T::Array[String])), user_agent: T.nilable(T.any(Symbol, String)), @@ -80,7 +80,8 @@ module Cask specs[:revisions] = @revisions = T.let(revisions, T.nilable(T::Hash[T.any(Symbol, String), String])) specs[:revision] = @revision = T.let(revision, T.nilable(String)) specs[:trust_cert] = @trust_cert = T.let(trust_cert, T.nilable(T::Boolean)) - specs[:cookies] = @cookies = T.let(cookies, T.nilable(T::Hash[String, String])) + specs[:cookies] = + @cookies = T.let(cookies&.transform_keys(&:to_s), T.nilable(T::Hash[String, String])) specs[:referer] = @referer = T.let(referer, T.nilable(T.any(URI::Generic, String))) specs[:headers] = @header = T.let(header, T.nilable(T.any(String, T::Array[String]))) specs[:user_agent] = @user_agent = T.let(user_agent || :default, T.nilable(T.any(Symbol, String))) diff --git a/Library/Homebrew/cask_dependent.rb b/Library/Homebrew/cask_dependent.rb index 01bd0a7f19..815bc9050b 100644 --- a/Library/Homebrew/cask_dependent.rb +++ b/Library/Homebrew/cask_dependent.rb @@ -45,7 +45,7 @@ class CaskDependent ) end - sig { returns(T::Array[CaskDependent::Requirement]) } + sig { returns(T::Array[::Requirement]) } def requirements @requirements ||= T.let( begin @@ -73,7 +73,7 @@ class CaskDependent requirements end, - T.nilable(T::Array[CaskDependent::Requirement]), + T.nilable(T::Array[::Requirement]), ) end diff --git a/Library/Homebrew/cli/args.rb b/Library/Homebrew/cli/args.rb index f3358bfc10..c6e0eb9b47 100644 --- a/Library/Homebrew/cli/args.rb +++ b/Library/Homebrew/cli/args.rb @@ -9,7 +9,7 @@ module Homebrew # 1: long option name (e.g. "--debug") # 2: option description (e.g. "Print debugging information") # 3: whether the option is hidden - OptionsType = T.type_alias { T::Array[[String, T.nilable(String), String, T::Boolean]] } + OptionsType = T.type_alias { T::Array[[T.nilable(String), T.nilable(String), String, T::Boolean]] } sig { returns(T::Array[String]) } attr_reader :options_only, :flags_only, :remaining @@ -170,7 +170,7 @@ module Homebrew sig { returns(T::Array[String]) } def cli_args @cli_args ||= @processed_options.filter_map do |short, long| - option = long || short + option = T.must(long || short) switch = :"#{option_to_name(option)}?" flag = option_to_name(option).to_sym if @table[switch] == true || @table[flag] == true diff --git a/Library/Homebrew/cmd/outdated.rb b/Library/Homebrew/cmd/outdated.rb index 6b4d81f179..3b9761c2dd 100644 --- a/Library/Homebrew/cmd/outdated.rb +++ b/Library/Homebrew/cmd/outdated.rb @@ -127,9 +127,7 @@ module Homebrew sig { params( formulae_or_casks: T::Array[T.any(Formula, Cask::Cask)], - ).returns( - T::Array[T.any(T::Hash[String, T.untyped], T::Hash[String, T.untyped])], - ) + ).returns(T::Array[T::Hash[Symbol, T.untyped]]) } def json_info(formulae_or_casks) formulae_or_casks.map do |formula_or_cask| diff --git a/Library/Homebrew/cmd/update-report.rb b/Library/Homebrew/cmd/update-report.rb index 9419a9eb2d..54f2d39718 100644 --- a/Library/Homebrew/cmd/update-report.rb +++ b/Library/Homebrew/cmd/update-report.rb @@ -427,6 +427,19 @@ require "extend/os/cmd/update-report" class Reporter include Utils::Output::Mixin + Report = T.type_alias do + { + A: T::Array[String], + AC: T::Array[String], + D: T::Array[String], + DC: T::Array[String], + M: T::Array[String], + MC: T::Array[String], + R: T::Array[[String, String]], + RC: T::Array[[String, String]], + } + end + class ReporterRevisionUnsetError < RuntimeError sig { params(var_name: String).void } def initialize(var_name) @@ -456,14 +469,17 @@ class Reporter raise ReporterRevisionUnsetError, current_revision_var if @current_revision.empty? end - @report = T.let(nil, T.nilable(T::Hash[Symbol, T::Array[String]])) + @report = T.let(nil, T.nilable(Report)) end - sig { params(auto_update: T::Boolean).returns(T::Hash[Symbol, T::Array[String]]) } + sig { params(auto_update: T::Boolean).returns(Report) } def report(auto_update: false) return @report if @report - @report = Hash.new { |h, k| h[k] = [] } + @report = { + A: [], AC: [], D: [], DC: [], M: [], MC: [], R: T.let([], T::Array[[String, String]]), + RC: T.let([], T::Array[[String, String]]) + } return @report unless updated? diff.each_line do |line| @@ -791,13 +807,15 @@ class ReporterHub sig { void } def initialize - @hash = T.let({}, T::Hash[Symbol, T::Array[String]]) + @hash = T.let({}, T::Hash[Symbol, T::Array[T.any(String, [String, String])]]) @reporters = T.let([], T::Array[Reporter]) end sig { params(key: Symbol).returns(T::Array[String]) } def select_formula_or_cask(key) - @hash.fetch(key, []) + raise "Unsupported key #{key}" unless [:A, :AC, :D, :DC, :M, :MC].include?(key) + + T.cast(@hash.fetch(key, []), T::Array[String]) end sig { params(reporter: Reporter, auto_update: T::Boolean).void } diff --git a/Library/Homebrew/commands.rb b/Library/Homebrew/commands.rb index 421866524d..6beee3bab9 100644 --- a/Library/Homebrew/commands.rb +++ b/Library/Homebrew/commands.rb @@ -204,7 +204,7 @@ module Commands cmd_parser.processed_options.filter_map do |short, long, desc, hidden| next if hidden - [long || short, desc] + [T.must(long || short), desc] end else options = [] diff --git a/Library/Homebrew/dependency_collector.rb b/Library/Homebrew/dependency_collector.rb index 68e68c3fa9..3724f97cd4 100644 --- a/Library/Homebrew/dependency_collector.rb +++ b/Library/Homebrew/dependency_collector.rb @@ -135,7 +135,7 @@ class DependencyCollector sig { params(spec: T.any(String, Resource, Symbol, Requirement, Dependency, Class), - tags: T::Array[Symbol]).returns(T.any(Dependency, Requirement, Array, NilClass)) + tags: T::Array[T.any(String, Symbol)]).returns(T.any(Dependency, Requirement, Array, NilClass)) } def parse_spec(spec, tags) raise ArgumentError, "Implicit dependencies cannot be manually specified" if tags.include?(:implicit) diff --git a/Library/Homebrew/dev-cmd/bottle.rb b/Library/Homebrew/dev-cmd/bottle.rb index 5abeb8d0f4..7fb25e4a56 100644 --- a/Library/Homebrew/dev-cmd/bottle.rb +++ b/Library/Homebrew/dev-cmd/bottle.rb @@ -181,7 +181,7 @@ module Homebrew end sig { - params(old_keys: T::Array[String], old_bottle_spec: BottleSpecification, + params(old_keys: T::Array[Symbol], old_bottle_spec: BottleSpecification, new_bottle_hash: T::Hash[String, T.untyped]) .returns([T::Array[String], T::Array[T::Hash[Symbol, T.any(String, Symbol)]]]) } @@ -506,7 +506,7 @@ module Homebrew tab.time = nil tab.changed_files = changed_files.dup if args.only_json_tab? - tab.changed_files.delete(Pathname.new(AbstractTab::FILENAME)) + tab.changed_files&.delete(Pathname.new(AbstractTab::FILENAME)) tab.tabfile.unlink else tab.write diff --git a/Library/Homebrew/dev-cmd/tests.rb b/Library/Homebrew/dev-cmd/tests.rb index dc742876bf..0780be102d 100644 --- a/Library/Homebrew/dev-cmd/tests.rb +++ b/Library/Homebrew/dev-cmd/tests.rb @@ -119,7 +119,7 @@ module Homebrew # seeds being output when running parallel tests. seed = args.seed || rand(0xFFFF).to_i - bundle_args = ["-I", HOMEBREW_LIBRARY_PATH/"test"] + bundle_args = ["-I", (HOMEBREW_LIBRARY_PATH/"test").to_s] bundle_args += %W[ --seed #{seed} --color @@ -249,6 +249,7 @@ module Homebrew ENV["HOMEBREW_TEST_GENERIC_OS"] = "1" if args.generic? ENV["HOMEBREW_TEST_ONLINE"] = "1" if args.online? ENV["HOMEBREW_SORBET_RUNTIME"] = "1" + ENV["HOMEBREW_SORBET_RECURSIVE"] = "1" ENV["USER"] ||= system_command!("id", args: ["-nu"]).stdout.chomp diff --git a/Library/Homebrew/diagnostic.rb b/Library/Homebrew/diagnostic.rb index b00517b557..9dbcb63ce9 100644 --- a/Library/Homebrew/diagnostic.rb +++ b/Library/Homebrew/diagnostic.rb @@ -1198,9 +1198,9 @@ module Homebrew private - sig { returns(T::Array[Pathname]) } + sig { returns(T::Array[String]) } def paths - @paths ||= T.let(ORIGINAL_PATHS.uniq.map(&:to_s), T.nilable(T::Array[Pathname])) + @paths ||= T.let(ORIGINAL_PATHS.uniq.map(&:to_s), T.nilable(T::Array[String])) end end end diff --git a/Library/Homebrew/download_strategy.rb b/Library/Homebrew/download_strategy.rb index 5353ee2862..c70cbce062 100644 --- a/Library/Homebrew/download_strategy.rb +++ b/Library/Homebrew/download_strategy.rb @@ -643,11 +643,9 @@ class CurlDownloadStrategy < AbstractFileDownloadStrategy args end - sig { returns(T::Hash[Symbol, String]) } + sig { returns(T::Hash[Symbol, T.any(String, Symbol)]) } def _curl_opts - return { user_agent: meta.fetch(:user_agent) } if meta.key?(:user_agent) - - {} + meta.slice(:user_agent) end sig { override.params(args: String, options: T.untyped).returns(SystemCommand::Result) } diff --git a/Library/Homebrew/env_config.rb b/Library/Homebrew/env_config.rb index 328bd734f8..40bdbadbbd 100644 --- a/Library/Homebrew/env_config.rb +++ b/Library/Homebrew/env_config.rb @@ -471,6 +471,11 @@ module Homebrew "of macOS. This is useful in development on new macOS versions.", boolean: true, }, + HOMEBREW_SORBET_RECURSIVE: { + description: "If set along with `$HOMEBREW_SORBET_RUNTIME`, enable recursive typechecking using Sorbet. " \ + "Auomatically enabled when running tests.", + boolean: true, + }, HOMEBREW_SORBET_RUNTIME: { description: "If set, enable runtime typechecking using Sorbet. " \ "Set by default for `$HOMEBREW_DEVELOPER` or when running some developer commands.", diff --git a/Library/Homebrew/extend/ENV/super.rb b/Library/Homebrew/extend/ENV/super.rb index 03fe313b47..0fca6cc7a3 100644 --- a/Library/Homebrew/extend/ENV/super.rb +++ b/Library/Homebrew/extend/ENV/super.rb @@ -244,7 +244,7 @@ module Superenv end # Don't add `llvm` to library paths; this leads to undesired linkage to LLVM's `libunwind` - paths << keg_only_deps.reject { |dep| dep.name.match?(/^llvm(@\d+)?$/) } + paths += keg_only_deps.reject { |dep| dep.name.match?(/^llvm(@\d+)?$/) } .map(&:opt_lib) paths << (HOMEBREW_PREFIX/"lib") diff --git a/Library/Homebrew/extend/kernel.rb b/Library/Homebrew/extend/kernel.rb index a38121b094..6b6454dc4f 100644 --- a/Library/Homebrew/extend/kernel.rb +++ b/Library/Homebrew/extend/kernel.rb @@ -34,7 +34,7 @@ module Kernel sig { type_parameters(:U).params(block: T.proc.returns(T.type_parameter(:U))).returns(T.type_parameter(:U)) } def with_homebrew_path(&block) - with_env(PATH: PATH.new(ORIGINAL_PATHS), &block) + with_env(PATH: PATH.new(ORIGINAL_PATHS).to_s, &block) end sig { @@ -283,8 +283,10 @@ module Kernel # @api public sig { type_parameters(:U) - .params(hash: T::Hash[Object, String], _block: T.proc.returns(T.type_parameter(:U))) - .returns(T.type_parameter(:U)) + .params( + hash: T::Hash[Object, T.any(NilClass, PATH, Pathname, String)], + _block: T.proc.returns(T.type_parameter(:U)), + ).returns(T.type_parameter(:U)) } def with_env(hash, &_block) old_values = {} @@ -292,7 +294,7 @@ module Kernel hash.each do |key, value| key = key.to_s old_values[key] = ENV.delete(key) - ENV[key] = value + ENV[key] = value&.to_s end yield diff --git a/Library/Homebrew/extend/os/linux/cask/config.rb b/Library/Homebrew/extend/os/linux/cask/config.rb index 756cc7bae1..c9184fea82 100644 --- a/Library/Homebrew/extend/os/linux/cask/config.rb +++ b/Library/Homebrew/extend/os/linux/cask/config.rb @@ -15,7 +15,7 @@ module OS appdir: "~/.config/apps", }.freeze, T::Hash[Symbol, String]) - sig { returns(T::Hash[Symbol, String]) } + sig { returns(T::Hash[Symbol, T.any(LazyObject, String)]) } def defaults { languages: LazyObject.new { Linux.languages }, diff --git a/Library/Homebrew/formula.rb b/Library/Homebrew/formula.rb index 33560d6e04..a1e0720544 100644 --- a/Library/Homebrew/formula.rb +++ b/Library/Homebrew/formula.rb @@ -3963,7 +3963,7 @@ class Formula # ``` # # @api public - sig { params(dep: T.any(String, Symbol, T::Hash[String, T.untyped], T::Class[Requirement])).void } + sig { params(dep: T.any(String, Symbol, T::Hash[T.any(String, Symbol, T::Class[Requirement]), T.untyped], T::Class[Requirement])).void } def depends_on(dep) specs.each { |spec| spec.depends_on(dep) } end diff --git a/Library/Homebrew/formula_installer.rb b/Library/Homebrew/formula_installer.rb index 08107df5af..6e714d12ee 100644 --- a/Library/Homebrew/formula_installer.rb +++ b/Library/Homebrew/formula_installer.rb @@ -809,7 +809,7 @@ on_request: installed_on_request?, options:) else [] end - options += effective_build_options_for(formula).used_options.to_a + options += effective_build_options_for(formula).used_options.to_a.map(&:to_s) options end diff --git a/Library/Homebrew/formulary.rb b/Library/Homebrew/formulary.rb index b9bad8ecf3..60daf254d9 100644 --- a/Library/Homebrew/formulary.rb +++ b/Library/Homebrew/formulary.rb @@ -51,7 +51,14 @@ module Formulary end private_class_method :platform_cache_tag - sig { returns(T::Hash[Symbol, T::Hash[String, T.class_of(Formula)]]) } + sig { + returns({ + api: T.nilable(T::Hash[String, T.class_of(Formula)]), + formulary_factory: T.nilable(T::Hash[String, Formula]), + path: T.nilable(T::Hash[String, T.class_of(Formula)]), + stub: T.nilable(T::Hash[String, T.class_of(Formula)]), + }) + } def self.platform_cache cache[platform_cache_tag] ||= {} end diff --git a/Library/Homebrew/lazy_object.rb b/Library/Homebrew/lazy_object.rb index c99bcb4db3..a09c92ed7a 100644 --- a/Library/Homebrew/lazy_object.rb +++ b/Library/Homebrew/lazy_object.rb @@ -28,4 +28,7 @@ class LazyObject < Delegator __getobj__.is_a?(klass) || super end + + def class = __getobj__.class + def to_s = __getobj__.to_s end diff --git a/Library/Homebrew/messages.rb b/Library/Homebrew/messages.rb index 49b2ebd5c3..5c1317abb8 100644 --- a/Library/Homebrew/messages.rb +++ b/Library/Homebrew/messages.rb @@ -14,7 +14,7 @@ class Messages sig { returns(Integer) } attr_reader :package_count - sig { returns(T::Array[T::Hash[String, Float]]) } + sig { returns(T::Array[{ package: String, time: Float }]) } attr_reader :install_times sig { void } @@ -22,7 +22,7 @@ class Messages @caveats = T.let([], T::Array[{ package: String, caveats: T.any(String, Caveats) }]) @completions_and_elisp = T.let(Set.new, T::Set[String]) @package_count = T.let(0, Integer) - @install_times = T.let([], T::Array[T::Hash[String, Float]]) + @install_times = T.let([], T::Array[{ package: String, time: Float }]) end sig { params(package: String, caveats: T.any(String, Caveats)).void } diff --git a/Library/Homebrew/requirements/xcode_requirement.rb b/Library/Homebrew/requirements/xcode_requirement.rb index c0c9134238..abc31503ce 100644 --- a/Library/Homebrew/requirements/xcode_requirement.rb +++ b/Library/Homebrew/requirements/xcode_requirement.rb @@ -15,10 +15,10 @@ class XcodeRequirement < Requirement xcode_installed_version! end - sig { params(tags: T::Array[String]).void } + sig { params(tags: T::Array[T.any(String, Symbol)]).void } def initialize(tags = []) version = tags.shift if tags.first.to_s.match?(/(\d\.)+\d/) - @version = T.let(version, T.nilable(String)) + @version = T.let(version.to_s, T.nilable(String)) super end diff --git a/Library/Homebrew/rubocops/cask/ast/stanza.rb b/Library/Homebrew/rubocops/cask/ast/stanza.rb index cab7d606e4..8bd68c6539 100644 --- a/Library/Homebrew/rubocops/cask/ast/stanza.rb +++ b/Library/Homebrew/rubocops/cask/ast/stanza.rb @@ -83,11 +83,11 @@ module RuboCop ) end - sig { returns(T::Hash[Parser::Source::Range, T::Array[Parser::Source::Comment]]) } + sig { returns(T::Hash[Parser::Source::Map, T::Array[Parser::Source::Comment]]) } def comments_hash @comments_hash ||= T.let( Parser::Source::Comment.associate_locations(stanza_node.parent, all_comments), - T.nilable(T::Hash[Parser::Source::Range, T::Array[Parser::Source::Comment]]), + T.nilable(T::Hash[Parser::Source::Map, T::Array[Parser::Source::Comment]]), ) end diff --git a/Library/Homebrew/rubocops/cask/mixin/cask_help.rb b/Library/Homebrew/rubocops/cask/mixin/cask_help.rb index 61bd3643a8..d9d43ec445 100644 --- a/Library/Homebrew/rubocops/cask/mixin/cask_help.rb +++ b/Library/Homebrew/rubocops/cask/mixin/cask_help.rb @@ -46,7 +46,7 @@ module RuboCop sig { params( block_node: RuboCop::AST::BlockNode, - comments: T::Array[String], + comments: T::Array[Parser::Source::Comment], ).returns( T::Array[RuboCop::Cask::AST::Stanza], ) diff --git a/Library/Homebrew/sbom.rb b/Library/Homebrew/sbom.rb index b0b463a004..5607b12f06 100644 --- a/Library/Homebrew/sbom.rb +++ b/Library/Homebrew/sbom.rb @@ -13,7 +13,7 @@ class SBOM include Utils::Output::Mixin FILENAME = "sbom.spdx.json" - SCHEMA_FILE = (HOMEBREW_LIBRARY_PATH/"data/schemas/sbom.json").freeze + SCHEMA_FILE = T.let((HOMEBREW_LIBRARY_PATH/"data/schemas/sbom.json").freeze, Pathname) # Instantiates a {SBOM} for a new installation of a formula. sig { params(formula: Formula, tab: Tab).returns(T.attached_class) } @@ -62,7 +62,7 @@ class SBOM formula.prefix/FILENAME end - sig { params(deps: T::Array[T::Hash[String, String]]).returns(T::Array[T::Hash[String, String]]) } + sig { params(deps: T::Array[T::Hash[String, T.untyped]]).returns(T::Array[T::Hash[String, T.anything]]) } def self.runtime_deps_hash(deps) deps.map do |dep| full_name = dep.fetch("full_name") @@ -83,12 +83,12 @@ class SBOM spdxfile(formula).exist? end - sig { returns(T::Hash[String, T.untyped]) } + sig { returns(T::Hash[String, T.anything]) } def self.schema - @schema ||= JSON.parse(SCHEMA_FILE.read, freeze: true) + @schema ||= T.let(JSON.parse(SCHEMA_FILE.read, freeze: true), T.nilable(T::Hash[String, T.untyped])) end - sig { params(bottling: T::Boolean).returns(T::Array[T::Hash[String, T.untyped]]) } + sig { params(bottling: T::Boolean).returns(T::Array[String]) } def schema_validation_errors(bottling: false) unless Homebrew.require? "json_schemer" error_message = "Need json_schemer to validate SBOM, run `brew install-bundler-gems --add-groups=bottle`!" @@ -134,17 +134,17 @@ class SBOM attr_reader :name, :homebrew_version, :time, :stdlib, :source, :built_on, :license attr_accessor :spdxfile - sig { params(attributes: Hash).void } + sig { params(attributes: T::Hash[Symbol, T.untyped]).void } def initialize(attributes = {}) attributes.each { |key, value| instance_variable_set(:"@#{key}", value) } end sig { params( - runtime_dependency_declaration: T::Array[Hash], - compiler_declaration: Hash, + runtime_dependency_declaration: T::Array[T::Hash[Symbol, T.untyped]], + compiler_declaration: T::Hash[String, T.untyped], bottling: T::Boolean, - ).returns(T::Array[Hash]) + ).returns(T::Array[T::Hash[Symbol, T.untyped]]) } def generate_relations_json(runtime_dependency_declaration, compiler_declaration, bottling:) runtime = runtime_dependency_declaration.map do |dependency| @@ -167,7 +167,7 @@ class SBOM spdxElementId: "SPDXRef-File-#{name}", relationshipType: "PACKAGE_OF", relatedSpdxElement: "SPDXRef-Archive-#{name}-src", - }], T::Array[Hash]) + }], T::Array[T::Hash[Symbol, T.untyped]]) unless bottling base << { @@ -189,16 +189,11 @@ class SBOM end sig { - params(runtime_dependency_declaration: T::Array[Hash], - compiler_declaration: Hash, - bottling: T::Boolean).returns( - T::Array[ - T::Hash[ - Symbol, - T.any(String, T::Array[T::Hash[Symbol, String]]), - ], - ], - ) + params( + runtime_dependency_declaration: T::Array[T::Hash[Symbol, T.anything]], + compiler_declaration: T::Hash[String, T::Hash[Symbol, T.anything]], + bottling: T::Boolean, + ).returns(T::Array[T::Hash[Symbol, T.untyped]]) } def generate_packages_json(runtime_dependency_declaration, compiler_declaration, bottling:) bottle = [] @@ -259,9 +254,8 @@ class SBOM end sig { - params(bottling: T::Boolean).returns(T::Array[T::Hash[Symbol, - T.any(T::Boolean, String, - T::Array[T::Hash[Symbol, String]])]]) + params(bottling: T::Boolean) + .returns(T::Array[T::Hash[Symbol, T.any(T::Boolean, String, T::Array[T::Hash[Symbol, String]])]]) } def full_spdx_runtime_dependencies(bottling:) return [] if bottling || @runtime_dependencies.blank? @@ -302,7 +296,7 @@ class SBOM end end - sig { params(bottling: T::Boolean).returns(T::Hash[Symbol, T.any(String, T::Array[T::Hash[Symbol, String]])]) } + sig { params(bottling: T::Boolean).returns(T::Hash[Symbol, T.anything]) } def to_spdx_sbom(bottling:) runtime_full = full_spdx_runtime_dependencies(bottling:) @@ -360,7 +354,7 @@ class SBOM } end - sig { params(base: T.nilable(T::Hash[String, Hash])).returns(T.nilable(T::Hash[String, String])) } + sig { params(base: T.nilable(T::Hash[String, T.untyped])).returns(T.nilable(T::Hash[String, String])) } def get_bottle_info(base) return unless base.present? diff --git a/Library/Homebrew/service.rb b/Library/Homebrew/service.rb index 9d648e2c54..b9ac0a41bf 100644 --- a/Library/Homebrew/service.rb +++ b/Library/Homebrew/service.rb @@ -337,7 +337,7 @@ module Homebrew parsed end - sig { params(variables: T::Hash[Symbol, String]).returns(T.nilable(T::Hash[Symbol, String])) } + sig { params(variables: T::Hash[Symbol, T.any(Pathname, String)]).returns(T.nilable(T::Hash[Symbol, String])) } def environment_variables(variables = {}) @environment_variables = variables.transform_values(&:to_s) end diff --git a/Library/Homebrew/software_spec.rb b/Library/Homebrew/software_spec.rb index 82435a9a28..0f909685a1 100644 --- a/Library/Homebrew/software_spec.rb +++ b/Library/Homebrew/software_spec.rb @@ -219,7 +219,7 @@ class SoftwareSpec options << opt end - sig { params(hash: T::Hash[T.any(String, Symbol), T.any(String, Symbol)]).void } + sig { params(hash: T::Hash[T.any(String, Symbol, T::Array[String]), T.any(String, Symbol, T::Array[String])]).void } def deprecated_option(hash) raise ArgumentError, "deprecated_option hash must not be empty" if hash.empty? @@ -242,7 +242,7 @@ class SoftwareSpec @build = BuildOptions.new(Options.create(@flags), options) end - sig { params(spec: T.any(String, Symbol, T::Hash[String, T.untyped], T::Class[Requirement], Dependable)).void } + sig { params(spec: T.any(String, Symbol, T::Hash[T.any(String, Symbol, T::Class[Requirement]), T.untyped], T::Class[Requirement], Dependable)).void } def depends_on(spec) dep = dependency_collector.add(spec) add_dep_option(dep) if dep diff --git a/Library/Homebrew/standalone/sorbet.rb b/Library/Homebrew/standalone/sorbet.rb index 406582618d..332356f5c5 100644 --- a/Library/Homebrew/standalone/sorbet.rb +++ b/Library/Homebrew/standalone/sorbet.rb @@ -10,6 +10,55 @@ require "extend/module" # There are mechanisms to achieve a middle ground (`default_checked_level`). if ENV["HOMEBREW_SORBET_RUNTIME"] T::Configuration.enable_final_checks_on_hooks + if ENV["HOMEBREW_SORBET_RECURSIVE"] == "1" + module T + module Types + class FixedArray < Base + def valid?(obj) = recursively_valid?(obj) + end + + class FixedHash < Base + def valid?(obj) = recursively_valid?(obj) + end + + class Intersection < Base + def valid?(obj) = recursively_valid?(obj) + end + + class TypedArray < TypedEnumerable + def valid?(obj) = recursively_valid?(obj) + end + + class TypedEnumerable < Base + def valid?(obj) = recursively_valid?(obj) + end + + class TypedEnumeratorChain < TypedEnumerable + def valid?(obj) = recursively_valid?(obj) + end + + class TypedEnumeratorLazy < TypedEnumerable + def valid?(obj) = recursively_valid?(obj) + end + + class TypedHash < TypedEnumerable + def valid?(obj) = recursively_valid?(obj) + end + + class TypedRange < TypedEnumerable + def valid?(obj) = recursively_valid?(obj) + end + + class TypedSet < TypedEnumerable + def valid?(obj) = recursively_valid?(obj) + end + + class Union < Base + def valid?(obj) = recursively_valid?(obj) + end + end + end + end else # Redefine `T.let`, etc. to make the `checked` parameter default to `false` rather than `true`. # @private diff --git a/Library/Homebrew/system_command.rb b/Library/Homebrew/system_command.rb index 39f9975e16..3f6f6fc230 100644 --- a/Library/Homebrew/system_command.rb +++ b/Library/Homebrew/system_command.rb @@ -27,7 +27,7 @@ class SystemCommand args: T::Array[T.any(String, Integer, Float, Pathname, URI::Generic)], sudo: T::Boolean, sudo_as_root: T::Boolean, - env: T::Hash[String, String], + env: T::Hash[String, T.any(NilClass, String, T::Boolean)], input: T.any(String, T::Array[String]), must_succeed: T::Boolean, print_stdout: T.any(T::Boolean, Symbol), @@ -56,7 +56,7 @@ class SystemCommand args: T::Array[T.any(String, Integer, Float, Pathname, URI::Generic)], sudo: T::Boolean, sudo_as_root: T::Boolean, - env: T::Hash[String, String], + env: T::Hash[String, T.any(NilClass, String, T::Boolean)], input: T.any(String, T::Array[String]), print_stdout: T.any(T::Boolean, Symbol), print_stderr: T.any(T::Boolean, Symbol), @@ -84,7 +84,7 @@ class SystemCommand args: T::Array[T.any(String, Integer, Float, Pathname, URI::Generic)], sudo: T::Boolean, sudo_as_root: T::Boolean, - env: T::Hash[String, String], + env: T::Hash[String, T.any(NilClass, String, T::Boolean)], input: T.any(String, T::Array[String]), must_succeed: T::Boolean, print_stdout: T.any(T::Boolean, Symbol), @@ -110,7 +110,7 @@ class SystemCommand args: T::Array[T.any(String, Integer, Float, Pathname, URI::Generic)], sudo: T::Boolean, sudo_as_root: T::Boolean, - env: T::Hash[String, String], + env: T::Hash[String, T.any(NilClass, String, T::Boolean)], input: T.any(String, T::Array[String]), must_succeed: T::Boolean, print_stdout: T.any(T::Boolean, Symbol), @@ -169,7 +169,7 @@ class SystemCommand args: T::Array[T.any(String, Integer, Float, Pathname, URI::Generic)], sudo: T::Boolean, sudo_as_root: T::Boolean, - env: T::Hash[String, String], + env: T::Hash[String, T.any(NilClass, String, T::Boolean)], input: T.any(String, T::Array[String]), must_succeed: T::Boolean, print_stdout: T.any(T::Boolean, Symbol), @@ -237,7 +237,7 @@ class SystemCommand sig { returns(T.any(NilClass, String, Pathname)) } attr_reader :chdir - sig { returns(T::Hash[String, String]) } + sig { returns(T::Hash[String, T.any(NilClass, String, T::Boolean)]) } attr_reader :env sig { returns(T::Boolean) } @@ -378,7 +378,7 @@ class SystemCommand sig { params( - env: T::Hash[String, String], + env: T::Hash[String, T.nilable(String)], executable: String, args: String, options: T.untyped, @@ -480,7 +480,7 @@ class SystemCommand sig { params( command: T::Array[String], - output: T::Array[[Symbol, String]], + output: T::Array[[T.any(String, Symbol), String]], status: Process::Status, secrets: T::Array[String], ).void diff --git a/Library/Homebrew/tab.rb b/Library/Homebrew/tab.rb index 9acea83252..1f5985b5f1 100644 --- a/Library/Homebrew/tab.rb +++ b/Library/Homebrew/tab.rb @@ -38,7 +38,8 @@ class AbstractTab # @api internal attr_accessor :runtime_dependencies - sig { params(attributes: T::Hash[String, T.untyped]).void } + # TODO: Update attributes to only accept symbol keys (kwargs style). + sig { params(attributes: T.any(T::Hash[String, T.untyped], T::Hash[Symbol, T.untyped])).void } def initialize(attributes = {}) @installed_as_dependency = T.let(nil, T.nilable(T::Boolean)) @installed_on_request = T.let(nil, T.nilable(T::Boolean)) @@ -51,7 +52,14 @@ class AbstractTab @built_on = T.let(nil, T.nilable(T::Hash[String, T.untyped])) @runtime_dependencies = T.let(nil, T.nilable(T::Array[T.untyped])) - attributes.each { |key, value| instance_variable_set(:"@#{key}", value) } + attributes.each do |key, value| + case key.to_sym + when :changed_files + @changed_files = value&.map { |f| Pathname(f) } + else + instance_variable_set(:"@#{key}", value) + end + end end # Instantiates a {Tab} for a new installation of a formula or cask. @@ -166,15 +174,18 @@ class Tab < AbstractTab # @api internal attr_accessor :poured_from_bottle - attr_accessor :built_as_bottle, :changed_files, :stdlib, :aliases + attr_accessor :built_as_bottle, :stdlib, :aliases attr_writer :used_options, :unused_options, :compiler, :source_modified_time attr_reader :tapped_from - sig { params(attributes: T::Hash[String, T.untyped]).void } + sig { returns(T.nilable(T::Array[Pathname])) } + attr_accessor :changed_files + + sig { params(attributes: T.any(T::Hash[String, T.untyped], T::Hash[Symbol, T.untyped])).void } def initialize(attributes = {}) @poured_from_bottle = T.let(nil, T.nilable(T::Boolean)) @built_as_bottle = T.let(nil, T.nilable(T::Boolean)) - @changed_files = T.let(nil, T.nilable(T::Array[Pathname])) + @changed_files = nil @stdlib = T.let(nil, T.nilable(String)) @aliases = T.let(nil, T.nilable(T::Array[String])) @used_options = T.let(nil, T.nilable(T::Array[String])) diff --git a/Library/Homebrew/test/cmd/update-report_spec.rb b/Library/Homebrew/test/cmd/update-report_spec.rb index 50363220c1..3b919200bf 100644 --- a/Library/Homebrew/test/cmd/update-report_spec.rb +++ b/Library/Homebrew/test/cmd/update-report_spec.rb @@ -83,7 +83,7 @@ RSpec.describe Homebrew::Cmd::UpdateReport do expect(hub.select_formula_or_cask(:A)).to be_empty expect(hub.select_formula_or_cask(:D)).to be_empty - expect(hub.select_formula_or_cask(:R)).to eq([["cv", "progress"]]) + expect(hub.instance_variable_get(:@hash)[:R]).to eq([["cv", "progress"]]) end context "when updating a Tap other than the core Tap" do @@ -102,7 +102,7 @@ RSpec.describe Homebrew::Cmd::UpdateReport do expect(hub.select_formula_or_cask(:A)).to be_empty expect(hub.select_formula_or_cask(:D)).to be_empty - expect(hub.select_formula_or_cask(:R)).to be_empty + expect(hub.instance_variable_get(:@hash)[:R]).to be_nil end specify "with renamed Formula and restructured Tap" do @@ -111,7 +111,7 @@ RSpec.describe Homebrew::Cmd::UpdateReport do expect(hub.select_formula_or_cask(:A)).to be_empty expect(hub.select_formula_or_cask(:D)).to be_empty - expect(hub.select_formula_or_cask(:R)).to eq([%w[foo/bar/xchat foo/bar/xchat2]]) + expect(hub.instance_variable_get(:@hash)[:R]).to eq([%w[foo/bar/xchat foo/bar/xchat2]]) end specify "with simulated 'homebrew/php' restructuring" do @@ -119,7 +119,7 @@ RSpec.describe Homebrew::Cmd::UpdateReport do expect(hub.select_formula_or_cask(:A)).to be_empty expect(hub.select_formula_or_cask(:D)).to be_empty - expect(hub.select_formula_or_cask(:R)).to be_empty + expect(hub.instance_variable_get(:@hash)[:R]).to be_nil end specify "with Formula changes" do @@ -127,7 +127,7 @@ RSpec.describe Homebrew::Cmd::UpdateReport do expect(hub.select_formula_or_cask(:A)).to eq(%w[foo/bar/lua]) expect(hub.select_formula_or_cask(:M)).to eq(%w[foo/bar/git]) - expect(hub.select_formula_or_cask(:D)).to be_empty + expect(hub.instance_variable_get(:@hash)[:R]).to be_nil end end end diff --git a/Library/Homebrew/test/download_strategies/curl_spec.rb b/Library/Homebrew/test/download_strategies/curl_spec.rb index a7c5deee52..c3da1134c9 100644 --- a/Library/Homebrew/test/download_strategies/curl_spec.rb +++ b/Library/Homebrew/test/download_strategies/curl_spec.rb @@ -173,7 +173,7 @@ RSpec.describe CurlDownloadStrategy do hash_including(args: array_including_cons("#{artifact_domain}/#{resource_path}")), ) .at_least(:once) - .and_return(SystemCommand::Result.new(["curl"], [""], status, secrets: [])) + .and_return(SystemCommand::Result.new(["curl"], [[:stdout, ""]], status, secrets: [])) strategy.fetch end @@ -191,7 +191,7 @@ RSpec.describe CurlDownloadStrategy do hash_including(args: array_including_cons("#{artifact_domain}/#{resource_path}")), ) .at_least(:once) - .and_return(SystemCommand::Result.new(["curl"], [""], status, secrets: [])) + .and_return(SystemCommand::Result.new(["curl"], [[:stdout, ""]], status, secrets: [])) strategy.fetch end diff --git a/Library/Homebrew/test/livecheck/strategy/header_match_spec.rb b/Library/Homebrew/test/livecheck/strategy/header_match_spec.rb index 39553a28d0..aa9b2d7c46 100644 --- a/Library/Homebrew/test/livecheck/strategy/header_match_spec.rb +++ b/Library/Homebrew/test/livecheck/strategy/header_match_spec.rb @@ -110,7 +110,7 @@ RSpec.describe Homebrew::Livecheck::Strategy::HeaderMatch do it "errors on an invalid return type from a block" do expect { header_match.versions_from_headers(headers) { 123 } } - .to raise_error(TypeError, Homebrew::Livecheck::Strategy::INVALID_BLOCK_RETURN_VALUE_MSG) + .to raise_error(TypeError, /Parameter 'headers': Expected type T::Hash\[String, String\]/o) end end end diff --git a/Library/Homebrew/test/services/cli_spec.rb b/Library/Homebrew/test/services/cli_spec.rb index c8cbc717c2..006f8a8adc 100644 --- a/Library/Homebrew/test/services/cli_spec.rb +++ b/Library/Homebrew/test/services/cli_spec.rb @@ -87,8 +87,9 @@ RSpec.describe Homebrew::Services::Cli do describe "#run" do it "checks missing file causes error" do expect(Homebrew::Services::System).not_to receive(:root?) + service = instance_double(Homebrew::Services::FormulaWrapper, name: "service_name") expect do - services_cli.start(["service_name"], "/non/existent/path") + services_cli.start([service], "/non/existent/path") end.to raise_error(UsageError, "Invalid usage: Provided service file does not exist.") end @@ -110,8 +111,9 @@ RSpec.describe Homebrew::Services::Cli do describe "#start" do it "checks missing file causes error" do expect(Homebrew::Services::System).not_to receive(:root?) + service = instance_double(Homebrew::Services::FormulaWrapper, name: "service_name") expect do - services_cli.start(["service_name"], "/hfdkjshksdjhfkjsdhf/fdsjghsdkjhb") + services_cli.start([service], "/hfdkjshksdjhfkjsdhf/fdsjghsdkjhb") end.to raise_error(UsageError, "Invalid usage: Provided service file does not exist.") end diff --git a/Library/Homebrew/test/services/commands/info_spec.rb b/Library/Homebrew/test/services/commands/info_spec.rb index 8b5c5cefee..788f229299 100644 --- a/Library/Homebrew/test/services/commands/info_spec.rb +++ b/Library/Homebrew/test/services/commands/info_spec.rb @@ -23,7 +23,7 @@ RSpec.describe Homebrew::Services::Commands::Info do it "succeeds with items" do out = "service ()\nRunning: true\nLoaded: true\nSchedulable: false\n" - formula = { + formula_wrapper = instance_double(Homebrew::Services::FormulaWrapper, to_hash: { name: "service", user: "user", status: :started, @@ -31,9 +31,9 @@ RSpec.describe Homebrew::Services::Commands::Info do running: true, loaded: true, schedulable: false, - } + }) expect do - described_class.run([formula], verbose: false, json: false) + described_class.run([formula_wrapper], verbose: false, json: false) end.to output(out).to_stdout end @@ -48,8 +48,9 @@ RSpec.describe Homebrew::Services::Commands::Info do schedulable: false, } out = "#{JSON.pretty_generate([formula])}\n" + formula_wrapper = instance_double(Homebrew::Services::FormulaWrapper, to_hash: formula) expect do - described_class.run([formula], verbose: false, json: true) + described_class.run([formula_wrapper], verbose: false, json: true) end.to output(out).to_stdout end end diff --git a/Library/Homebrew/test/system_command_spec.rb b/Library/Homebrew/test/system_command_spec.rb index 7eefe508fa..1884f39049 100644 --- a/Library/Homebrew/test/system_command_spec.rb +++ b/Library/Homebrew/test/system_command_spec.rb @@ -275,7 +275,7 @@ RSpec.describe SystemCommand do FileUtils.chmod "+x", path/"tool" - expect(described_class.run("tool", env: { "PATH" => path }).stdout).to include "Hello, world!" + expect(described_class.run("tool", env: { "PATH" => path.to_s }).stdout).to include "Hello, world!" end end diff --git a/Library/Homebrew/test/tab_spec.rb b/Library/Homebrew/test/tab_spec.rb index 594e9c7747..c3dc4a1a23 100644 --- a/Library/Homebrew/test/tab_spec.rb +++ b/Library/Homebrew/test/tab_spec.rb @@ -241,7 +241,7 @@ RSpec.describe Tab do tab = described_class.from_file(path) source_path = "/usr/local/Library/Taps/homebrew/homebrew-core/Formula/foo.rb" runtime_dependencies = [{ "full_name" => "foo", "version" => "1.0" }] - changed_files = %w[INSTALL_RECEIPT.json bin/foo] + changed_files = %w[INSTALL_RECEIPT.json bin/foo].map { Pathname.new(_1) } expect(tab.used_options.sort).to eq(used_options.sort) expect(tab.unused_options.sort).to eq(unused_options.sort) @@ -271,7 +271,7 @@ RSpec.describe Tab do tab = described_class.from_file_content(path.read, path) source_path = "/usr/local/Library/Taps/homebrew/homebrew-core/Formula/foo.rb" runtime_dependencies = [{ "full_name" => "foo", "version" => "1.0" }] - changed_files = %w[INSTALL_RECEIPT.json bin/foo] + changed_files = %w[INSTALL_RECEIPT.json bin/foo].map { Pathname.new(_1) } expect(tab.used_options.sort).to eq(used_options.sort) expect(tab.unused_options.sort).to eq(unused_options.sort) diff --git a/Library/Homebrew/test/utils/analytics_spec.rb b/Library/Homebrew/test/utils/analytics_spec.rb index 4428b1423a..c221af0d6f 100644 --- a/Library/Homebrew/test/utils/analytics_spec.rb +++ b/Library/Homebrew/test/utils/analytics_spec.rb @@ -184,7 +184,7 @@ RSpec.describe Utils::Analytics do end specify "::table_output" do - results = { ack: 10, wget: 100 } + results = { "ack" => 10, "wget" => 100 } expect { described_class.table_output("install", "30", results) } .to output(/110 | 100.00%/).to_stdout .and not_to_output.to_stderr diff --git a/Library/Homebrew/test/utils/inreplace_spec.rb b/Library/Homebrew/test/utils/inreplace_spec.rb index 3014f1b789..05951ae3fa 100644 --- a/Library/Homebrew/test/utils/inreplace_spec.rb +++ b/Library/Homebrew/test/utils/inreplace_spec.rb @@ -86,7 +86,7 @@ RSpec.describe Utils::Inreplace do it "raises error if there is no old value" do expect do described_class.inreplace_pairs(file.path, [[nil, "f"]]) - end.to raise_error(Utils::Inreplace::Error) + end.to raise_error(TypeError) end it "substitutes returned string but not file when `read_only_run: true`" do diff --git a/Library/Homebrew/unpack_strategy/zip.rb b/Library/Homebrew/unpack_strategy/zip.rb index 28e413e00a..cbc39ba3f2 100644 --- a/Library/Homebrew/unpack_strategy/zip.rb +++ b/Library/Homebrew/unpack_strategy/zip.rb @@ -36,7 +36,7 @@ module UnpackStrategy quiet_flags = verbose ? [] : ["-qq"] result = system_command! "unzip", args: [*quiet_flags, "-o", path, "-d", unpack_dir], - env: { "PATH" => PATH.new(unzip&.opt_bin, ENV.fetch("PATH")) }, + env: { "PATH" => PATH.new(unzip&.opt_bin, ENV.fetch("PATH")).to_s }, verbose:, print_stderr: false diff --git a/Library/Homebrew/utils/analytics.rb b/Library/Homebrew/utils/analytics.rb index d9136a168c..2ac747df12 100644 --- a/Library/Homebrew/utils/analytics.rb +++ b/Library/Homebrew/utils/analytics.rb @@ -360,7 +360,7 @@ module Utils nil end - sig { returns(T::Hash[Symbol, String]) } + sig { returns(T::Hash[Symbol, T.any(T::Boolean, String)]) } def default_package_tags cache[:default_package_tags] ||= begin # Only display default prefixes to reduce cardinality and improve privacy