From a850ba2aa33894775dd35c726ab72d06a927be69 Mon Sep 17 00:00:00 2001 From: Issy Long Date: Mon, 6 Jan 2025 00:12:03 +0000 Subject: [PATCH] Bump more files to Sorbet `typed: strict` --- Library/Homebrew/api/formula.rb | 9 +-- Library/Homebrew/bundle_version.rb | 8 ++- Library/Homebrew/cask_dependent.rb | 66 ++++++++++++------- Library/Homebrew/dev-cmd/bump-cask-pr.rb | 4 +- Library/Homebrew/formula_info.rb | 19 +++++- Library/Homebrew/utils/inreplace.rb | 14 +++- Library/Homebrew/utils/repology.rb | 14 +++- .../utils/ruby_check_version_script.rb | 4 +- 8 files changed, 94 insertions(+), 44 deletions(-) diff --git a/Library/Homebrew/api/formula.rb b/Library/Homebrew/api/formula.rb index 0baaa94e9dd06..d905bb4c85bb6 100644 --- a/Library/Homebrew/api/formula.rb +++ b/Library/Homebrew/api/formula.rb @@ -1,4 +1,4 @@ -# typed: true # rubocop:todo Sorbet/StrictSigil +# typed: strict # frozen_string_literal: true require "extend/cachable" @@ -15,7 +15,7 @@ module Formula private_class_method :cache - sig { params(name: String).returns(Hash) } + sig { params(name: String).returns(T::Hash[String, T.untyped]) } def self.fetch(name) Homebrew::API.fetch "formula/#{name}.json" end @@ -41,6 +41,7 @@ def self.source_download(formula) end end + sig { returns(Pathname) } def self.cached_json_file_path if Homebrew::API.internal_json_v3? HOMEBREW_CACHE_API/INTERNAL_V3_API_FILENAME @@ -75,7 +76,7 @@ def self.download_and_cache_data! end private_class_method :download_and_cache_data! - sig { returns(T::Hash[String, Hash]) } + sig { returns(T::Hash[String, T.untyped]) } def self.all_formulae unless cache.key?("formulae") json_updated = download_and_cache_data! @@ -105,7 +106,7 @@ def self.all_renames cache["renames"] end - sig { returns(Hash) } + sig { returns(T::Hash[String, T.untyped]) } def self.tap_migrations # Not sure that we need to reload here. unless cache.key?("tap_migrations") diff --git a/Library/Homebrew/bundle_version.rb b/Library/Homebrew/bundle_version.rb index 065e3098ba61c..8ebcf966fbeb8 100644 --- a/Library/Homebrew/bundle_version.rb +++ b/Library/Homebrew/bundle_version.rb @@ -1,4 +1,4 @@ -# typed: true # rubocop:todo Sorbet/StrictSigil +# typed: strict # frozen_string_literal: true require "system_command" @@ -51,14 +51,15 @@ def initialize(short_version, version) # Remove version from short version, if present. short_version = short_version&.sub(/\s*\(#{Regexp.escape(version)}\)\Z/, "") if version - @short_version = short_version.presence - @version = version.presence + @short_version = T.let(short_version.presence, T.nilable(String)) + @version = T.let(version.presence, T.nilable(String)) return if @short_version || @version raise ArgumentError, "`short_version` and `version` cannot both be `nil` or empty" end + sig { params(other: BundleVersion).returns(T.any(Integer, NilClass)) } def <=>(other) return super unless instance_of?(other.class) @@ -82,6 +83,7 @@ def <=>(other) difference end + sig { params(other: BundleVersion).returns(T::Boolean) } def ==(other) instance_of?(other.class) && short_version == other.short_version && version == other.version end diff --git a/Library/Homebrew/cask_dependent.rb b/Library/Homebrew/cask_dependent.rb index cdea653623951..2f436860941b5 100644 --- a/Library/Homebrew/cask_dependent.rb +++ b/Library/Homebrew/cask_dependent.rb @@ -1,4 +1,4 @@ -# typed: true # rubocop:todo Sorbet/StrictSigil +# typed: strict # frozen_string_literal: true require "requirement" @@ -12,66 +12,82 @@ class Requirement < ::Requirement end end + sig { returns(Cask::Cask) } attr_reader :cask + sig { params(cask: Cask::Cask).void } def initialize(cask) - @cask = cask + @cask = T.let(cask, Cask::Cask) end + sig { returns(String) } def name @cask.token end + sig { returns(String) } def full_name @cask.full_name end + sig { returns(T::Array[Dependency]) } def runtime_dependencies deps.flat_map { |dep| [dep, *dep.to_formula.runtime_dependencies] }.uniq end + sig { returns(T::Array[Dependency]) } def deps - @deps ||= @cask.depends_on.formula.map do |f| - Dependency.new f - end + @deps ||= T.let( + @cask.depends_on.formula.map do |f| + Dependency.new f + end, + T.nilable(T::Array[Dependency]), + ) end + sig { returns(T::Array[Requirement]) } def requirements - @requirements ||= begin - requirements = [] - dsl_reqs = @cask.depends_on + @requirements ||= T.let( + begin + requirements = [] + dsl_reqs = @cask.depends_on - dsl_reqs.arch&.each do |arch| - arch = if arch[:bits] == 64 - if arch[:type] == :intel - :x86_64 + dsl_reqs.arch&.each do |arch| + arch = if arch[:bits] == 64 + if arch[:type] == :intel + :x86_64 + else + :"#{arch[:type]}64" + end + elsif arch[:type] == :intel && arch[:bits] == 32 + :i386 else - :"#{arch[:type]}64" + arch[:type] end - elsif arch[:type] == :intel && arch[:bits] == 32 - :i386 - else - arch[:type] + requirements << ArchRequirement.new([arch]) + end + dsl_reqs.cask.each do |cask_ref| + requirements << CaskDependent::Requirement.new([{ cask: cask_ref }]) end - requirements << ArchRequirement.new([arch]) - end - dsl_reqs.cask.each do |cask_ref| - requirements << CaskDependent::Requirement.new([{ cask: cask_ref }]) - end - requirements << dsl_reqs.macos if dsl_reqs.macos + requirements << dsl_reqs.macos if dsl_reqs.macos - requirements - end + requirements + end, + T.nilable(T::Array[Requirement]), + ) end + sig { params(block: T.proc.returns(T::Array[Dependency])).returns(T::Array[Requirement]) } def recursive_dependencies(&block) Dependency.expand(self, &block) end + sig { params(block: T.proc.returns(T::Array[Requirement])).returns(T::Array[Requirement]) } def recursive_requirements(&block) Requirement.expand(self, &block) end + sig { returns(T::Boolean) } def any_version_installed? @cask.installed? end diff --git a/Library/Homebrew/dev-cmd/bump-cask-pr.rb b/Library/Homebrew/dev-cmd/bump-cask-pr.rb index 579e9db915b18..a46968cf83d06 100644 --- a/Library/Homebrew/dev-cmd/bump-cask-pr.rb +++ b/Library/Homebrew/dev-cmd/bump-cask-pr.rb @@ -186,8 +186,8 @@ def shortened_version(version, cask:) cask: Cask::Cask, new_hash: T.any(NilClass, String, Symbol), new_version: BumpVersionParser, - replacement_pairs: T::Array[[T.any(Regexp, String), T.any(Regexp, String)]], - ).returns(T::Array[[T.any(Regexp, String), T.any(Regexp, String)]]) + replacement_pairs: T::Array[[T.any(Regexp, String), T.any(Pathname, String)]], + ).returns(T::Array[[T.any(Regexp, String), T.any(Pathname, String)]]) } def replace_version_and_checksum(cask, new_hash, new_version, replacement_pairs) # When blocks are absent, arch is not relevant. For consistency, we simulate the arm architecture. diff --git a/Library/Homebrew/formula_info.rb b/Library/Homebrew/formula_info.rb index 7ec8734e4e5d4..56be071d19ec4 100644 --- a/Library/Homebrew/formula_info.rb +++ b/Library/Homebrew/formula_info.rb @@ -1,17 +1,20 @@ -# typed: true # rubocop:todo Sorbet/StrictSigil +# typed: strict # frozen_string_literal: true # Formula information drawn from an external `brew info --json` call. class FormulaInfo # The whole info structure parsed from the JSON. + sig { returns(T::Hash[String, T.untyped]) } attr_accessor :info + sig { params(info: T::Hash[String, T.untyped]).void } def initialize(info) - @info = info + @info = T.let(info, T::Hash[String, T.untyped]) end # Looks up formula on disk and reads its info. # Returns nil if formula is absent or if there was an error reading it. + sig { params(name: Pathname).returns(T.nilable(FormulaInfo)) } def self.lookup(name) json = Utils.popen_read( *HOMEBREW_RUBY_EXEC_ARGS, @@ -27,12 +30,16 @@ def self.lookup(name) FormulaInfo.new(JSON.parse(json)[0]) end + sig { returns(T::Array[String]) } def bottle_tags return [] unless info["bottle"]["stable"] info["bottle"]["stable"]["files"].keys end + sig { + params(my_bottle_tag: T.any(Utils::Bottles::Tag, T.nilable(String))).returns(T.nilable(T::Hash[String, String])) + } def bottle_info(my_bottle_tag = Utils::Bottles.tag) tag_s = my_bottle_tag.to_s return unless info["bottle"]["stable"] @@ -43,29 +50,35 @@ def bottle_info(my_bottle_tag = Utils::Bottles.tag) { "url" => btl_info["url"], "sha256" => btl_info["sha256"] } end + sig { returns(T.nilable(T::Hash[String, String])) } def bottle_info_any bottle_info(any_bottle_tag) end + sig { returns(T.nilable(String)) } def any_bottle_tag tag = Utils::Bottles.tag.to_s # Prefer native bottles as a convenience for download caching bottle_tags.include?(tag) ? tag : bottle_tags.first end + sig { params(spec_type: Symbol).returns(Version) } def version(spec_type) version_str = info["versions"][spec_type.to_s] - version_str && Version.new(version_str) + Version.new(version_str) end + sig { params(spec_type: Symbol).returns(PkgVersion) } def pkg_version(spec_type = :stable) PkgVersion.new(version(spec_type), revision) end + sig { returns(Integer) } def revision info["revision"] end + sig { params(str: String).void } def self.force_utf8!(str) str.force_encoding("UTF-8") if str.respond_to?(:force_encoding) end diff --git a/Library/Homebrew/utils/inreplace.rb b/Library/Homebrew/utils/inreplace.rb index 3d380301d1c83..360b90be72622 100644 --- a/Library/Homebrew/utils/inreplace.rb +++ b/Library/Homebrew/utils/inreplace.rb @@ -1,4 +1,4 @@ -# typed: true # rubocop:todo Sorbet/StrictSigil +# typed: strict # frozen_string_literal: true require "utils/string_inreplace_extension" @@ -8,6 +8,7 @@ module Utils module Inreplace # Error during text replacement. class Error < RuntimeError + sig { params(errors: T::Hash[String, T::Array[String]]).void } def initialize(errors) formatted_errors = errors.reduce(+"inreplace failed\n") do |s, (path, errs)| s << "#{path}:\n" << errs.map { |e| " #{e}\n" }.join @@ -82,12 +83,19 @@ def self.inreplace(paths, before = nil, after = nil, audit_result: true, global: raise Utils::Inreplace::Error, errors if errors.present? end + sig { + params( + path: T.any(String, Pathname), + replacement_pairs: T::Array[[T.any(Regexp, Pathname, String), T.any(Pathname, String)]], + read_only_run: T::Boolean, + silent: T::Boolean, + ).returns(String) + } def self.inreplace_pairs(path, replacement_pairs, read_only_run: false, silent: false) str = File.binread(path) contents = StringInreplaceExtension.new(str) replacement_pairs.each do |old, new| - ohai "replace #{old.inspect} with #{new.inspect}" unless silent - unless old + if old.blank? contents.errors << "No old value for new value #{new}! Did you pass the wrong arguments?" next end diff --git a/Library/Homebrew/utils/repology.rb b/Library/Homebrew/utils/repology.rb index a382f47f5e408..c2681327d2507 100644 --- a/Library/Homebrew/utils/repology.rb +++ b/Library/Homebrew/utils/repology.rb @@ -1,4 +1,4 @@ -# typed: true # rubocop:todo Sorbet/StrictSigil +# typed: strict # frozen_string_literal: true require "utils/curl" @@ -10,6 +10,7 @@ module Repology MAX_PAGINATION = 15 private_constant :MAX_PAGINATION + sig { params(last_package_in_response: T.nilable(String), repository: String).returns(T::Hash[String, T.untyped]) } def self.query_api(last_package_in_response = "", repository:) last_package_in_response += "/" if last_package_in_response.present? url = "https://repology.org/api/v1/projects/#{last_package_in_response}?inrepo=#{repository}&outdated=1" @@ -27,6 +28,7 @@ def self.query_api(last_package_in_response = "", repository:) raise end + sig { params(name: String, repository: String).returns(T.nilable(T::Hash[String, T.untyped])) } def self.single_package_query(name, repository:) url = "https://repology.org/api/v1/project/#{name}" @@ -47,6 +49,13 @@ def self.single_package_query(name, repository:) nil end + sig { + params( + limit: T.nilable(Integer), + last_package: T.nilable(String), + repository: String, + ).returns(T::Hash[String, T.untyped]) + } def self.parse_api_response(limit = nil, last_package = "", repository:) package_term = case repository when HOMEBREW_CORE @@ -80,6 +89,7 @@ def self.parse_api_response(limit = nil, last_package = "", repository:) outdated_packages.sort.to_h end + sig { params(repositories: T::Array[String]).returns(T.any(String, Version)) } def self.latest_version(repositories) # The status is "unique" when the package is present only in Homebrew, so # Repology has no way of knowing if the package is up-to-date. @@ -97,6 +107,6 @@ def self.latest_version(repositories) # scheme return "no latest version" if latest_version.blank? - Version.new(latest_version["version"]) + Version.new(T.must(latest_version["version"])) end end diff --git a/Library/Homebrew/utils/ruby_check_version_script.rb b/Library/Homebrew/utils/ruby_check_version_script.rb index 8a3471269c1a5..a2aaa91733fd5 100755 --- a/Library/Homebrew/utils/ruby_check_version_script.rb +++ b/Library/Homebrew/utils/ruby_check_version_script.rb @@ -1,8 +1,8 @@ #!/usr/bin/env ruby -# typed: true # rubocop:todo Sorbet/StrictSigil +# typed: strict # frozen_string_literal: true -HOMEBREW_REQUIRED_RUBY_VERSION = ARGV.first.freeze +HOMEBREW_REQUIRED_RUBY_VERSION = T.let(ARGV.first.freeze, String) raise "No Ruby version passed!" if HOMEBREW_REQUIRED_RUBY_VERSION.to_s.empty? require "rubygems"