From 00f960174f351fbb4bedc08b9edc8370867e6887 Mon Sep 17 00:00:00 2001 From: Rylan Polster Date: Wed, 3 Sep 2025 15:30:31 -0400 Subject: [PATCH] Download new API files once per Homebrew instance --- Library/Homebrew/api.rb | 45 +++++++++++++++++++-------- Library/Homebrew/api/cask.rb | 8 ++--- Library/Homebrew/api/formula.rb | 8 ++--- Library/Homebrew/api/internal.rb | 12 +++---- Library/Homebrew/api/json_download.rb | 6 ++-- 5 files changed, 49 insertions(+), 30 deletions(-) diff --git a/Library/Homebrew/api.rb b/Library/Homebrew/api.rb index 6f1bbaad46..65e7f6934a 100644 --- a/Library/Homebrew/api.rb +++ b/Library/Homebrew/api.rb @@ -17,7 +17,7 @@ module Homebrew HOMEBREW_CACHE_API = T.let((HOMEBREW_CACHE/"api").freeze, Pathname) HOMEBREW_CACHE_API_SOURCE = T.let((HOMEBREW_CACHE/"api-source").freeze, Pathname) - TAP_MIGRATIONS_STALE_SECONDS = T.let(86400, Integer) # 1 day + DEFAULT_API_STALE_SECONDS = T.let(86400, Integer) # 1 day sig { params(endpoint: String).returns(T::Hash[String, T.untyped]) } def self.fetch(endpoint) @@ -37,12 +37,25 @@ module Homebrew raise ArgumentError, "Invalid JSON file: #{Tty.underline}#{api_url}#{Tty.reset}" end + sig { params(target: Pathname, stale_seconds: T.nilable(Integer)).returns(T::Boolean) } + def self.skip_download?(target:, stale_seconds:) + return true if Homebrew.running_as_root_but_not_owned_by_root? + return false if !target.exist? || target.empty? + return true unless stale_seconds + + (Time.now - stale_seconds) < target.mtime + end + sig { - params(endpoint: String, target: Pathname, stale_seconds: Integer, download_queue: T.nilable(DownloadQueue)) - .returns([T.any(T::Array[T.untyped], T::Hash[String, T.untyped]), T::Boolean]) + params( + endpoint: String, + target: Pathname, + stale_seconds: T.nilable(Integer), + download_queue: T.nilable(DownloadQueue), + ).returns([T.any(T::Array[T.untyped], T::Hash[String, T.untyped]), T::Boolean]) } def self.fetch_json_api_file(endpoint, target: HOMEBREW_CACHE_API/endpoint, - stale_seconds: Homebrew::EnvConfig.api_auto_update_secs.to_i, download_queue: nil) + stale_seconds: nil, download_queue: nil) # Lazy-load dependency. require "development_tools" @@ -63,12 +76,7 @@ module Homebrew insecure_download = DevelopmentTools.ca_file_substitution_required? || DevelopmentTools.curl_substitution_required? - skip_download = target.exist? && - !target.empty? && - (!Homebrew.auto_update_command? || - (Homebrew::EnvConfig.no_auto_update? && !Homebrew::EnvConfig.force_api_auto_update?) || - ((Time.now - stale_seconds) < target.mtime)) - skip_download ||= Homebrew.running_as_root_but_not_owned_by_root? + skip_download = skip_download?(target:, stale_seconds:) if download_queue unless skip_download @@ -161,17 +169,28 @@ module Homebrew require "download_queue" Homebrew::DownloadQueue.new end - stale_seconds = 86400 # 1 day + + stale_seconds = if ENV["HOMEBREW_API_UPDATED"].present? || + (Homebrew::EnvConfig.no_auto_update? && !Homebrew::EnvConfig.force_api_auto_update?) + nil + elsif Homebrew.auto_update_command? + Homebrew::EnvConfig.api_auto_update_secs.to_i + else + DEFAULT_API_STALE_SECONDS + end 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::Formula.fetch_tap_migrations!(download_queue:, stale_seconds: DEFAULT_API_STALE_SECONDS) Homebrew::API::Cask.fetch_api!(download_queue:, stale_seconds:) - Homebrew::API::Cask.fetch_tap_migrations!(download_queue:, stale_seconds:) + Homebrew::API::Cask.fetch_tap_migrations!(download_queue:, stale_seconds: DEFAULT_API_STALE_SECONDS) end + + ENV["HOMEBREW_API_UPDATED"] = "1" + return unless download_queue begin diff --git a/Library/Homebrew/api/cask.rb b/Library/Homebrew/api/cask.rb index 52c8695dc1..7deb40bd66 100644 --- a/Library/Homebrew/api/cask.rb +++ b/Library/Homebrew/api/cask.rb @@ -75,18 +75,18 @@ module Homebrew end sig { - params(download_queue: T.nilable(::Homebrew::DownloadQueue), stale_seconds: Integer) + params(download_queue: T.nilable(::Homebrew::DownloadQueue), stale_seconds: T.nilable(Integer)) .returns([T.any(T::Array[T.untyped], T::Hash[String, T.untyped]), T::Boolean]) } - def self.fetch_api!(download_queue: nil, stale_seconds: Homebrew::EnvConfig.api_auto_update_secs.to_i) + def self.fetch_api!(download_queue: nil, stale_seconds: nil) Homebrew::API.fetch_json_api_file DEFAULT_API_FILENAME, stale_seconds:, download_queue: end sig { - params(download_queue: T.nilable(::Homebrew::DownloadQueue), stale_seconds: Integer) + params(download_queue: T.nilable(::Homebrew::DownloadQueue), stale_seconds: T.nilable(Integer)) .returns([T.any(T::Array[T.untyped], T::Hash[String, T.untyped]), T::Boolean]) } - def self.fetch_tap_migrations!(download_queue: nil, stale_seconds: Homebrew::API::TAP_MIGRATIONS_STALE_SECONDS) + def self.fetch_tap_migrations!(download_queue: nil, stale_seconds: nil) Homebrew::API.fetch_json_api_file "cask_tap_migrations.jws.json", stale_seconds:, download_queue: end diff --git a/Library/Homebrew/api/formula.rb b/Library/Homebrew/api/formula.rb index 0dfc4cba13..dc24481b10 100644 --- a/Library/Homebrew/api/formula.rb +++ b/Library/Homebrew/api/formula.rb @@ -74,18 +74,18 @@ module Homebrew end sig { - params(download_queue: T.nilable(Homebrew::DownloadQueue), stale_seconds: Integer) + params(download_queue: T.nilable(Homebrew::DownloadQueue), stale_seconds: T.nilable(Integer)) .returns([T.any(T::Array[T.untyped], T::Hash[String, T.untyped]), T::Boolean]) } - def self.fetch_api!(download_queue: nil, stale_seconds: Homebrew::EnvConfig.api_auto_update_secs.to_i) + def self.fetch_api!(download_queue: nil, stale_seconds: nil) Homebrew::API.fetch_json_api_file DEFAULT_API_FILENAME, stale_seconds:, download_queue: end sig { - params(download_queue: T.nilable(Homebrew::DownloadQueue), stale_seconds: Integer) + params(download_queue: T.nilable(Homebrew::DownloadQueue), stale_seconds: T.nilable(Integer)) .returns([T.any(T::Array[T.untyped], T::Hash[String, T.untyped]), T::Boolean]) } - def self.fetch_tap_migrations!(download_queue: nil, stale_seconds: Homebrew::API::TAP_MIGRATIONS_STALE_SECONDS) + def self.fetch_tap_migrations!(download_queue: nil, stale_seconds: nil) Homebrew::API.fetch_json_api_file "formula_tap_migrations.jws.json", stale_seconds:, download_queue: end diff --git a/Library/Homebrew/api/internal.rb b/Library/Homebrew/api/internal.rb index ba5da6fdba..ddc094da26 100644 --- a/Library/Homebrew/api/internal.rb +++ b/Library/Homebrew/api/internal.rb @@ -56,20 +56,20 @@ module Homebrew end sig { - params(download_queue: T.nilable(Homebrew::DownloadQueue), stale_seconds: Integer) + params(download_queue: T.nilable(Homebrew::DownloadQueue), stale_seconds: T.nilable(Integer)) .returns([T::Hash[String, T.untyped], T::Boolean]) } - def self.fetch_formula_api!(download_queue: nil, stale_seconds: Homebrew::EnvConfig.api_auto_update_secs.to_i) - json_contents, updated = (Homebrew::API.fetch_json_api_file formula_endpoint, stale_seconds:, download_queue:) + def self.fetch_formula_api!(download_queue: nil, stale_seconds: nil) + json_contents, updated = Homebrew::API.fetch_json_api_file(formula_endpoint, stale_seconds:, download_queue:) [T.cast(json_contents, T::Hash[String, T.untyped]), updated] end sig { - params(download_queue: T.nilable(Homebrew::DownloadQueue), stale_seconds: Integer) + params(download_queue: T.nilable(Homebrew::DownloadQueue), stale_seconds: T.nilable(Integer)) .returns([T::Hash[String, T.untyped], T::Boolean]) } - def self.fetch_cask_api!(download_queue: nil, stale_seconds: Homebrew::EnvConfig.api_auto_update_secs.to_i) - json_contents, updated = (Homebrew::API.fetch_json_api_file cask_endpoint, stale_seconds:, download_queue:) + def self.fetch_cask_api!(download_queue: nil, stale_seconds: nil) + json_contents, updated = Homebrew::API.fetch_json_api_file(cask_endpoint, stale_seconds:, download_queue:) [T.cast(json_contents, T::Hash[String, T.untyped]), updated] end diff --git a/Library/Homebrew/api/json_download.rb b/Library/Homebrew/api/json_download.rb index e7d5a01b65..96a47c9b8c 100644 --- a/Library/Homebrew/api/json_download.rb +++ b/Library/Homebrew/api/json_download.rb @@ -10,13 +10,13 @@ module Homebrew def initialize(url, name, version, **meta) super @target = T.let(meta.fetch(:target), Pathname) - @stale_seconds = T.let(meta.fetch(:stale_seconds), Integer) + @stale_seconds = T.let(meta[:stale_seconds], T.nilable(Integer)) end sig { override.params(timeout: T.nilable(T.any(Integer, Float))).returns(Pathname) } def fetch(timeout: nil) with_context quiet: quiet? do - Homebrew::API.fetch_json_api_file(url, target: cached_location, stale_seconds: meta.fetch(:stale_seconds)) + Homebrew::API.fetch_json_api_file(url, target: cached_location, stale_seconds: meta[:stale_seconds]) end cached_location end @@ -30,7 +30,7 @@ module Homebrew class JSONDownload include Downloadable - sig { params(url: String, target: Pathname, stale_seconds: Integer).void } + sig { params(url: String, target: Pathname, stale_seconds: T.nilable(Integer)).void } def initialize(url, target:, stale_seconds:) super() @url = T.let(URL.new(url, using: API::JSONDownloadStrategy, target:, stale_seconds:), URL)