Merge pull request #20430 from Homebrew/use-api-helper-methods

Use API helper methods to manage toggling the internal API
This commit is contained in:
Mike McQuaid 2025-08-13 07:50:45 +00:00 committed by GitHub
commit 2525bd2b37
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 136 additions and 42 deletions

View File

@ -4,6 +4,7 @@
require "api/analytics" require "api/analytics"
require "api/cask" require "api/cask"
require "api/formula" require "api/formula"
require "api/internal"
require "base64" require "base64"
module Homebrew module Homebrew
@ -151,6 +152,30 @@ module Homebrew
json.except("variations") json.except("variations")
end end
sig { params(download_queue: T.nilable(DownloadQueue), stale_seconds: Integer).void }
def self.fetch_api_files!(download_queue: nil, stale_seconds: Homebrew::EnvConfig.api_auto_update_secs.to_i)
if Homebrew::EnvConfig.use_internal_api?
Homebrew::API::Internal.fetch_formula_api!(download_queue:, stale_seconds:)
Homebrew::API::Internal.fetch_cask_api!(download_queue:, stale_seconds:)
else
Homebrew::API::Formula.fetch_api!(download_queue:, stale_seconds:)
Homebrew::API::Formula.fetch_tap_migrations!(download_queue:, stale_seconds:)
Homebrew::API::Cask.fetch_api!(download_queue:, stale_seconds:)
Homebrew::API::Cask.fetch_tap_migrations!(download_queue:, stale_seconds:)
end
end
sig { void }
def self.write_names_and_aliases
if Homebrew::EnvConfig.use_internal_api?
Homebrew::API::Internal.write_formula_names_and_aliases
Homebrew::API::Internal.write_cask_names
else
Homebrew::API::Formula.write_names_and_aliases
Homebrew::API::Cask.write_names
end
end
sig { params(names: T::Array[String], type: String, regenerate: T::Boolean).returns(T::Boolean) } sig { params(names: T::Array[String], type: String, regenerate: T::Boolean).returns(T::Boolean) }
def self.write_names_file!(names, type, regenerate:) def self.write_names_file!(names, type, regenerate:)
names_path = HOMEBREW_CACHE_API/"#{type}_names.txt" names_path = HOMEBREW_CACHE_API/"#{type}_names.txt"
@ -216,6 +241,69 @@ module Homebrew
Tap.fetch(org, repo) Tap.fetch(org, repo)
end end
sig { returns(T::Array[String]) }
def self.formula_names
if Homebrew::EnvConfig.use_internal_api?
Homebrew::API::Internal.formula_arrays.keys
else
Homebrew::API::Formula.all_formulae.keys
end
end
sig { returns(T::Hash[String, String]) }
def self.formula_aliases
if Homebrew::EnvConfig.use_internal_api?
Homebrew::API::Internal.formula_aliases
else
Homebrew::API::Formula.all_aliases
end
end
sig { returns(T::Hash[String, String]) }
def self.formula_renames
if Homebrew::EnvConfig.use_internal_api?
Homebrew::API::Internal.formula_renames
else
Homebrew::API::Formula.all_renames
end
end
sig { returns(T::Hash[String, String]) }
def self.formula_tap_migrations
if Homebrew::EnvConfig.use_internal_api?
Homebrew::API::Internal.formula_tap_migrations
else
Homebrew::API::Formula.tap_migrations
end
end
sig { returns(T::Array[String]) }
def self.cask_tokens
if Homebrew::EnvConfig.use_internal_api?
Homebrew::API::Internal.cask_hashes.keys
else
Homebrew::API::Cask.all_casks.keys
end
end
sig { returns(T::Hash[String, String]) }
def self.cask_renames
if Homebrew::EnvConfig.use_internal_api?
Homebrew::API::Internal.cask_renames
else
Homebrew::API::Cask.all_renames
end
end
sig { returns(T::Hash[String, String]) }
def self.cask_tap_migrations
if Homebrew::EnvConfig.use_internal_api?
Homebrew::API::Internal.cask_tap_migrations
else
Homebrew::API::Cask.tap_migrations
end
end
end end
sig { params(block: T.proc.returns(T.untyped)).returns(T.untyped) } sig { params(block: T.proc.returns(T.untyped)).returns(T.untyped) }

View File

