Download tap_migrations.json files from the API

Download the previously stored tap migrations files for homebrew/core
and homebrew/cask from the formulae.brew.sh API.

This adds a much longer stale time (24 hours) to decide whether or not
the migrations files need downloaded from the API in Ruby land.
`brew update` will still update them every time.

Requires https://github.com/Homebrew/brew/pull/15628
Fixes https://github.com/Homebrew/brew/issues/14897
This commit is contained in:
Mike McQuaid 2023-07-05 17:18:12 +01:00
parent a34d46e093
commit 27dda52a5d
No known key found for this signature in database
GPG Key ID: 3338A31AFDB1D829
5 changed files with 44 additions and 27 deletions

View File

@ -34,8 +34,11 @@ module Homebrew
raise ArgumentError, "Invalid JSON file: #{Tty.underline}#{api_url}#{Tty.reset}" raise ArgumentError, "Invalid JSON file: #{Tty.underline}#{api_url}#{Tty.reset}"
end end
sig { params(endpoint: String, target: Pathname).returns([T.any(Array, Hash), T::Boolean]) } sig {
def self.fetch_json_api_file(endpoint, target:) params(endpoint: String, target: Pathname, stale_seconds: Integer).returns([T.any(Array, Hash), T::Boolean])
}
def self.fetch_json_api_file(endpoint, target: HOMEBREW_CACHE_API/endpoint,
stale_seconds: Homebrew::EnvConfig.api_auto_update_secs.to_i)
retry_count = 0 retry_count = 0
url = "#{Homebrew::EnvConfig.api_domain}/#{endpoint}" url = "#{Homebrew::EnvConfig.api_domain}/#{endpoint}"
default_url = "#{HOMEBREW_API_DEFAULT_DOMAIN}/#{endpoint}" default_url = "#{HOMEBREW_API_DEFAULT_DOMAIN}/#{endpoint}"
@ -59,7 +62,7 @@ module Homebrew
!target.empty? && !target.empty? &&
(!Homebrew.auto_update_command? || (!Homebrew.auto_update_command? ||
Homebrew::EnvConfig.no_auto_update? || Homebrew::EnvConfig.no_auto_update? ||
((Time.now - Homebrew::EnvConfig.api_auto_update_secs.to_i) < target.mtime)) ((Time.now - stale_seconds) < target.mtime))
skip_download ||= Homebrew.running_as_root_but_not_owned_by_root? skip_download ||= Homebrew.running_as_root_but_not_owned_by_root?
json_data = begin json_data = begin

View File

@ -43,8 +43,7 @@ module Homebrew
sig { returns(T::Boolean) } sig { returns(T::Boolean) }
def download_and_cache_data! def download_and_cache_data!
json_casks, updated = Homebrew::API.fetch_json_api_file "cask.jws.json", json_casks, updated = Homebrew::API.fetch_json_api_file "cask.jws.json"
target: HOMEBREW_CACHE_API/"cask.jws.json"
cache["renames"] = {} cache["renames"] = {}
cache["casks"] = json_casks.to_h do |json_cask| cache["casks"] = json_casks.to_h do |json_cask|

View File

@ -40,8 +40,7 @@ module Homebrew
sig { returns(T::Boolean) } sig { returns(T::Boolean) }
def download_and_cache_data! def download_and_cache_data!
json_formulae, updated = Homebrew::API.fetch_json_api_file "formula.jws.json", json_formulae, updated = Homebrew::API.fetch_json_api_file "formula.jws.json"
target: HOMEBREW_CACHE_API/"formula.jws.json"
cache["aliases"] = {} cache["aliases"] = {}
cache["renames"] = {} cache["renames"] = {}

View File

