From 374b61584b560a011f2dc480bea38e5bcb5326ec Mon Sep 17 00:00:00 2001 From: Rylan Polster Date: Thu, 29 Dec 2022 02:48:31 -0500 Subject: [PATCH 1/8] Load casks from the JSON API with `HOMEBREW_INSTALL_FROM_API` --- Library/Homebrew/api/cask.rb | 35 +++++++++++ Library/Homebrew/cask/cask_loader.rb | 91 +++++++++++++++++++++++++++- Library/Homebrew/cmd/update.sh | 44 ++++++++------ 3 files changed, 147 insertions(+), 23 deletions(-) diff --git a/Library/Homebrew/api/cask.rb b/Library/Homebrew/api/cask.rb index b7ec658bf2382..949c7394899f1 100644 --- a/Library/Homebrew/api/cask.rb +++ b/Library/Homebrew/api/cask.rb @@ -10,10 +10,45 @@ module Cask 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 diff --git a/Library/Homebrew/cask/cask_loader.rb b/Library/Homebrew/cask/cask_loader.rb index 28c53f7527bde..4ed6db0c23682 100644 --- a/Library/Homebrew/cask/cask_loader.rb +++ b/Library/Homebrew/cask/cask_loader.rb @@ -186,6 +186,91 @@ def load(config:) 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 @@ def self.for(ref, need_path: false) 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)) diff --git a/Library/Homebrew/cmd/update.sh b/Library/Homebrew/cmd/update.sh index a171c450b46d7..c77a42845712f 100644 --- a/Library/Homebrew/cmd/update.sh +++ b/Library/Homebrew/cmd/update.sh @@ -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}" From bab85d84e944001dbfaa4e672f6c6b937338e513 Mon Sep 17 00:00:00 2001 From: Rylan Polster Date: Fri, 30 Dec 2022 01:01:52 -0500 Subject: [PATCH 2/8] Extract common JSON API fetch logic --- Library/Homebrew/api.rb | 20 ++++++++++++++++++++ Library/Homebrew/api/cask.rb | 26 +------------------------- Library/Homebrew/api/formula.rb | 33 ++------------------------------- 3 files changed, 23 insertions(+), 56 deletions(-) diff --git a/Library/Homebrew/api.rb b/Library/Homebrew/api.rb index e4028b26781eb..a6dadf6fa6c3f 100644 --- a/Library/Homebrew/api.rb +++ b/Library/Homebrew/api.rb @@ -21,6 +21,7 @@ module API API_DOMAIN = "https://formulae.brew.sh/api" HOMEBREW_CACHE_API = (HOMEBREW_CACHE/"api").freeze + MAX_RETRIES = 3 sig { params(endpoint: String, json: T::Boolean).returns(T.any(String, Hash)) } def fetch(endpoint, json: true) @@ -38,5 +39,24 @@ def fetch(endpoint, json: true) rescue JSON::ParserError raise ArgumentError, "Invalid JSON file: #{Tty.underline}#{api_url}#{Tty.reset}" end + + def fetch_json_api_file(endpoint, target:) + retry_count = 0 + + url = "#{API_DOMAIN}/#{endpoint}" + begin + curl_args = %W[--compressed --silent #{url}] + curl_args.prepend("--time-cond", target) if target.exist? && !target.empty? + Utils::Curl.curl_download(*curl_args, to: target, max_time: 5) + + JSON.parse(target.read) + rescue JSON::ParserError + target.unlink + retry_count += 1 + odie "Cannot download non-corrupt #{url}!" if retry_count > MAX_RETRIES + + retry + end + end end end diff --git a/Library/Homebrew/api/cask.rb b/Library/Homebrew/api/cask.rb index 949c7394899f1..19d1166164fbf 100644 --- a/Library/Homebrew/api/cask.rb +++ b/Library/Homebrew/api/cask.rb @@ -10,13 +10,6 @@ module Cask 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" @@ -25,24 +18,7 @@ def fetch(name) 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 = Homebrew::API.fetch_json_api_file "cask.json", target: HOMEBREW_CACHE_API/"cask.json" json_casks.to_h do |json_cask| [json_cask["token"], json_cask.except("token")] diff --git a/Library/Homebrew/api/formula.rb b/Library/Homebrew/api/formula.rb index 0e62566220fe4..8d6d1bc605a09 100644 --- a/Library/Homebrew/api/formula.rb +++ b/Library/Homebrew/api/formula.rb @@ -10,19 +10,6 @@ module Formula class << self extend T::Sig - MAX_RETRIES = 3 - - sig { returns(String) } - def formula_api_path - "formula" - end - alias generic_formula_api_path formula_api_path - - sig { returns(String) } - def cached_formula_json_file - HOMEBREW_CACHE_API/"#{formula_api_path}.json" - end - sig { params(name: String).returns(Hash) } def fetch(name) Homebrew::API.fetch "#{formula_api_path}/#{name}.json" @@ -31,24 +18,8 @@ def fetch(name) sig { returns(Hash) } def all_formulae @all_formulae ||= begin - retry_count = 0 - - url = "https://formulae.brew.sh/api/formula.json" - json_formulae = begin - curl_args = %W[--compressed --silent #{url}] - if cached_formula_json_file.exist? && !cached_formula_json_file.empty? - curl_args.prepend("--time-cond", cached_formula_json_file) - end - curl_download(*curl_args, to: cached_formula_json_file, max_time: 5) - - JSON.parse(cached_formula_json_file.read) - rescue JSON::ParserError - cached_formula_json_file.unlink - retry_count += 1 - odie "Cannot download non-corrupt #{url}!" if retry_count > MAX_RETRIES - - retry - end + json_formulae = Homebrew::API.fetch_json_api_file "formula.json", + target: HOMEBREW_CACHE_API/"formula.json" @all_aliases = {} json_formulae.to_h do |json_formula| From 08529c38a6ea25247448234fc14c72ab840f5c52 Mon Sep 17 00:00:00 2001 From: Rylan Polster Date: Fri, 30 Dec 2022 01:54:32 -0500 Subject: [PATCH 3/8] Expand testing of `Homebrew::API` --- Library/Homebrew/test/api/cask_spec.rb | 44 ++++++++++++++++ Library/Homebrew/test/api/formula_spec.rb | 64 +++++++++++++++++++++++ Library/Homebrew/test/api_spec.rb | 34 ++++++++++++ 3 files changed, 142 insertions(+) create mode 100644 Library/Homebrew/test/api/cask_spec.rb create mode 100644 Library/Homebrew/test/api/formula_spec.rb diff --git a/Library/Homebrew/test/api/cask_spec.rb b/Library/Homebrew/test/api/cask_spec.rb new file mode 100644 index 0000000000000..35c561b8f9c18 --- /dev/null +++ b/Library/Homebrew/test/api/cask_spec.rb @@ -0,0 +1,44 @@ +# typed: false +# frozen_string_literal: true + +require "api" + +describe Homebrew::API::Cask do + let(:cache_dir) { mktmpdir } + + before do + stub_const("Homebrew::API::HOMEBREW_CACHE_API", cache_dir) + end + + def mock_curl_download(stdout:) + allow(Utils::Curl).to receive(:curl_download) do |*_args, **kwargs| + kwargs[:to].write stdout + end + end + + describe "::all_casks" do + let(:casks_json) { + <<~EOS + [{ + "token": "foo", + "url": "https://brew.sh/foo" + }, { + "token": "bar", + "url": "https://brew.sh/bar" + }] + EOS + } + let(:casks_hash) { + { + "foo" => { "url" => "https://brew.sh/foo" }, + "bar" => { "url" => "https://brew.sh/bar" }, + } + } + + it "returns the expected cask JSON list" do + mock_curl_download stdout: casks_json + casks_output = described_class.all_casks + expect(casks_output).to eq casks_hash + end + end +end diff --git a/Library/Homebrew/test/api/formula_spec.rb b/Library/Homebrew/test/api/formula_spec.rb new file mode 100644 index 0000000000000..38dbb57d5fe62 --- /dev/null +++ b/Library/Homebrew/test/api/formula_spec.rb @@ -0,0 +1,64 @@ +# typed: false +# frozen_string_literal: true + +require "api" + +describe Homebrew::API::Formula do + let(:cache_dir) { mktmpdir } + + before do + stub_const("Homebrew::API::HOMEBREW_CACHE_API", cache_dir) + end + + def mock_curl_download(stdout:) + allow(Utils::Curl).to receive(:curl_download) do |*_args, **kwargs| + kwargs[:to].write stdout + end + end + + describe "::all_formulae" do + let(:formulae_json) { + <<~EOS + [{ + "name": "foo", + "url": "https://brew.sh/foo", + "aliases": ["foo-alias1", "foo-alias2"] + }, { + "name": "bar", + "url": "https://brew.sh/bar", + "aliases": ["bar-alias"] + }, { + "name": "baz", + "url": "https://brew.sh/baz", + "aliases": [] + }] + EOS + } + let(:formulae_hash) { + { + "foo" => { "url" => "https://brew.sh/foo", "aliases" => ["foo-alias1", "foo-alias2"] }, + "bar" => { "url" => "https://brew.sh/bar", "aliases" => ["bar-alias"] }, + "baz" => { "url" => "https://brew.sh/baz", "aliases" => [] }, + } + } + let(:formulae_aliases) { + { + "foo-alias1" => "foo", + "foo-alias2" => "foo", + "bar-alias" => "bar", + } + } + + it "returns the expected formula JSON list" do + mock_curl_download stdout: formulae_json + formulae_output = described_class.all_formulae + expect(formulae_output).to eq formulae_hash + end + + it "returns the expected formula alias list" do + mock_curl_download stdout: formulae_json + aliases_output = described_class.all_aliases + expect(aliases_output).to eq formulae_aliases + end + end +end diff --git a/Library/Homebrew/test/api_spec.rb b/Library/Homebrew/test/api_spec.rb index 6d70ef66269d8..ff695bfe7797f 100644 --- a/Library/Homebrew/test/api_spec.rb +++ b/Library/Homebrew/test/api_spec.rb @@ -7,12 +7,19 @@ let(:text) { "foo" } let(:json) { '{"foo":"bar"}' } let(:json_hash) { JSON.parse(json) } + let(:json_invalid) { '{"foo":"bar"' } def mock_curl_output(stdout: "", success: true) curl_output = OpenStruct.new(stdout: stdout, success?: success) allow(Utils::Curl).to receive(:curl_output).and_return curl_output end + def mock_curl_download(stdout:) + allow(Utils::Curl).to receive(:curl_download) do |*_args, **kwargs| + kwargs[:to].write stdout + end + end + describe "::fetch" do it "fetches a text file" do mock_curl_output stdout: text @@ -36,4 +43,31 @@ def mock_curl_output(stdout: "", success: true) expect { described_class.fetch("baz.txt") }.to raise_error(ArgumentError, /Invalid JSON file/) end end + + describe "::fetch_json_api_file" do + let!(:cache_dir) { mktmpdir } + + before do + (cache_dir/"bar.json").write "tmp" + end + + it "fetches a JSON file" do + mock_curl_download stdout: json + fetched_json = described_class.fetch_json_api_file("foo.json", target: cache_dir/"foo.json") + expect(fetched_json).to eq json_hash + end + + it "updates an existing JSON file" do + mock_curl_download stdout: json + fetched_json = described_class.fetch_json_api_file("bar.json", target: cache_dir/"bar.json") + expect(fetched_json).to eq json_hash + end + + it "raises an error if the JSON file is invalid" do + mock_curl_download stdout: json_invalid + expect { + described_class.fetch_json_api_file("baz.json", target: cache_dir/"baz.json") + }.to raise_error(SystemExit) + end + end end From 68bbe03d042a157b763c18696fffe51a68ec555e Mon Sep 17 00:00:00 2001 From: Rylan Polster Date: Fri, 30 Dec 2022 02:24:12 -0500 Subject: [PATCH 4/8] Remove remaining `formula_api_path` references --- Library/Homebrew/api/formula.rb | 2 +- Library/Homebrew/dev-cmd/bottle.rb | 9 ++++----- Library/Homebrew/github_packages.rb | 3 +-- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/Library/Homebrew/api/formula.rb b/Library/Homebrew/api/formula.rb index 8d6d1bc605a09..48ebf47fdc173 100644 --- a/Library/Homebrew/api/formula.rb +++ b/Library/Homebrew/api/formula.rb @@ -12,7 +12,7 @@ class << self sig { params(name: String).returns(Hash) } def fetch(name) - Homebrew::API.fetch "#{formula_api_path}/#{name}.json" + Homebrew::API.fetch "formula/#{name}.json" end sig { returns(Hash) } diff --git a/Library/Homebrew/dev-cmd/bottle.rb b/Library/Homebrew/dev-cmd/bottle.rb index 6104050fc7f68..73301317dd673 100644 --- a/Library/Homebrew/dev-cmd/bottle.rb +++ b/Library/Homebrew/dev-cmd/bottle.rb @@ -557,11 +557,10 @@ def bottle_formula(f, args:) "date" => Pathname(filename.to_s).mtime.strftime("%F"), "tags" => { bottle_tag.to_s => { - "filename" => filename.url_encode, - "local_filename" => filename.to_s, - "sha256" => sha256, - "formulae_brew_sh_path" => Homebrew::API::Formula.formula_api_path, - "tab" => tab.to_bottle_hash, + "filename" => filename.url_encode, + "local_filename" => filename.to_s, + "sha256" => sha256, + "tab" => tab.to_bottle_hash, }, }, }, diff --git a/Library/Homebrew/github_packages.rb b/Library/Homebrew/github_packages.rb index 0527dcb401763..e50a1cbb62fdf 100644 --- a/Library/Homebrew/github_packages.rb +++ b/Library/Homebrew/github_packages.rb @@ -354,8 +354,7 @@ def upload_bottle(user, token, skopeo, formula_full_name, bottle_hash, keep_old: config_json_sha256, config_json_size = write_image_config(platform_hash, tar_sha256.hexdigest, blobs) - formulae_dir = tag_hash["formulae_brew_sh_path"] - documentation = "https://formulae.brew.sh/#{formulae_dir}/#{formula_name}" if formula_core_tap + documentation = "https://formulae.brew.sh/formula/#{formula_name}" if formula_core_tap descriptor_annotations_hash = { "org.opencontainers.image.ref.name" => tag, From 54e013aef6214e34cca835d79c744e0aee1fd274 Mon Sep 17 00:00:00 2001 From: Rylan Polster Date: Mon, 2 Jan 2023 12:58:40 -0500 Subject: [PATCH 5/8] Improve style Co-authored-by: Mike McQuaid --- Library/Homebrew/api/cask.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Library/Homebrew/api/cask.rb b/Library/Homebrew/api/cask.rb index 19d1166164fbf..aca14406a8406 100644 --- a/Library/Homebrew/api/cask.rb +++ b/Library/Homebrew/api/cask.rb @@ -18,7 +18,8 @@ def fetch(name) sig { returns(Hash) } def all_casks @all_casks ||= begin - json_casks = Homebrew::API.fetch_json_api_file "cask.json", target: HOMEBREW_CACHE_API/"cask.json" + json_casks = Homebrew::API.fetch_json_api_file "cask.json", + target: HOMEBREW_CACHE_API/"cask.json" json_casks.to_h do |json_cask| [json_cask["token"], json_cask.except("token")] From 52263e291779f2be5ae344984af14bb482f6a688 Mon Sep 17 00:00:00 2001 From: Rylan Polster Date: Mon, 2 Jan 2023 13:03:57 -0500 Subject: [PATCH 6/8] Fix style --- Library/Homebrew/api/cask.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Library/Homebrew/api/cask.rb b/Library/Homebrew/api/cask.rb index aca14406a8406..f0ed248cdf809 100644 --- a/Library/Homebrew/api/cask.rb +++ b/Library/Homebrew/api/cask.rb @@ -18,8 +18,8 @@ def fetch(name) sig { returns(Hash) } def all_casks @all_casks ||= begin - json_casks = Homebrew::API.fetch_json_api_file "cask.json", - target: HOMEBREW_CACHE_API/"cask.json" + json_casks = Homebrew::API.fetch_json_api_file "cask.json", + target: HOMEBREW_CACHE_API/"cask.json" json_casks.to_h do |json_cask| [json_cask["token"], json_cask.except("token")] From ffc74a51fb32b66a4cd8bc41dbd076dd23d9100e Mon Sep 17 00:00:00 2001 From: Rylan Polster Date: Wed, 4 Jan 2023 02:30:24 -0500 Subject: [PATCH 7/8] Load `*flight` blocks from API --- Library/Homebrew/cask/cask_loader.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Library/Homebrew/cask/cask_loader.rb b/Library/Homebrew/cask/cask_loader.rb index 4ed6db0c23682..888cf8b1373b5 100644 --- a/Library/Homebrew/cask/cask_loader.rb +++ b/Library/Homebrew/cask/cask_loader.rb @@ -263,7 +263,11 @@ def load(config:) json_cask[:artifacts].each do |artifact| key = artifact.keys.first - send(key, *artifact[key]) + if FLIGHT_STANZAS.include?(key) + instance_eval(artifact[key]) + else + send(key, *artifact[key]) + end end caveats json_cask[:caveats] if json_cask[:caveats].present? From ec8adb617e9b2be5f6ab4c44028350ddc2c9bd5c Mon Sep 17 00:00:00 2001 From: Rylan Polster Date: Fri, 6 Jan 2023 02:41:35 -0500 Subject: [PATCH 8/8] Use cask-source API when needed --- Library/Homebrew/cask/cask_loader.rb | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Library/Homebrew/cask/cask_loader.rb b/Library/Homebrew/cask/cask_loader.rb index 888cf8b1373b5..2e67869755999 100644 --- a/Library/Homebrew/cask/cask_loader.rb +++ b/Library/Homebrew/cask/cask_loader.rb @@ -203,7 +203,6 @@ def initialize(token) 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) && @@ -213,6 +212,12 @@ def load(config:) json_cask.deep_symbolize_keys! + # Use the cask-source API if there are any `*flight` blocks + if json_cask[:artifacts].any? { |artifact| FLIGHT_STANZAS.include?(artifact.keys.first) } + cask_source = Homebrew::API::CaskSource.fetch(token) + return FromContentLoader.new(cask_source).load(config: config) + end + Cask.new(token, source: cask_source, config: config) do version json_cask[:version]