@ -95,10 +95,7 @@ begin
require "api/cask" require "api/cask"
download_queue = Homebrew::DownloadQueue.new download_queue = Homebrew::DownloadQueue.new
stale_seconds = 86400 # 1 day stale_seconds = 86400 # 1 day
Homebrew::API::Formula.fetch_api!(download_queue:, stale_seconds:) Homebrew::API.fetch_api_files!(download_queue:, stale_seconds:)
Homebrew::API::Formula.fetch_tap_migrations!(download_queue:, stale_seconds:)
Homebrew::API::Cask.fetch_api!(download_queue:, stale_seconds:)
Homebrew::API::Cask.fetch_tap_migrations!(download_queue:, stale_seconds:)
begin begin
download_queue.fetch download_queue.fetch
ensure ensure

View File

@ -306,8 +306,8 @@ module Cask
return if Homebrew::EnvConfig.no_install_from_api? return if Homebrew::EnvConfig.no_install_from_api?
return unless ref.is_a?(String) return unless ref.is_a?(String)
return unless (token = ref[HOMEBREW_DEFAULT_TAP_CASK_REGEX, :token]) return unless (token = ref[HOMEBREW_DEFAULT_TAP_CASK_REGEX, :token])
if !Homebrew::API::Cask.all_casks.key?(token) && if Homebrew::API.cask_tokens.exclude?(token) &&
!Homebrew::API::Cask.all_renames.key?(token) !Homebrew::API.cask_renames.key?(token)
return return
end end

View File

@ -207,13 +207,13 @@ module Homebrew
if formula_path.exist? || if formula_path.exist? ||
(!Homebrew::EnvConfig.no_install_from_api? && (!Homebrew::EnvConfig.no_install_from_api? &&
!CoreTap.instance.installed? && !CoreTap.instance.installed? &&
Homebrew::API::Formula.all_formulae.key?(path.basename.to_s)) Homebrew::API.formula_names.include?(path.basename.to_s))
paths << formula_path paths << formula_path
end end
if cask_path.exist? || if cask_path.exist? ||
(!Homebrew::EnvConfig.no_install_from_api? && (!Homebrew::EnvConfig.no_install_from_api? &&
!CoreCaskTap.instance.installed? && !CoreCaskTap.instance.installed? &&
Homebrew::API::Cask.all_casks.key?(path.basename.to_s)) Homebrew::API.cask_tokens.include?(path.basename.to_s))
paths << cask_path paths << cask_path
end end

View File

@ -134,10 +134,7 @@ module Homebrew
end end
# Check if we can parse the JSON and do any Ruby-side follow-up. # Check if we can parse the JSON and do any Ruby-side follow-up.
unless Homebrew::EnvConfig.no_install_from_api? Homebrew::API.write_names_and_aliases unless Homebrew::EnvConfig.no_install_from_api?
Homebrew::API::Formula.write_names_and_aliases
Homebrew::API::Cask.write_names
end
Homebrew.failed = true if ENV["HOMEBREW_UPDATE_FAILED"] Homebrew.failed = true if ENV["HOMEBREW_UPDATE_FAILED"]
return if Homebrew::EnvConfig.disable_load_formula? return if Homebrew::EnvConfig.disable_load_formula?

View File

@ -110,7 +110,7 @@ module Homebrew
raise TapUnavailableError, "#{tap_match[:user]}/#{tap_match[:repo]}" raise TapUnavailableError, "#{tap_match[:user]}/#{tap_match[:repo]}"
elsif cask || core_cask_path?(path) elsif cask || core_cask_path?(path)
if !CoreCaskTap.instance.installed? && Homebrew::API::Cask.all_casks.key?(name) if !CoreCaskTap.instance.installed? && Homebrew::API.cask_tokens.include?(name)
command = "brew tap --force #{CoreCaskTap.instance.name}" command = "brew tap --force #{CoreCaskTap.instance.name}"
action = "tap #{CoreCaskTap.instance.name}" action = "tap #{CoreCaskTap.instance.name}"
else else
@ -119,7 +119,7 @@ module Homebrew
end end
elsif core_formula_path?(path) && elsif core_formula_path?(path) &&
!CoreTap.instance.installed? && !CoreTap.instance.installed? &&
Homebrew::API::Formula.all_formulae.key?(name) Homebrew::API.formula_names.include?(name)
command = "brew tap --force #{CoreTap.instance.name}" command = "brew tap --force #{CoreTap.instance.name}"
action = "tap #{CoreTap.instance.name}" action = "tap #{CoreTap.instance.name}"
else else

View File

@ -662,5 +662,10 @@ module Homebrew
[concurrency, 1].max [concurrency, 1].max
end end
sig { returns(T::Boolean) }
def use_internal_api?
ENV["HOMEBREW_USE_INTERNAL_API"].present?
end
end end
end end

View File

