Load casks from the JSON API with HOMEBREW_INSTALL_FROM_API
This commit is contained in:
parent
ea0b786388
commit
374b61584b
@ -10,10 +10,45 @@ module Homebrew
|
||||
class << self
|
||||
extend T::Sig
|
||||
|
||||
MAX_RETRIES = 3
|
||||
|
||||
sig { returns(String) }
|
||||
def cached_cask_json_file
|
||||
HOMEBREW_CACHE_API/"cask.json"
|
||||
end
|
||||
|
||||
sig { params(name: String).returns(Hash) }
|
||||
def fetch(name)
|
||||
Homebrew::API.fetch "cask/#{name}.json"
|
||||
end
|
||||
|
||||
sig { returns(Hash) }
|
||||
def all_casks
|
||||
@all_casks ||= begin
|
||||
retry_count = 0
|
||||
|
||||
url = "https://formulae.brew.sh/api/cask.json"
|
||||
json_casks = begin
|
||||
curl_args = %W[--compressed --silent #{url}]
|
||||
if cached_cask_json_file.exist? && !cached_cask_json_file.empty?
|
||||
curl_args.prepend("--time-cond", cached_cask_json_file)
|
||||
end
|
||||
curl_download(*curl_args, to: cached_cask_json_file, max_time: 5)
|
||||
|
||||
JSON.parse(cached_cask_json_file.read)
|
||||
rescue JSON::ParserError
|
||||
cached_cask_json_file.unlink
|
||||
retry_count += 1
|
||||
odie "Cannot download non-corrupt #{url}!" if retry_count > MAX_RETRIES
|
||||
|
||||
retry
|
||||
end
|
||||
|
||||
json_casks.to_h do |json_cask|
|
||||
[json_cask["token"], json_cask.except("token")]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -186,6 +186,91 @@ module Cask
|
||||
end
|
||||
end
|
||||
|
||||
# Loads a cask from the JSON API.
|
||||
class FromAPILoader
|
||||
attr_reader :token, :path
|
||||
|
||||
FLIGHT_STANZAS = [:preflight, :postflight, :uninstall_preflight, :uninstall_postflight].freeze
|
||||
|
||||
def self.can_load?(ref)
|
||||
Homebrew::API::Cask.all_casks.key? ref
|
||||
end
|
||||
|
||||
def initialize(token)
|
||||
@token = token
|
||||
@path = CaskLoader.default_path(token)
|
||||
end
|
||||
|
||||
def load(config:)
|
||||
json_cask = Homebrew::API::Cask.all_casks[token]
|
||||
cask_source = Homebrew::API::CaskSource.fetch(token)
|
||||
|
||||
if (bottle_tag = ::Utils::Bottles.tag.to_s.presence) &&
|
||||
(variations = json_cask["variations"].presence) &&
|
||||
(variation = variations[bottle_tag].presence)
|
||||
json_cask = json_cask.merge(variation)
|
||||
end
|
||||
|
||||
json_cask.deep_symbolize_keys!
|
||||
|
||||
Cask.new(token, source: cask_source, config: config) do
|
||||
version json_cask[:version]
|
||||
|
||||
if json_cask[:sha256] == "no_check"
|
||||
sha256 :no_check
|
||||
else
|
||||
sha256 json_cask[:sha256]
|
||||
end
|
||||
|
||||
url json_cask[:url]
|
||||
appcast json_cask[:appcast] if json_cask[:appcast].present?
|
||||
json_cask[:name].each do |cask_name|
|
||||
name cask_name
|
||||
end
|
||||
desc json_cask[:desc]
|
||||
homepage json_cask[:homepage]
|
||||
|
||||
auto_updates json_cask[:auto_updates] if json_cask[:auto_updates].present?
|
||||
conflicts_with(**json_cask[:conflicts_with]) if json_cask[:conflicts_with].present?
|
||||
|
||||
if json_cask[:depends_on].present?
|
||||
dep_hash = json_cask[:depends_on].to_h do |dep_key, dep_value|
|
||||
next [dep_key, dep_value] unless dep_key == :macos
|
||||
|
||||
dep_type = dep_value.keys.first
|
||||
if dep_type == :==
|
||||
version_symbols = dep_value[dep_type].map do |version|
|
||||
MacOSVersions::SYMBOLS.key(version) || version
|
||||
end
|
||||
next [dep_key, version_symbols]
|
||||
end
|
||||
|
||||
version_symbol = dep_value[dep_type].first
|
||||
version_symbol = MacOSVersions::SYMBOLS.key(version_symbol) || version_symbol
|
||||
[dep_key, "#{dep_type} :#{version_symbol}"]
|
||||
end.compact
|
||||
depends_on(**dep_hash)
|
||||
end
|
||||
|
||||
if json_cask[:container].present?
|
||||
container_hash = json_cask[:container].to_h do |container_key, container_value|
|
||||
next [container_key, container_value] unless container_key == :type
|
||||
|
||||
[container_key, container_value.to_sym]
|
||||
end
|
||||
container(**container_hash)
|
||||
end
|
||||
|
||||
json_cask[:artifacts].each do |artifact|
|
||||
key = artifact.keys.first
|
||||
send(key, *artifact[key])
|
||||
end
|
||||
|
||||
caveats json_cask[:caveats] if json_cask[:caveats].present?
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Pseudo-loader which raises an error when trying to load the corresponding cask.
|
||||
class NullLoader < FromPathLoader
|
||||
extend T::Sig
|
||||
@ -225,15 +310,15 @@ module Cask
|
||||
next unless loader_class.can_load?(ref)
|
||||
|
||||
if loader_class == FromTapLoader && Homebrew::EnvConfig.install_from_api? &&
|
||||
ref.start_with?("homebrew/cask/") && Homebrew::API::CaskSource.available?(ref)
|
||||
return FromContentLoader.new(Homebrew::API::CaskSource.fetch(ref))
|
||||
ref.start_with?("homebrew/cask/") && FromAPILoader.can_load?(ref)
|
||||
return FromAPILoader.new(ref)
|
||||
end
|
||||
|
||||
return loader_class.new(ref)
|
||||
end
|
||||
|
||||
if Homebrew::EnvConfig.install_from_api? && !need_path && Homebrew::API::CaskSource.available?(ref)
|
||||
return FromContentLoader.new(Homebrew::API::CaskSource.fetch(ref))
|
||||
return FromAPILoader.new(ref)
|
||||
end
|
||||
|
||||
return FromTapPathLoader.new(default_path(ref)) if FromTapPathLoader.can_load?(default_path(ref))
|
||||
|
||||
@ -754,28 +754,32 @@ EOS
|
||||
if [[ -n "${HOMEBREW_INSTALL_FROM_API}" ]]
|
||||
then
|
||||
mkdir -p "${HOMEBREW_CACHE}/api"
|
||||
if [[ -f "${HOMEBREW_CACHE}/api/formula.json" ]]
|
||||
then
|
||||
INITIAL_JSON_BYTESIZE="$(wc -c "${HOMEBREW_CACHE}"/api/formula.json)"
|
||||
fi
|
||||
curl \
|
||||
"${CURL_DISABLE_CURLRC_ARGS[@]}" \
|
||||
--fail --compressed --silent --max-time 5 \
|
||||
--location --remote-time --output "${HOMEBREW_CACHE}/api/formula.json" \
|
||||
--time-cond "${HOMEBREW_CACHE}/api/formula.json" \
|
||||
--user-agent "${HOMEBREW_USER_AGENT_CURL}" \
|
||||
"https://formulae.brew.sh/api/formula.json"
|
||||
curl_exit_code=$?
|
||||
if [[ ${curl_exit_code} -eq 0 ]]
|
||||
then
|
||||
CURRENT_JSON_BYTESIZE="$(wc -c "${HOMEBREW_CACHE}"/api/formula.json)"
|
||||
if [[ "${INITIAL_JSON_BYTESIZE}" != "${CURRENT_JSON_BYTESIZE}" ]]
|
||||
|
||||
for formula_or_cask in formula cask
|
||||
do
|
||||
if [[ -f "${HOMEBREW_CACHE}/api/${formula_or_cask}.json" ]]
|
||||
then
|
||||
HOMEBREW_UPDATED="1"
|
||||
INITIAL_JSON_BYTESIZE="$(wc -c "${HOMEBREW_CACHE}"/api/"${formula_or_cask}".json)"
|
||||
fi
|
||||
else
|
||||
echo "Failed to download formula.json!" >>"${update_failed_file}"
|
||||
fi
|
||||
curl \
|
||||
"${CURL_DISABLE_CURLRC_ARGS[@]}" \
|
||||
--fail --compressed --silent --max-time 5 \
|
||||
--location --remote-time --output "${HOMEBREW_CACHE}/api/${formula_or_cask}.json" \
|
||||
--time-cond "${HOMEBREW_CACHE}/api/${formula_or_cask}.json" \
|
||||
--user-agent "${HOMEBREW_USER_AGENT_CURL}" \
|
||||
"https://formulae.brew.sh/api/${formula_or_cask}.json"
|
||||
curl_exit_code=$?
|
||||
if [[ ${curl_exit_code} -eq 0 ]]
|
||||
then
|
||||
CURRENT_JSON_BYTESIZE="$(wc -c "${HOMEBREW_CACHE}"/api/"${formula_or_cask}".json)"
|
||||
if [[ "${INITIAL_JSON_BYTESIZE}" != "${CURRENT_JSON_BYTESIZE}" ]]
|
||||
then
|
||||
HOMEBREW_UPDATED="1"
|
||||
fi
|
||||
else
|
||||
echo "Failed to download ${formula_or_cask}.json!" >>"${update_failed_file}"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
safe_cd "${HOMEBREW_REPOSITORY}"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user