@ -781,34 +781,37 @@ EOS
if [[ -z "${HOMEBREW_NO_INSTALL_FROM_API}" ]] if [[ -z "${HOMEBREW_NO_INSTALL_FROM_API}" ]]
then then
mkdir -p "${HOMEBREW_CACHE}/api" local api_cache="${HOMEBREW_CACHE}/api"
mkdir -p "${api_cache}"
for formula_or_cask in formula cask for json in formula cask formula_tap_migrations cask_tap_migrations
do do
if [[ -f "${HOMEBREW_CACHE}/api/${formula_or_cask}.jws.json" ]] local filename="${json}.jws.json"
local cache_path="${api_cache}/${filename}"
if [[ -f "${cache_path}" ]]
then then
INITIAL_JSON_BYTESIZE="$(wc -c "${HOMEBREW_CACHE}"/api/"${formula_or_cask}".jws.json)" INITIAL_JSON_BYTESIZE="$(wc -c "${cache_path}")"
fi fi
JSON_URLS=() JSON_URLS=()
if [[ -n "${HOMEBREW_API_DOMAIN}" && "${HOMEBREW_API_DOMAIN}" != "${HOMEBREW_API_DEFAULT_DOMAIN}" ]] if [[ -n "${HOMEBREW_API_DOMAIN}" && "${HOMEBREW_API_DOMAIN}" != "${HOMEBREW_API_DEFAULT_DOMAIN}" ]]
then then
JSON_URLS=("${HOMEBREW_API_DOMAIN}/${formula_or_cask}.jws.json") JSON_URLS=("${HOMEBREW_API_DOMAIN}/${filename}")
fi fi
JSON_URLS+=("${HOMEBREW_API_DEFAULT_DOMAIN}/${formula_or_cask}.jws.json") JSON_URLS+=("${HOMEBREW_API_DEFAULT_DOMAIN}/${filename}")
for json_url in "${JSON_URLS[@]}" for json_url in "${JSON_URLS[@]}"
do do
time_cond=() time_cond=()
if [[ -s "${HOMEBREW_CACHE}/api/${formula_or_cask}.jws.json" ]] if [[ -s "${cache_path}" ]]
then then
time_cond=("--time-cond" "${HOMEBREW_CACHE}/api/${formula_or_cask}.jws.json") time_cond=("--time-cond" "${cache_path}")
fi fi
curl \ curl \
"${CURL_DISABLE_CURLRC_ARGS[@]}" \ "${CURL_DISABLE_CURLRC_ARGS[@]}" \
--fail --compressed --silent \ --fail --compressed --silent \
--speed-limit "${HOMEBREW_CURL_SPEED_LIMIT}" --speed-time "${HOMEBREW_CURL_SPEED_TIME}" \ --speed-limit "${HOMEBREW_CURL_SPEED_LIMIT}" --speed-time "${HOMEBREW_CURL_SPEED_TIME}" \
--location --remote-time --output "${HOMEBREW_CACHE}/api/${formula_or_cask}.jws.json" \ --location --remote-time --output "${cache_path}" \
"${time_cond[@]}" \ "${time_cond[@]}" \
--user-agent "${HOMEBREW_USER_AGENT_CURL}" \ --user-agent "${HOMEBREW_USER_AGENT_CURL}" \
"${json_url}" "${json_url}"
@ -816,23 +819,25 @@ EOS
[[ ${curl_exit_code} -eq 0 ]] && break [[ ${curl_exit_code} -eq 0 ]] && break
done done
if [[ -f "${HOMEBREW_CACHE}/api/${formula_or_cask}_names.txt" ]] if [[ "${json}" == "formula" ]] && [[ -f "${api_cache}/formula_names.txt" ]]
then then
mv -f "${HOMEBREW_CACHE}/api/${formula_or_cask}_names.txt" \ mv -f "${api_cache}/formula_names.txt" "${api_cache}/formula_names.before.txt"
"${HOMEBREW_CACHE}/api/${formula_or_cask}_names.before.txt" elif [[ "${json}" == "cask" ]] && [[ -f "${api_cache}/cask_names.txt" ]]
then
mv -f "${api_cache}/cask_names.txt" "${api_cache}/cask_names.before.txt"
fi fi
if [[ ${curl_exit_code} -eq 0 ]] if [[ ${curl_exit_code} -eq 0 ]]
then then
touch "${HOMEBREW_CACHE}/api/${formula_or_cask}.jws.json" touch "${cache_path}"
CURRENT_JSON_BYTESIZE="$(wc -c "${HOMEBREW_CACHE}"/api/"${formula_or_cask}".jws.json)" CURRENT_JSON_BYTESIZE="$(wc -c "${cache_path}")"
if [[ "${INITIAL_JSON_BYTESIZE}" != "${CURRENT_JSON_BYTESIZE}" ]] if [[ "${INITIAL_JSON_BYTESIZE}" != "${CURRENT_JSON_BYTESIZE}" ]]
then then
if [[ "${formula_or_cask}" == "formula" ]] if [[ "${json}" == "formula" ]]
then then
rm -f "${HOMEBREW_CACHE}/api/formula_aliases.txt" rm -f "${api_cache}/formula_aliases.txt"
fi fi
HOMEBREW_UPDATED="1" HOMEBREW_UPDATED="1"
fi fi
@ -840,9 +845,10 @@ EOS
echo "Failed to download ${json_url}!" >>"${update_failed_file}" echo "Failed to download ${json_url}!" >>"${update_failed_file}"
fi fi
# Not a typo, this is the file we used to download that we should cleanup.
rm -f "${HOMEBREW_CACHE}/api/${formula_or_cask}.json"
done done
# Not a typo, these are the files we used to download that no longer need so should cleanup.
rm -f "${HOMEBREW_CACHE}/api/formula.json" "${HOMEBREW_CACHE}/api/cask.json"
fi fi
if [[ -f "${update_failed_file}" ]] if [[ -f "${update_failed_file}" ]]