@ -875,9 +875,9 @@ module Formulary
return if Homebrew::EnvConfig.no_install_from_api? return if Homebrew::EnvConfig.no_install_from_api?
return unless ref.is_a?(String) return unless ref.is_a?(String)
return unless (name = ref[HOMEBREW_DEFAULT_TAP_FORMULA_REGEX, :name]) return unless (name = ref[HOMEBREW_DEFAULT_TAP_FORMULA_REGEX, :name])
if !Homebrew::API::Formula.all_formulae.key?(name) && if Homebrew::API.formula_names.exclude?(name) &&
!Homebrew::API::Formula.all_aliases.key?(name) && !Homebrew::API.formula_aliases.key?(name) &&
!Homebrew::API::Formula.all_renames.key?(name) !Homebrew::API.formula_renames.key?(name)
return return
end end

View File

@ -1345,13 +1345,18 @@ class CoreTap < AbstractCoreTap
end, T.nilable(Pathname)) end, T.nilable(Pathname))
end end
sig { override.params(name: String).returns(Pathname) } sig { params(name: String).returns(String) }
def new_formula_path(name) def new_formula_subdirectory(name)
formula_subdir = if name.start_with?("lib") if name.start_with?("lib")
"lib" "lib"
else else
name[0].to_s name[0].to_s
end end
end
sig { override.params(name: String).returns(Pathname) }
def new_formula_path(name)
formula_subdir = new_formula_subdirectory(name)
return super unless (formula_dir/formula_subdir).directory? return super unless (formula_dir/formula_subdir).directory?
@ -1373,7 +1378,7 @@ class CoreTap < AbstractCoreTap
ensure_installed! ensure_installed!
super super
else else
Homebrew::API::Formula.all_renames Homebrew::API.formula_renames
end, end,
T.nilable(T::Hash[String, String]), T.nilable(T::Hash[String, String]),
) )
@ -1386,7 +1391,7 @@ class CoreTap < AbstractCoreTap
ensure_installed! ensure_installed!
super super
else else
Homebrew::API::Formula.tap_migrations Homebrew::API.formula_tap_migrations
end, end,
T.nilable(T::Hash[String, T.untyped]), T.nilable(T::Hash[String, T.untyped]),
) )
@ -1443,7 +1448,7 @@ class CoreTap < AbstractCoreTap
if Homebrew::EnvConfig.no_install_from_api? if Homebrew::EnvConfig.no_install_from_api?
super super
else else
Homebrew::API::Formula.all_aliases Homebrew::API.formula_aliases
end, end,
T.nilable(T::Hash[String, String]), T.nilable(T::Hash[String, String]),
) )
@ -1460,7 +1465,7 @@ class CoreTap < AbstractCoreTap
def formula_names def formula_names
return super if Homebrew::EnvConfig.no_install_from_api? return super if Homebrew::EnvConfig.no_install_from_api?
Homebrew::API::Formula.all_formulae.keys Homebrew::API.formula_names
end end
sig { override.returns(T::Hash[String, Pathname]) } sig { override.returns(T::Hash[String, Pathname]) }
@ -1469,13 +1474,12 @@ class CoreTap < AbstractCoreTap
@formula_files_by_name ||= T.let( @formula_files_by_name ||= T.let(
begin begin
tap_path = path.to_s formula_directory_path = formula_dir.to_s
Homebrew::API::Formula.all_formulae.each_with_object({}) do |item, hash| Homebrew::API.formula_names.each_with_object({}) do |name, hash|
name, formula_hash = item
# If there's more than one item with the same path: use the longer one to prioritise more specific results. # If there's more than one item with the same path: use the longer one to prioritise more specific results.
existing_path = hash[name] existing_path = hash[name]
# Pathname equivalent is slow in a tight loop # Pathname equivalent is slow in a tight loop
new_path = File.join(tap_path, formula_hash.fetch("ruby_source_path")) new_path = File.join(formula_directory_path, new_formula_subdirectory(name), "#{name.downcase}.rb")
hash[name] = Pathname(new_path) if existing_path.nil? || existing_path.to_s.length < new_path.length hash[name] = Pathname(new_path) if existing_path.nil? || existing_path.to_s.length < new_path.length
end end
end, end,
@ -1500,14 +1504,18 @@ class CoreCaskTap < AbstractCoreTap
true true
end end
sig { override.params(token: String).returns(Pathname) } sig { params(token: String).returns(String) }
def new_cask_path(token) def new_cask_subdirectory(token)
cask_subdir = if token.start_with?("font-") if token.start_with?("font-")
"font/font-#{token.delete_prefix("font-")[0]}" "font/font-#{token.delete_prefix("font-")[0]}"
else else
token[0].to_s token[0].to_s
end end
cask_dir/cask_subdir/"#{token.downcase}.rb" end
sig { override.params(token: String).returns(Pathname) }
def new_cask_path(token)
cask_dir/new_cask_subdirectory(token)/"#{token.downcase}.rb"
end end
sig { override.returns(T::Array[Pathname]) } sig { override.returns(T::Array[Pathname]) }
@ -1521,7 +1529,7 @@ class CoreCaskTap < AbstractCoreTap
def cask_tokens def cask_tokens
return super if Homebrew::EnvConfig.no_install_from_api? return super if Homebrew::EnvConfig.no_install_from_api?
Homebrew::API::Cask.all_casks.keys Homebrew::API.cask_tokens
end end
sig { override.returns(T::Hash[String, Pathname]) } sig { override.returns(T::Hash[String, Pathname]) }
@ -1530,13 +1538,12 @@ class CoreCaskTap < AbstractCoreTap
@cask_files_by_name ||= T.let( @cask_files_by_name ||= T.let(
begin begin
tap_path = path.to_s cask_directory_path = cask_dir.to_s
Homebrew::API::Cask.all_casks.each_with_object({}) do |item, hash| Homebrew::API.cask_tokens.each_with_object({}) do |name, hash|
name, cask_hash = item
# If there's more than one item with the same path: use the longer one to prioritise more specific results. # If there's more than one item with the same path: use the longer one to prioritise more specific results.
existing_path = hash[name] existing_path = hash[name]
# Pathname equivalent is slow in a tight loop # Pathname equivalent is slow in a tight loop
new_path = File.join(tap_path, cask_hash.fetch("ruby_source_path")) new_path = File.join(cask_directory_path, new_cask_subdirectory(name), "#{name.downcase}.rb")
hash[name] = Pathname(new_path) if existing_path.nil? || existing_path.to_s.length < new_path.length hash[name] = Pathname(new_path) if existing_path.nil? || existing_path.to_s.length < new_path.length
end end
end, end,
@ -1550,7 +1557,7 @@ class CoreCaskTap < AbstractCoreTap
if Homebrew::EnvConfig.no_install_from_api? if Homebrew::EnvConfig.no_install_from_api?
super super
else else
Homebrew::API::Cask.all_renames Homebrew::API.cask_renames
end, end,
T.nilable(T::Hash[String, String]), T.nilable(T::Hash[String, String]),
) )
@ -1562,7 +1569,7 @@ class CoreCaskTap < AbstractCoreTap
if Homebrew::EnvConfig.no_install_from_api? if Homebrew::EnvConfig.no_install_from_api?
super super
else else
Homebrew::API::Cask.tap_migrations Homebrew::API.cask_tap_migrations
end, end,
T.nilable(T::Hash[String, T.untyped]), T.nilable(T::Hash[String, T.untyped]),
) )

