97 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			Ruby
		
	
	
	
	
	
			
		
		
	
	
			97 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			Ruby
		
	
	
	
	
	
| # 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:(?<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
 | 