View File

@ -25,6 +25,8 @@ class Tap
HOMEBREW_TAP_STYLE_EXCEPTIONS_DIR = "style_exceptions" HOMEBREW_TAP_STYLE_EXCEPTIONS_DIR = "style_exceptions"
HOMEBREW_TAP_PYPI_FORMULA_MAPPINGS = "pypi_formula_mappings.json" HOMEBREW_TAP_PYPI_FORMULA_MAPPINGS = "pypi_formula_mappings.json"
TAP_MIGRATIONS_STALE_SECONDS = 86400 # 1 day
HOMEBREW_TAP_JSON_FILES = %W[ HOMEBREW_TAP_JSON_FILES = %W[
#{HOMEBREW_TAP_FORMULA_RENAMES_FILE} #{HOMEBREW_TAP_FORMULA_RENAMES_FILE}
#{HOMEBREW_TAP_CASK_RENAMES_FILE} #{HOMEBREW_TAP_CASK_RENAMES_FILE}
@ -714,7 +716,11 @@ class Tap
# Hash with tap migrations. # Hash with tap migrations.
sig { returns(Hash) } sig { returns(Hash) }
def tap_migrations def tap_migrations
@tap_migrations ||= if (migration_file = path/HOMEBREW_TAP_MIGRATIONS_FILE).file? @tap_migrations ||= if name == "homebrew/cask" && !Homebrew::EnvConfig.no_install_from_api?
migrations, = Homebrew::API.fetch_json_api_file "cask_tap_migrations.jws.json",
stale_seconds: TAP_MIGRATIONS_STALE_SECONDS
migrations
elsif (migration_file = path/HOMEBREW_TAP_MIGRATIONS_FILE).file?
JSON.parse(migration_file.read) JSON.parse(migration_file.read)
else else
{} {}
@ -958,9 +964,13 @@ class CoreTap < Tap
# @private # @private
sig { returns(Hash) } sig { returns(Hash) }
def tap_migrations def tap_migrations
@tap_migrations ||= begin @tap_migrations ||= if Homebrew::EnvConfig.no_install_from_api?
self.class.ensure_installed! self.class.ensure_installed!
super super
else
migrations, = Homebrew::API.fetch_json_api_file "formula_tap_migrations.jws.json",
stale_seconds: TAP_MIGRATIONS_STALE_SECONDS
migrations
end end
end end