Skip to content

Commit

Permalink
Merge pull request #11831 from Rylan12/api-cleanup
Browse files Browse the repository at this point in the history
Refactor API methods
  • Loading branch information
Rylan12 committed Aug 9, 2021
2 parents d829145 + ab8aea0 commit 90bbe8b
Show file tree
Hide file tree
Showing 28 changed files with 457 additions and 235 deletions.
37 changes: 37 additions & 0 deletions Library/Homebrew/api.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# typed: false
# frozen_string_literal: true

require "api/analytics"
require "api/bottle"
require "api/cask"
require "api/formula"
require "api/versions"
require "extend/cachable"

module Homebrew
# Helper functions for using Homebrew's formulae.brew.sh API.
#
# @api private
module API
extend T::Sig

extend Cachable

module_function

API_DOMAIN = "https://formulae.brew.sh/api"

sig { params(endpoint: String).returns(T.any(String, Hash)) }
def fetch(endpoint)
return cache[endpoint] if cache.present? && cache.key?(endpoint)

api_url = "#{API_DOMAIN}/#{endpoint}"
output = Utils::Curl.curl_output("--fail", "--max-time", "5", api_url)
raise ArgumentError, "No file found at #{Tty.underline}#{api_url}#{Tty.reset}" unless output.success?

cache[endpoint] = JSON.parse(output.stdout)
rescue JSON::ParserError
raise ArgumentError, "Invalid JSON file: #{Tty.underline}#{api_url}#{Tty.reset}"
end
end
end
28 changes: 28 additions & 0 deletions Library/Homebrew/api/analytics.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# typed: false
# frozen_string_literal: true

module Homebrew
module API
# Helper functions for using the analytics JSON API.
#
# @api private
module Analytics
extend T::Sig

module_function

sig { returns(String) }
def analytics_api_path
"analytics"
end
alias generic_analytics_api_path analytics_api_path

sig { params(category: String, days: T.any(Integer, String)).returns(Hash) }
def fetch(category, days)
Homebrew::API.fetch "#{analytics_api_path}/#{category}/#{days}d.json"
end
end
end
end

require "extend/os/api/analytics"
95 changes: 95 additions & 0 deletions Library/Homebrew/api/bottle.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
# 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
extend T::Sig

module_function

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)
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: Symbol).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`.
Formulary.map_formula_name_to_local_bottle_path hash["name"], resource.downloader.cached_location
end
end
end
end

require "extend/os/api/bottle"
20 changes: 20 additions & 0 deletions Library/Homebrew/api/cask.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# typed: false
# frozen_string_literal: true

module Homebrew
module API
# Helper functions for using the cask JSON API.
#
# @api private
module Cask
extend T::Sig

module_function

sig { params(name: String).returns(Hash) }
def fetch(name)
Homebrew::API.fetch "cask/#{name}.json"
end
end
end
end
28 changes: 28 additions & 0 deletions Library/Homebrew/api/formula.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# typed: false
# frozen_string_literal: true

module Homebrew
module API
# Helper functions for using the formula JSON API.
#
# @api private
module Formula
extend T::Sig

module_function

sig { returns(String) }
def formula_api_path
"formula"
end
alias generic_formula_api_path formula_api_path

sig { params(name: String).returns(Hash) }
def fetch(name)
Homebrew::API.fetch "#{formula_api_path}/#{name}.json"
end
end
end
end

require "extend/os/api/formula"
52 changes: 52 additions & 0 deletions Library/Homebrew/api/versions.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# typed: false
# frozen_string_literal: true

module Homebrew
module API
# Helper functions for using the versions JSON API.
#
# @api private
module Versions
extend T::Sig

module_function

def formulae
# The result is cached by Homebrew::API.fetch
Homebrew::API.fetch "versions-formulae.json"
end

def linux
# The result is cached by Homebrew::API.fetch
Homebrew::API.fetch "versions-linux.json"
end

def casks
# The result is cached by Homebrew::API.fetch
Homebrew::API.fetch "versions-casks.json"
end

sig { params(name: String).returns(T.nilable(PkgVersion)) }
def latest_formula_version(name)
versions = if OS.mac? || Homebrew::EnvConfig.force_homebrew_on_linux?
formulae
else
linux
end

return unless versions.key? name

version = Version.new(versions[name]["version"])
revision = versions[name]["revision"]
PkgVersion.new(version, revision)
end

sig { params(token: String).returns(T.nilable(Version)) }
def latest_cask_version(token)
return unless casks.key? token

Version.new(casks[token]["version"])
end
end
end
end
118 changes: 0 additions & 118 deletions Library/Homebrew/bottle_api.rb

This file was deleted.

5 changes: 0 additions & 5 deletions Library/Homebrew/bottle_api.rbi

This file was deleted.

0 comments on commit 90bbe8b

Please sign in to comment.