Merge pull request #14439 from MikeMcQuaid/cask_source_tweaks
Tweak cask-source API handling
This commit is contained in:
commit
cdf58fe392
@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
require "api/analytics"
|
require "api/analytics"
|
||||||
require "api/cask"
|
require "api/cask"
|
||||||
require "api/cask-source"
|
|
||||||
require "api/formula"
|
require "api/formula"
|
||||||
require "api/versions"
|
require "api/versions"
|
||||||
require "extend/cachable"
|
require "extend/cachable"
|
||||||
@ -23,23 +22,20 @@ module Homebrew
|
|||||||
HOMEBREW_CACHE_API = (HOMEBREW_CACHE/"api").freeze
|
HOMEBREW_CACHE_API = (HOMEBREW_CACHE/"api").freeze
|
||||||
MAX_RETRIES = 3
|
MAX_RETRIES = 3
|
||||||
|
|
||||||
sig { params(endpoint: String, json: T::Boolean).returns(T.any(String, Hash)) }
|
sig { params(endpoint: String).returns(Hash) }
|
||||||
def fetch(endpoint, json: true)
|
def fetch(endpoint)
|
||||||
return cache[endpoint] if cache.present? && cache.key?(endpoint)
|
return cache[endpoint] if cache.present? && cache.key?(endpoint)
|
||||||
|
|
||||||
api_url = "#{API_DOMAIN}/#{endpoint}"
|
api_url = "#{API_DOMAIN}/#{endpoint}"
|
||||||
output = Utils::Curl.curl_output("--fail", api_url, max_time: 5)
|
output = Utils::Curl.curl_output("--fail", api_url, max_time: 5)
|
||||||
raise ArgumentError, "No file found at #{Tty.underline}#{api_url}#{Tty.reset}" unless output.success?
|
raise ArgumentError, "No file found at #{Tty.underline}#{api_url}#{Tty.reset}" unless output.success?
|
||||||
|
|
||||||
cache[endpoint] = if json
|
cache[endpoint] = JSON.parse(output.stdout)
|
||||||
JSON.parse(output.stdout)
|
|
||||||
else
|
|
||||||
output.stdout
|
|
||||||
end
|
|
||||||
rescue JSON::ParserError
|
rescue JSON::ParserError
|
||||||
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(Hash) }
|
||||||
def fetch_json_api_file(endpoint, target:)
|
def fetch_json_api_file(endpoint, target:)
|
||||||
retry_count = 0
|
retry_count = 0
|
||||||
|
|
||||||
@ -58,5 +54,19 @@ module Homebrew
|
|||||||
retry
|
retry
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { params(filepath: String, repo: String, git_head: T.nilable(String)).returns(String) }
|
||||||
|
def fetch_file_source(filepath, repo:, git_head: nil)
|
||||||
|
git_head ||= "master"
|
||||||
|
endpoint = "#{git_head}/#{filepath}"
|
||||||
|
return cache[endpoint] if cache.present? && cache.key?(endpoint)
|
||||||
|
|
||||||
|
raw_url = "https://raw.githubusercontent.com/#{repo}/#{endpoint}"
|
||||||
|
puts "Fetching #{raw_url}..."
|
||||||
|
output = Utils::Curl.curl_output("--fail", raw_url, max_time: 5)
|
||||||
|
raise ArgumentError, "No file found at #{Tty.underline}#{raw_url}#{Tty.reset}" unless output.success?
|
||||||
|
|
||||||
|
cache[endpoint] = output.stdout
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,29 +0,0 @@
|
|||||||
# typed: false
|
|
||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
module Homebrew
|
|
||||||
module API
|
|
||||||
# Helper functions for using the cask source API.
|
|
||||||
#
|
|
||||||
# @api private
|
|
||||||
module CaskSource
|
|
||||||
class << self
|
|
||||||
extend T::Sig
|
|
||||||
|
|
||||||
sig { params(token: String).returns(Hash) }
|
|
||||||
def fetch(token)
|
|
||||||
token = token.sub(%r{^homebrew/cask/}, "")
|
|
||||||
Homebrew::API.fetch "cask-source/#{token}.rb", json: false
|
|
||||||
end
|
|
||||||
|
|
||||||
sig { params(token: String).returns(T::Boolean) }
|
|
||||||
def available?(token)
|
|
||||||
fetch token
|
|
||||||
true
|
|
||||||
rescue ArgumentError
|
|
||||||
false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
@ -10,9 +10,14 @@ module Homebrew
|
|||||||
class << self
|
class << self
|
||||||
extend T::Sig
|
extend T::Sig
|
||||||
|
|
||||||
sig { params(name: String).returns(Hash) }
|
sig { params(token: String).returns(Hash) }
|
||||||
def fetch(name)
|
def fetch(token)
|
||||||
Homebrew::API.fetch "cask/#{name}.json"
|
Homebrew::API.fetch "cask/#{token}.json"
|
||||||
|
end
|
||||||
|
|
||||||
|
sig { params(token: String, git_head: T.nilable(String)).returns(String) }
|
||||||
|
def fetch_source(token, git_head: nil)
|
||||||
|
Homebrew::API.fetch_file_source "Casks/#{token}.rb", repo: "Homebrew/homebrew-cask", git_head: git_head
|
||||||
end
|
end
|
||||||
|
|
||||||
sig { returns(Hash) }
|
sig { returns(Hash) }
|
||||||
|
@ -246,6 +246,7 @@ module Cask
|
|||||||
"conflicts_with" => conflicts_with,
|
"conflicts_with" => conflicts_with,
|
||||||
"container" => container&.pairs,
|
"container" => container&.pairs,
|
||||||
"auto_updates" => auto_updates,
|
"auto_updates" => auto_updates,
|
||||||
|
"tap_git_head" => tap&.git_head,
|
||||||
"languages" => languages,
|
"languages" => languages,
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
@ -212,9 +212,9 @@ module Cask
|
|||||||
|
|
||||||
json_cask.deep_symbolize_keys!
|
json_cask.deep_symbolize_keys!
|
||||||
|
|
||||||
# Use the cask-source API if there are any `*flight` blocks
|
# Download and use the cask source file if there are any `*flight` blocks
|
||||||
if json_cask[:artifacts].any? { |artifact| FLIGHT_STANZAS.include?(artifact.keys.first) }
|
if json_cask[:artifacts].any? { |artifact| FLIGHT_STANZAS.include?(artifact.keys.first) }
|
||||||
cask_source = Homebrew::API::CaskSource.fetch(token)
|
cask_source = Homebrew::API::Cask.fetch_source(token, git_head: json_cask[:tap_git_head])
|
||||||
return FromContentLoader.new(cask_source).load(config: config)
|
return FromContentLoader.new(cask_source).load(config: config)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -222,7 +222,9 @@ module Cask
|
|||||||
json_cask[:artifacts] = json_cask[:artifacts].map(&method(:from_h_hash_gsubs))
|
json_cask[:artifacts] = json_cask[:artifacts].map(&method(:from_h_hash_gsubs))
|
||||||
json_cask[:caveats] = from_h_string_gsubs(json_cask[:caveats])
|
json_cask[:caveats] = from_h_string_gsubs(json_cask[:caveats])
|
||||||
|
|
||||||
Cask.new(token, source: cask_source, config: config) do
|
tap = Tap.fetch(json_cask[:tap]) if json_cask[:tap].to_s.include?("/")
|
||||||
|
|
||||||
|
Cask.new(token, tap: tap, source: cask_source, config: config) do
|
||||||
version json_cask[:version]
|
version json_cask[:version]
|
||||||
|
|
||||||
if json_cask[:sha256] == "no_check"
|
if json_cask[:sha256] == "no_check"
|
||||||
@ -370,7 +372,7 @@ module Cask
|
|||||||
return loader_class.new(ref)
|
return loader_class.new(ref)
|
||||||
end
|
end
|
||||||
|
|
||||||
if Homebrew::EnvConfig.install_from_api? && !need_path && Homebrew::API::CaskSource.available?(ref)
|
if Homebrew::EnvConfig.install_from_api? && !need_path && Homebrew::API::Cask.all_casks.key?(ref)
|
||||||
return FromAPILoader.new(ref)
|
return FromAPILoader.new(ref)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -2126,6 +2126,7 @@ class Formula
|
|||||||
"disabled" => disabled?,
|
"disabled" => disabled?,
|
||||||
"disable_date" => disable_date,
|
"disable_date" => disable_date,
|
||||||
"disable_reason" => disable_reason,
|
"disable_reason" => disable_reason,
|
||||||
|
"tap_git_head" => tap&.git_head,
|
||||||
}
|
}
|
||||||
|
|
||||||
if stable
|
if stable
|
||||||
|
@ -141,11 +141,15 @@ module SystemConfig
|
|||||||
|
|
||||||
def core_tap_config(f = $stdout)
|
def core_tap_config(f = $stdout)
|
||||||
if CoreTap.instance.installed?
|
if CoreTap.instance.installed?
|
||||||
f.puts "Core tap ORIGIN: #{core_tap_origin}"
|
f.puts "Core tap origin: #{core_tap_origin}"
|
||||||
f.puts "Core tap HEAD: #{core_tap_head}"
|
f.puts "Core tap HEAD: #{core_tap_head}"
|
||||||
f.puts "Core tap last commit: #{core_tap_last_commit}"
|
f.puts "Core tap last commit: #{core_tap_last_commit}"
|
||||||
f.puts "Core tap branch: #{core_tap_branch}"
|
f.puts "Core tap branch: #{core_tap_branch}"
|
||||||
else
|
end
|
||||||
|
|
||||||
|
if (formula_json = Homebrew::API::HOMEBREW_CACHE_API/"formula.json") && formula_json.exist?
|
||||||
|
f.puts "Core tap JSON: #{formula_json.mtime.to_s(:short)}"
|
||||||
|
elsif !CoreTap.instance.installed?
|
||||||
f.puts "Core tap: N/A"
|
f.puts "Core tap: N/A"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -178,7 +178,7 @@ class Tap
|
|||||||
def git_head
|
def git_head
|
||||||
raise TapUnavailableError, name unless installed?
|
raise TapUnavailableError, name unless installed?
|
||||||
|
|
||||||
path.git_head
|
@git_head ||= path.git_head
|
||||||
end
|
end
|
||||||
|
|
||||||
# Time since last git commit for this {Tap}.
|
# Time since last git commit for this {Tap}.
|
||||||
|
@ -41,4 +41,14 @@ describe Homebrew::API::Cask do
|
|||||||
expect(casks_output).to eq casks_hash
|
expect(casks_output).to eq casks_hash
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "::fetch_source" do
|
||||||
|
it "fetches the source of a cask (defaulting to master when no `git_head` is passed)" do
|
||||||
|
curl_output = OpenStruct.new(stdout: "foo", success?: true)
|
||||||
|
expect(Utils::Curl).to receive(:curl_output)
|
||||||
|
.with("--fail", "https://raw.githubusercontent.com/Homebrew/homebrew-cask/master/Casks/foo.rb", max_time: 5)
|
||||||
|
.and_return(curl_output)
|
||||||
|
described_class.fetch_source("foo", git_head: nil)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
@ -21,12 +21,6 @@ describe Homebrew::API do
|
|||||||
end
|
end
|
||||||
|
|
||||||
describe "::fetch" do
|
describe "::fetch" do
|
||||||
it "fetches a text file" do
|
|
||||||
mock_curl_output stdout: text
|
|
||||||
fetched_text = described_class.fetch("foo.txt", json: false)
|
|
||||||
expect(fetched_text).to eq text
|
|
||||||
end
|
|
||||||
|
|
||||||
it "fetches a JSON file" do
|
it "fetches a JSON file" do
|
||||||
mock_curl_output stdout: json
|
mock_curl_output stdout: json
|
||||||
fetched_json = described_class.fetch("foo.json")
|
fetched_json = described_class.fetch("foo.json")
|
||||||
@ -70,4 +64,19 @@ describe Homebrew::API do
|
|||||||
}.to raise_error(SystemExit)
|
}.to raise_error(SystemExit)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "::fetch_file_source" do
|
||||||
|
it "fetches a file" do
|
||||||
|
mock_curl_output stdout: json
|
||||||
|
fetched_json = described_class.fetch_file_source("foo.json", repo: "Homebrew/homebrew-core", git_head: "master")
|
||||||
|
expect(fetched_json).to eq json
|
||||||
|
end
|
||||||
|
|
||||||
|
it "raises an error if the file does not exist" do
|
||||||
|
mock_curl_output success: false
|
||||||
|
expect {
|
||||||
|
described_class.fetch_file_source("bar.txt", repo: "Homebrew/homebrew-core", git_head: "master")
|
||||||
|
}.to raise_error(ArgumentError, /No file found/)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
@ -128,6 +128,7 @@ describe Cask::Cmd::List, :cask do
|
|||||||
"conflicts_with": null,
|
"conflicts_with": null,
|
||||||
"container": null,
|
"container": null,
|
||||||
"auto_updates": null,
|
"auto_updates": null,
|
||||||
|
"tap_git_head": null,
|
||||||
"languages": [
|
"languages": [
|
||||||
|
|
||||||
]
|
]
|
||||||
@ -162,6 +163,7 @@ describe Cask::Cmd::List, :cask do
|
|||||||
"conflicts_with": null,
|
"conflicts_with": null,
|
||||||
"container": null,
|
"container": null,
|
||||||
"auto_updates": null,
|
"auto_updates": null,
|
||||||
|
"tap_git_head": null,
|
||||||
"languages": [
|
"languages": [
|
||||||
|
|
||||||
]
|
]
|
||||||
@ -199,6 +201,7 @@ describe Cask::Cmd::List, :cask do
|
|||||||
"conflicts_with": null,
|
"conflicts_with": null,
|
||||||
"container": null,
|
"container": null,
|
||||||
"auto_updates": null,
|
"auto_updates": null,
|
||||||
|
"tap_git_head": null,
|
||||||
"languages": [
|
"languages": [
|
||||||
|
|
||||||
]
|
]
|
||||||
@ -233,6 +236,7 @@ describe Cask::Cmd::List, :cask do
|
|||||||
"conflicts_with": null,
|
"conflicts_with": null,
|
||||||
"container": null,
|
"container": null,
|
||||||
"auto_updates": null,
|
"auto_updates": null,
|
||||||
|
"tap_git_head": null,
|
||||||
"languages": [
|
"languages": [
|
||||||
|
|
||||||
]
|
]
|
||||||
@ -267,6 +271,7 @@ describe Cask::Cmd::List, :cask do
|
|||||||
"conflicts_with": null,
|
"conflicts_with": null,
|
||||||
"container": null,
|
"container": null,
|
||||||
"auto_updates": null,
|
"auto_updates": null,
|
||||||
|
"tap_git_head": null,
|
||||||
"languages": [
|
"languages": [
|
||||||
"zh",
|
"zh",
|
||||||
"en-US"
|
"en-US"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user