From 89483abda9199d6c6ded1dd1f1163a41d4d8c2cd Mon Sep 17 00:00:00 2001 From: Rylan Polster Date: Tue, 14 Jun 2022 15:09:39 -0400 Subject: [PATCH] Remove Bottle API --- Library/Homebrew/api.rb | 1 - Library/Homebrew/api/bottle.rb | 96 ------------------------ Library/Homebrew/diagnostic.rb | 2 +- Library/Homebrew/test/api/bottle_spec.rb | 95 ----------------------- 4 files changed, 1 insertion(+), 193 deletions(-) delete mode 100644 Library/Homebrew/api/bottle.rb delete mode 100644 Library/Homebrew/test/api/bottle_spec.rb diff --git a/Library/Homebrew/api.rb b/Library/Homebrew/api.rb index 7798262da8..e4028b2678 100644 --- a/Library/Homebrew/api.rb +++ b/Library/Homebrew/api.rb @@ -2,7 +2,6 @@ # frozen_string_literal: true require "api/analytics" -require "api/bottle" require "api/cask" require "api/cask-source" require "api/formula" diff --git a/Library/Homebrew/api/bottle.rb b/Library/Homebrew/api/bottle.rb deleted file mode 100644 index f7327bdf10..0000000000 --- a/Library/Homebrew/api/bottle.rb +++ /dev/null @@ -1,96 +0,0 @@ -# typed: false -# frozen_string_literal: true - -require "github_packages" - -module Homebrew - module API - # Helper functions for using the bottle JSON API. - # - # @api private - module Bottle - class << self - extend T::Sig - - sig { returns(String) } - def bottle_api_path - "bottle" - end - alias generic_bottle_api_path bottle_api_path - - GITHUB_PACKAGES_SHA256_REGEX = %r{#{GitHubPackages::URL_REGEX}.*/blobs/sha256:(?\h{64})$}.freeze - - sig { params(name: String).returns(Hash) } - def fetch(name) - name = name.sub(%r{^homebrew/core/}, "") - Homebrew::API.fetch "#{bottle_api_path}/#{name}.json" - end - - sig { params(name: String).returns(T::Boolean) } - def available?(name) - fetch name - true - rescue ArgumentError - false - end - - sig { params(name: String).void } - def fetch_bottles(name) - hash = fetch(name) - bottle_tag = Utils::Bottles.tag.to_s - - if !hash["bottles"].key?(bottle_tag) && !hash["bottles"].key?("all") - odie "No bottle available for #{name} on the current OS" - end - - download_bottle(hash, bottle_tag) - - hash["dependencies"].each do |dep_hash| - existing_formula = begin - Formulary.factory dep_hash["name"] - rescue FormulaUnavailableError - # The formula might not exist if it's not installed and homebrew/core isn't tapped - nil - end - - next if existing_formula.present? && existing_formula.latest_version_installed? - - download_bottle(dep_hash, bottle_tag) - end - end - - sig { params(url: String).returns(T.nilable(String)) } - def checksum_from_url(url) - match = url.match GITHUB_PACKAGES_SHA256_REGEX - return if match.blank? - - match[:sha256] - end - - sig { params(hash: Hash, tag: String).void } - def download_bottle(hash, tag) - bottle = hash["bottles"][tag] - bottle ||= hash["bottles"]["all"] - return if bottle.blank? - - sha256 = bottle["sha256"] || checksum_from_url(bottle["url"]) - bottle_filename = ::Bottle::Filename.new(hash["name"], hash["pkg_version"], tag, hash["rebuild"]) - - resource = Resource.new hash["name"] - resource.url bottle["url"] - resource.sha256 sha256 - resource.version hash["pkg_version"] - resource.downloader.resolved_basename = bottle_filename - - resource.fetch - - # Map the name of this formula to the local bottle path to allow the - # formula to be loaded by passing just the name to `Formulary::factory`. - [hash["name"], "homebrew/core/#{hash["name"]}"].each do |name| - Formulary.map_formula_name_to_local_bottle_path name, resource.downloader.cached_location - end - end - end - end - end -end diff --git a/Library/Homebrew/diagnostic.rb b/Library/Homebrew/diagnostic.rb index d262d3541d..6d1eee6e41 100644 --- a/Library/Homebrew/diagnostic.rb +++ b/Library/Homebrew/diagnostic.rb @@ -890,7 +890,7 @@ module Homebrew # Formulae installed with HOMEBREW_INSTALL_FROM_API should not count as deleted formulae # but may not have a tap listed in their tab tap = Tab.for_keg(keg).tap - next if (tap.blank? || tap.core_tap?) && Homebrew::API::Bottle.available?(keg.name) + next if (tap.blank? || tap.core_tap?) && Homebrew::API::Formula.all_formulae.key?(keg.name) end keg.name diff --git a/Library/Homebrew/test/api/bottle_spec.rb b/Library/Homebrew/test/api/bottle_spec.rb deleted file mode 100644 index 3fe9e450a1..0000000000 --- a/Library/Homebrew/test/api/bottle_spec.rb +++ /dev/null @@ -1,95 +0,0 @@ -# typed: false -# frozen_string_literal: true - -require "api" - -describe Homebrew::API::Bottle do - let(:bottle_json) { - <<~EOS - { - "name": "hello", - "pkg_version": "2.10", - "rebuild": 0, - "bottles": { - "arm64_big_sur": { - "url": "https://ghcr.io/v2/homebrew/core/hello/blobs/sha256:b3b083db0807ff92c6e289a298f378198354b7727fb9ba9f4d550b8e08f90a60" - }, - "big_sur": { - "url": "https://ghcr.io/v2/homebrew/core/hello/blobs/sha256:69489ae397e4645127aa7773211310f81ebb6c99e1f8e3e22c5cdb55333f5408" - }, - "x86_64_linux": { - "url": "https://ghcr.io/v2/homebrew/core/hello/blobs/sha256:e6980196298e0a9cfe4fa4e328a71a1869a4d5e1d31c38442150ed784cfc0e29" - } - }, - "dependencies": [] - } - EOS - } - let(:bottle_hash) { JSON.parse(bottle_json) } - - 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 - - describe "::fetch" do - it "fetches the bottle JSON for a formula that exists" do - mock_curl_output stdout: bottle_json - fetched_hash = described_class.fetch("foo") - expect(fetched_hash).to eq bottle_hash - end - - it "raises an error if the formula does not exist" do - mock_curl_output success: false - expect { described_class.fetch("bar") }.to raise_error(ArgumentError, /No file found/) - end - - it "raises an error if the bottle JSON is invalid" do - mock_curl_output stdout: "foo" - expect { described_class.fetch("baz") }.to raise_error(ArgumentError, /Invalid JSON file/) - end - end - - describe "::available?" do - it "returns `true` if `fetch` succeeds" do - allow(described_class).to receive(:fetch) - expect(described_class.available?("foo")).to be true - end - - it "returns `false` if `fetch` fails" do - allow(described_class).to receive(:fetch).and_raise ArgumentError - expect(described_class.available?("foo")).to be false - end - end - - describe "::fetch_bottles" do - before do - ENV["HOMEBREW_INSTALL_FROM_API"] = "1" - allow(described_class).to receive(:fetch).and_return bottle_hash - end - - it "fetches bottles if a bottle is available" do - allow(Utils::Bottles).to receive(:tag).and_return :arm64_big_sur - expect { described_class.fetch_bottles("hello") }.not_to raise_error - end - - it "raises an error if no bottle is available" do - allow(Utils::Bottles).to receive(:tag).and_return :catalina - expect { described_class.fetch_bottles("hello") }.to raise_error(SystemExit) - end - end - - describe "::checksum_from_url" do - let(:sha256) { "b3b083db0807ff92c6e289a298f378198354b7727fb9ba9f4d550b8e08f90a60" } - let(:url) { "https://ghcr.io/v2/homebrew/core/hello/blobs/sha256:#{sha256}" } - let(:non_ghp_url) { "https://formulae.brew.sh/api/formula/hello.json" } - - it "returns the `sha256` for a GitHub packages URL" do - expect(described_class.checksum_from_url(url)).to eq sha256 - end - - it "returns `nil` for a non-GitHub packages URL" do - expect(described_class.checksum_from_url(non_ghp_url)).to be_nil - end - end -end