diff --git a/Library/Homebrew/api/cask.rb b/Library/Homebrew/api/cask.rb index baaf2f0d8e..17ca86b716 100644 --- a/Library/Homebrew/api/cask.rb +++ b/Library/Homebrew/api/cask.rb @@ -60,7 +60,7 @@ module Homebrew end private :download_and_cache_data! - sig { returns(Hash) } + sig { returns(T::Hash[String, Hash]) } def all_casks unless cache.key?("casks") json_updated = download_and_cache_data! diff --git a/Library/Homebrew/cask/cask_loader.rb b/Library/Homebrew/cask/cask_loader.rb index 4d3cf74051..cf2ac67abb 100644 --- a/Library/Homebrew/cask/cask_loader.rb +++ b/Library/Homebrew/cask/cask_loader.rb @@ -90,10 +90,14 @@ module Cask .returns(T.nilable(T.attached_class)) } def self.try_new(ref, warn: false) - ref = Pathname(ref) if ref.is_a?(String) - return unless ref.is_a?(Pathname) - - path = ref + path = case ref + when String + Pathname(ref) + when Pathname + ref + else + return + end return if %w[.rb .json].exclude?(path.extname) return unless path.expand_path.exist? @@ -110,9 +114,8 @@ module Cask path = Pathname(path).expand_path @token = path.basename(path.extname).to_s - @path = path - @tap = Homebrew::API.tap_from_source_download(path) + @tap = Tap.from_path(path) || Homebrew::API.tap_from_source_download(path) end def load(config:) @@ -191,27 +194,8 @@ module Cask end end - # Loads a cask from a tap path. - class FromTapPathLoader < FromPathLoader - sig { - params(ref: T.any(String, Pathname, Cask, URI::Generic), warn: T::Boolean) - .returns(T.nilable(T.attached_class)) - } - def self.try_new(ref, warn: false) - return unless (loader = super) - - loader unless Tap.from_path(ref).nil? - end - - sig { params(path: T.any(Pathname, String)).void } - def initialize(path) - super(path) - @tap = Tap.from_path(path) - end - end - # Loads a cask from a specific tap. - class FromTapLoader < FromTapPathLoader + class FromTapLoader < FromPathLoader sig { params(ref: T.any(String, Pathname, Cask, URI::Generic), warn: T::Boolean) .returns(T.nilable(T.attached_class)) @@ -225,9 +209,9 @@ module Cask new("#{tap}/#{token}") end - sig { params(tapped_name: String).void } - def initialize(tapped_name) - user, repo, token = tapped_name.split("/", 3) + sig { params(tapped_token: String).void } + def initialize(tapped_token) + user, repo, token = tapped_token.split("/", 3) tap = Tap.fetch(user, repo) cask = CaskLoader.find_cask_in_tap(token, tap) super cask @@ -249,7 +233,7 @@ module Cask def self.try_new(ref, warn: false) ref = ref.to_s - return unless (match = ref.match(HOMEBREW_MAIN_TAP_CASK_REGEX)) + return unless (match = ref.match(HOMEBREW_DEFAULT_TAP_CASK_REGEX)) token = match[:token] @@ -261,7 +245,7 @@ module Cask end # Loads a cask from the default tap path. - class FromDefaultTapPathLoader < FromTapPathLoader + class FromDefaultTapPathLoader < FromPathLoader sig { params(ref: T.any(String, Pathname, Cask, URI::Generic), warn: T::Boolean) .returns(T.nilable(T.attached_class)) @@ -297,7 +281,11 @@ module Cask class FromAPILoader include ILoader - attr_reader :token, :path + sig { returns(String) } + attr_reader :token + + sig { returns(Pathname) } + attr_reader :path sig { returns(T.nilable(Hash)) } attr_reader :from_json @@ -309,12 +297,8 @@ module Cask def self.try_new(ref, warn: false) return if Homebrew::EnvConfig.no_install_from_api? return unless ref.is_a?(String) - - return unless (match = ref.match(HOMEBREW_MAIN_TAP_CASK_REGEX)) - - token = match[:token] - - return unless Homebrew::API::Cask.all_casks.key?(token) + return unless (token = ref[HOMEBREW_DEFAULT_TAP_CASK_REGEX, :token]) + return if !Homebrew::API::Cask.all_casks.key?(token) && !Homebrew::API::Cask.all_renames.key?(token) ref = "#{CoreCaskTap.instance}/#{token}" @@ -330,7 +314,7 @@ module Cask end def load(config:) - json_cask = from_json || Homebrew::API::Cask.all_casks[token] + json_cask = from_json || Homebrew::API::Cask.all_casks.fetch(token) cask_options = { loaded_from_api: true, @@ -480,13 +464,13 @@ module Cask # Loader which tries loading casks from tap paths, failing # if the same token exists in multiple taps. - class FromAmbiguousTapPathLoader < FromTapPathLoader + class FromAmbiguousTapPathLoader < FromPathLoader def self.try_new(ref, warn: false) - case (possible_tap_casks = CaskLoader.tap_paths(ref, warn: warn)).count + case (possible_tap_casks = CaskLoader.tap_paths(ref)).count when 1 new(possible_tap_casks.first) when 2..Float::INFINITY - loaders = possible_tap_casks.map(&FromTapPathLoader.method(:new)) + loaders = possible_tap_casks.map(&FromPathLoader.method(:new)) raise TapCaskAmbiguityError.new(ref, loaders) end end @@ -568,7 +552,6 @@ module Cask FromURILoader, FromAPILoader, FromTapLoader, - FromTapPathLoader, FromPathLoader, FromDefaultTapPathLoader, FromAmbiguousTapPathLoader, @@ -587,7 +570,7 @@ module Cask find_cask_in_tap(token.to_s.downcase, CoreCaskTap.instance) end - def self.tap_paths(token, warn: true) + def self.tap_paths(token) token = token.to_s.downcase Tap.map { |tap| find_cask_in_tap(token, tap) }.select(&:exist?) diff --git a/Library/Homebrew/cask/caskroom.rb b/Library/Homebrew/cask/caskroom.rb index bc3f505df3..272685dc59 100644 --- a/Library/Homebrew/cask/caskroom.rb +++ b/Library/Homebrew/cask/caskroom.rb @@ -56,7 +56,7 @@ module Cask CaskLoader.load(token, config: config) rescue TapCaskAmbiguityError tap_path = CaskLoader.tap_paths(token).first - CaskLoader::FromTapPathLoader.new(tap_path).load(config: config) + CaskLoader::FromPathLoader.new(tap_path).load(config: config) rescue # Don't blow up because of a single unavailable cask. nil diff --git a/Library/Homebrew/cli/named_args.rb b/Library/Homebrew/cli/named_args.rb index 04f81687ba..9b470f4f2e 100644 --- a/Library/Homebrew/cli/named_args.rb +++ b/Library/Homebrew/cli/named_args.rb @@ -256,11 +256,11 @@ module Homebrew paths = [] if formula_path.exist? || - (!CoreTap.instance.installed? && Homebrew::API::Formula.all_formulae.key?(path.basename)) + (!CoreTap.instance.installed? && Homebrew::API::Formula.all_formulae.key?(path.basename.to_s)) paths << formula_path end if cask_path.exist? || - (!CoreCaskTap.instance.installed? && Homebrew::API::Cask.all_casks.key?(path.basename)) + (!CoreCaskTap.instance.installed? && Homebrew::API::Cask.all_casks.key?(path.basename.to_s)) paths << cask_path end diff --git a/Library/Homebrew/sorbet/rbi/upstream.rbi b/Library/Homebrew/sorbet/rbi/upstream.rbi index a00487f95a..7653a8622e 100644 --- a/Library/Homebrew/sorbet/rbi/upstream.rbi +++ b/Library/Homebrew/sorbet/rbi/upstream.rbi @@ -2,3 +2,111 @@ # This file contains temporary definitions for fixes that have # been submitted upstream to https://github.com/sorbet/sorbet. + +# https://github.com/sorbet/sorbet/pull/7678 +class String + sig do + params( + arg0: Integer, + arg1: Integer, + ) + .returns(T.nilable(String)) + end + sig do + params( + arg0: T.any(T::Range[Integer], Regexp), + ) + .returns(T.nilable(String)) + end + sig do + params( + arg0: Regexp, + arg1: Integer, + ) + .returns(T.nilable(String)) + end + sig do + params( + arg0: Regexp, + arg1: T.any(String, Symbol), + ) + .returns(T.nilable(String)) + end + sig do + params( + arg0: String, + ) + .returns(T.nilable(String)) + end + def [](arg0, arg1=T.unsafe(nil)); end + + sig do + params( + arg0: Integer, + arg1: Integer, + ) + .returns(T.nilable(String)) + end + sig do + params( + arg0: T.any(T::Range[Integer], Regexp), + ) + .returns(T.nilable(String)) + end + sig do + params( + arg0: Regexp, + arg1: Integer, + ) + .returns(T.nilable(String)) + end + sig do + params( + arg0: Regexp, + arg1: T.any(String, Symbol), + ) + .returns(T.nilable(String)) + end + sig do + params( + arg0: String, + ) + .returns(T.nilable(String)) + end + def slice!(arg0, arg1=T.unsafe(nil)); end + + sig do + params( + arg0: Integer, + arg1: Integer, + ) + .returns(T.nilable(String)) + end + sig do + params( + arg0: T.any(T::Range[Integer], Regexp), + ) + .returns(T.nilable(String)) + end + sig do + params( + arg0: Regexp, + arg1: Integer, + ) + .returns(T.nilable(String)) + end + sig do + params( + arg0: Regexp, + arg1: T.any(String, Symbol), + ) + .returns(T.nilable(String)) + end + sig do + params( + arg0: String, + ) + .returns(T.nilable(String)) + end + def slice(arg0, arg1=T.unsafe(nil)); end +end diff --git a/Library/Homebrew/tap_constants.rb b/Library/Homebrew/tap_constants.rb index 670821f660..6f102bfcbf 100644 --- a/Library/Homebrew/tap_constants.rb +++ b/Library/Homebrew/tap_constants.rb @@ -5,8 +5,10 @@ HOMEBREW_TAP_FORMULA_REGEX = T.let(%r{^([\w-]+)/([\w-]+)/([\w+-.@]+)$}, Regexp) # Match taps' casks, e.g. `someuser/sometap/somecask` HOMEBREW_TAP_CASK_REGEX = T.let(%r{^([\w-]+)/([\w-]+)/([a-z0-9\-_]+)$}, Regexp) -# Match main cask taps' casks, e.g. `homebrew/cask/somecask` or `somecask` -HOMEBREW_MAIN_TAP_CASK_REGEX = T.let(%r{^(?:[Hh]omebrew/(?:homebrew-)?cask/)?(?[a-z0-9\-_]+)$}, Regexp) +# Match default cask taps' casks, e.g. `homebrew/cask/somecask` or `somecask` +HOMEBREW_DEFAULT_TAP_CASK_REGEX = T.let( + %r{^(?:[Hh]omebrew/(?:homebrew-)?cask/)?(?[a-z0-9\-_]+)$}, Regexp +) # Match taps' directory paths, e.g. `HOMEBREW_LIBRARY/Taps/someuser/sometap` HOMEBREW_TAP_DIR_REGEX = T.let( %r{#{Regexp.escape(HOMEBREW_LIBRARY.to_s)}/Taps/(?[\w-]+)/(?[\w-]+)}, Regexp diff --git a/Library/Homebrew/test/cask/cask_loader_spec.rb b/Library/Homebrew/test/cask/cask_loader_spec.rb index b9c83cbb45..184343dd03 100644 --- a/Library/Homebrew/test/cask/cask_loader_spec.rb +++ b/Library/Homebrew/test/cask/cask_loader_spec.rb @@ -37,13 +37,13 @@ describe Cask::CaskLoader, :cask do it "warns when using the short token" do expect do - expect(described_class.for("version-newest")).to be_a Cask::CaskLoader::FromTapPathLoader + expect(described_class.for("version-newest")).to be_a Cask::CaskLoader::FromPathLoader end.to output(/version-newest was renamed to version-latest/).to_stderr end it "warns when using the full token" do expect do - expect(described_class.for("homebrew/cask/version-newest")).to be_a Cask::CaskLoader::FromTapPathLoader + expect(described_class.for("homebrew/cask/version-newest")).to be_a Cask::CaskLoader::FromPathLoader end.to output(/version-newest was renamed to version-latest/).to_stderr end end