View File

@ -68,7 +68,7 @@ module Homebrew
unversioned_name = f.name.gsub(/@.+$/, "") unversioned_name = f.name.gsub(/@.+$/, "")
maybe_paths = Dir.glob("#{f.etc}/#{unversioned_name}*") maybe_paths = Dir.glob("#{f.etc}/#{unversioned_name}*")
excluded_names = Homebrew::API::Formula.all_formulae.keys excluded_names = Homebrew::API.formula_names
maybe_paths = maybe_paths.reject do |path| maybe_paths = maybe_paths.reject do |path|
# Remove extension only if a file # Remove extension only if a file
# (e.g. directory with name "openssl@1.1" will be trimmed to "openssl@1") # (e.g. directory with name "openssl@1.1" will be trimmed to "openssl@1")

View File

@ -329,7 +329,7 @@ module Utils
require "api" require "api"
return unless Homebrew::API::Formula.all_formulae.key? formula.name return unless Homebrew::API.formula_names.include? formula.name
json = Homebrew::API::Formula.formula_json formula.name json = Homebrew::API::Formula.formula_json formula.name
return if json.blank? || json["analytics"].blank? return if json.blank? || json["analytics"].blank?
@ -347,7 +347,7 @@ module Utils
require "api" require "api"
return unless Homebrew::API::Cask.all_casks.key? cask.token return unless Homebrew::API.cask_tokens.include? cask.token
json = Homebrew::API::Cask.cask_json cask.token json = Homebrew::API::Cask.cask_json cask.token
return if json.blank? || json["analytics"].blank? return if json.blank? || json["analytics"].blank?