Merge pull request #20429 from Homebrew/simplify-to-hash-with-variations-from-api
Store API data in formulae/casks for use in `to_hash_with_variations`
This commit is contained in:
commit
e9bc015f9a
@ -60,13 +60,14 @@ module Cask
|
|||||||
source: T.nilable(String),
|
source: T.nilable(String),
|
||||||
tap: T.nilable(Tap),
|
tap: T.nilable(Tap),
|
||||||
loaded_from_api: T::Boolean,
|
loaded_from_api: T::Boolean,
|
||||||
|
api_source: T.nilable(T::Hash[String, T.untyped]),
|
||||||
config: T.nilable(Config),
|
config: T.nilable(Config),
|
||||||
allow_reassignment: T::Boolean,
|
allow_reassignment: T::Boolean,
|
||||||
loader: T.nilable(CaskLoader::ILoader),
|
loader: T.nilable(CaskLoader::ILoader),
|
||||||
block: T.nilable(T.proc.bind(DSL).void),
|
block: T.nilable(T.proc.bind(DSL).void),
|
||||||
).void
|
).void
|
||||||
}
|
}
|
||||||
def initialize(token, sourcefile_path: nil, source: nil, tap: nil, loaded_from_api: false,
|
def initialize(token, sourcefile_path: nil, source: nil, tap: nil, loaded_from_api: false, api_source: nil,
|
||||||
config: nil, allow_reassignment: false, loader: nil, &block)
|
config: nil, allow_reassignment: false, loader: nil, &block)
|
||||||
@token = token
|
@token = token
|
||||||
@sourcefile_path = sourcefile_path
|
@sourcefile_path = sourcefile_path
|
||||||
@ -74,6 +75,7 @@ module Cask
|
|||||||
@tap = tap
|
@tap = tap
|
||||||
@allow_reassignment = allow_reassignment
|
@allow_reassignment = allow_reassignment
|
||||||
@loaded_from_api = loaded_from_api
|
@loaded_from_api = loaded_from_api
|
||||||
|
@api_source = api_source
|
||||||
@loader = loader
|
@loader = loader
|
||||||
# Sorbet has trouble with bound procs assigned to instance variables:
|
# Sorbet has trouble with bound procs assigned to instance variables:
|
||||||
# https://github.com/sorbet/sorbet/issues/6843
|
# https://github.com/sorbet/sorbet/issues/6843
|
||||||
@ -91,6 +93,9 @@ module Cask
|
|||||||
sig { returns(T::Boolean) }
|
sig { returns(T::Boolean) }
|
||||||
def loaded_from_api? = @loaded_from_api
|
def loaded_from_api? = @loaded_from_api
|
||||||
|
|
||||||
|
sig { returns(T.nilable(T::Hash[String, T.untyped])) }
|
||||||
|
attr_reader :api_source
|
||||||
|
|
||||||
# An old name for the cask.
|
# An old name for the cask.
|
||||||
sig { returns(T::Array[String]) }
|
sig { returns(T::Array[String]) }
|
||||||
def old_tokens
|
def old_tokens
|
||||||
@ -407,8 +412,8 @@ module Cask
|
|||||||
private_constant :HASH_KEYS_TO_SKIP
|
private_constant :HASH_KEYS_TO_SKIP
|
||||||
|
|
||||||
def to_hash_with_variations
|
def to_hash_with_variations
|
||||||
if loaded_from_api? && !Homebrew::EnvConfig.no_install_from_api?
|
if loaded_from_api? && (json_cask = api_source) && !Homebrew::EnvConfig.no_install_from_api?
|
||||||
return api_to_local_hash(Homebrew::API::Cask.all_casks[token].dup)
|
return api_to_local_hash(json_cask.dup)
|
||||||
end
|
end
|
||||||
|
|
||||||
hash = to_h
|
hash = to_h
|
||||||
|
|||||||
@ -336,6 +336,7 @@ module Cask
|
|||||||
|
|
||||||
cask_options = {
|
cask_options = {
|
||||||
loaded_from_api: true,
|
loaded_from_api: true,
|
||||||
|
api_source: json_cask,
|
||||||
sourcefile_path: @sourcefile_path,
|
sourcefile_path: @sourcefile_path,
|
||||||
source: JSON.pretty_generate(json_cask),
|
source: JSON.pretty_generate(json_cask),
|
||||||
config:,
|
config:,
|
||||||
|
|||||||
@ -557,6 +557,12 @@ class Formula
|
|||||||
# @see .loaded_from_api?
|
# @see .loaded_from_api?
|
||||||
delegate loaded_from_api?: :"self.class"
|
delegate loaded_from_api?: :"self.class"
|
||||||
|
|
||||||
|
# The API source data used to load this formula.
|
||||||
|
# Returns `nil` if the formula was not loaded from the API.
|
||||||
|
# @!method api_source
|
||||||
|
# @see .api_source
|
||||||
|
delegate api_source: :"self.class"
|
||||||
|
|
||||||
sig { void }
|
sig { void }
|
||||||
def update_head_version
|
def update_head_version
|
||||||
return unless head?
|
return unless head?
|
||||||
@ -2625,9 +2631,8 @@ class Formula
|
|||||||
hash = to_hash
|
hash = to_hash
|
||||||
|
|
||||||
# Take from API, merging in local install status.
|
# Take from API, merging in local install status.
|
||||||
if loaded_from_api? && !Homebrew::EnvConfig.no_install_from_api?
|
if loaded_from_api? && (json_formula = api_source) && !Homebrew::EnvConfig.no_install_from_api?
|
||||||
json_formula = Homebrew::API::Formula.all_formulae.fetch(name).dup
|
return json_formula.dup.merge(
|
||||||
return json_formula.merge(
|
|
||||||
hash.slice("name", "installed", "linked_keg", "pinned", "outdated"),
|
hash.slice("name", "installed", "linked_keg", "pinned", "outdated"),
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
@ -3360,6 +3365,7 @@ class Formula
|
|||||||
@skip_clean_paths = T.let(Set.new, T.nilable(T::Set[T.any(String, Symbol)]))
|
@skip_clean_paths = T.let(Set.new, T.nilable(T::Set[T.any(String, Symbol)]))
|
||||||
@link_overwrite_paths = T.let(Set.new, T.nilable(T::Set[String]))
|
@link_overwrite_paths = T.let(Set.new, T.nilable(T::Set[String]))
|
||||||
@loaded_from_api = T.let(false, T.nilable(T::Boolean))
|
@loaded_from_api = T.let(false, T.nilable(T::Boolean))
|
||||||
|
@api_source = T.let(nil, T.nilable(T::Hash[String, T.untyped]))
|
||||||
@on_system_blocks_exist = T.let(false, T.nilable(T::Boolean))
|
@on_system_blocks_exist = T.let(false, T.nilable(T::Boolean))
|
||||||
@network_access_allowed = T.let(SUPPORTED_NETWORK_ACCESS_PHASES.to_h do |phase|
|
@network_access_allowed = T.let(SUPPORTED_NETWORK_ACCESS_PHASES.to_h do |phase|
|
||||||
[phase, DEFAULT_NETWORK_ACCESS_ALLOWED]
|
[phase, DEFAULT_NETWORK_ACCESS_ALLOWED]
|
||||||
@ -3384,6 +3390,10 @@ class Formula
|
|||||||
sig { returns(T::Boolean) }
|
sig { returns(T::Boolean) }
|
||||||
def loaded_from_api? = !!@loaded_from_api
|
def loaded_from_api? = !!@loaded_from_api
|
||||||
|
|
||||||
|
# Whether this formula was loaded using the formulae.brew.sh API.
|
||||||
|
sig { returns(T.nilable(T::Hash[String, T.untyped])) }
|
||||||
|
attr_reader :api_source
|
||||||
|
|
||||||
# Whether this formula contains OS/arch-specific blocks
|
# Whether this formula contains OS/arch-specific blocks
|
||||||
# (e.g. `on_macos`, `on_arm`, `on_monterey :or_older`, `on_system :linux, macos: :big_sur_or_newer`).
|
# (e.g. `on_macos`, `on_arm`, `on_monterey :or_older`, `on_system :linux, macos: :big_sur_or_newer`).
|
||||||
sig { returns(T::Boolean) }
|
sig { returns(T::Boolean) }
|
||||||
|
|||||||
@ -173,9 +173,9 @@ module Formulary
|
|||||||
platform_cache[:path][path] = klass
|
platform_cache[:path][path] = klass
|
||||||
end
|
end
|
||||||
|
|
||||||
sig { params(name: String, flags: T::Array[String]).returns(T.class_of(Formula)) }
|
sig { params(name: String, json_formula_with_variations: T::Hash[String, T.untyped], flags: T::Array[String]).returns(T.class_of(Formula)) }
|
||||||
def self.load_formula_from_api!(name, flags:)
|
def self.load_formula_from_json!(name, json_formula_with_variations, flags:)
|
||||||
namespace = :"FormulaNamespaceAPI#{namespace_key(name)}"
|
namespace = :"FormulaNamespaceAPI#{namespace_key(json_formula_with_variations.to_json)}"
|
||||||
|
|
||||||
mod = Module.new
|
mod = Module.new
|
||||||
remove_const(namespace) if const_defined?(namespace)
|
remove_const(namespace) if const_defined?(namespace)
|
||||||
@ -184,10 +184,7 @@ module Formulary
|
|||||||
mod.const_set(:BUILD_FLAGS, flags)
|
mod.const_set(:BUILD_FLAGS, flags)
|
||||||
|
|
||||||
class_name = class_s(name)
|
class_name = class_s(name)
|
||||||
json_formula = Homebrew::API::Formula.all_formulae[name]
|
json_formula = Homebrew::API.merge_variations(json_formula_with_variations)
|
||||||
raise FormulaUnavailableError, name if json_formula.nil?
|
|
||||||
|
|
||||||
json_formula = Homebrew::API.merge_variations(json_formula)
|
|
||||||
|
|
||||||
uses_from_macos_names = json_formula.fetch("uses_from_macos", []).map do |dep|
|
uses_from_macos_names = json_formula.fetch("uses_from_macos", []).map do |dep|
|
||||||
next dep unless dep.is_a? Hash
|
next dep unless dep.is_a? Hash
|
||||||
@ -273,6 +270,7 @@ module Formulary
|
|||||||
# rubocop:todo Sorbet/BlockMethodDefinition
|
# rubocop:todo Sorbet/BlockMethodDefinition
|
||||||
klass = Class.new(::Formula) do
|
klass = Class.new(::Formula) do
|
||||||
@loaded_from_api = true
|
@loaded_from_api = true
|
||||||
|
@api_source = json_formula_with_variations
|
||||||
|
|
||||||
desc json_formula["desc"]
|
desc json_formula["desc"]
|
||||||
homepage json_formula["homepage"]
|
homepage json_formula["homepage"]
|
||||||
@ -911,7 +909,10 @@ module Formulary
|
|||||||
private
|
private
|
||||||
|
|
||||||
def load_from_api(flags:)
|
def load_from_api(flags:)
|
||||||
Formulary.load_formula_from_api!(name, flags:)
|
json_formula = Homebrew::API::Formula.all_formulae[name]
|
||||||
|
raise FormulaUnavailableError, name if json_formula.nil?
|
||||||
|
|
||||||
|
Formulary.load_formula_from_json!(name, json_formula, flags:)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
3
Library/Homebrew/sorbet/rbi/dsl/formula.rbi
generated
3
Library/Homebrew/sorbet/rbi/dsl/formula.rbi
generated
@ -9,6 +9,9 @@ class Formula
|
|||||||
sig { params(args: T.untyped, block: T.untyped).returns(T.untyped) }
|
sig { params(args: T.untyped, block: T.untyped).returns(T.untyped) }
|
||||||
def allow_network_access!(*args, &block); end
|
def allow_network_access!(*args, &block); end
|
||||||
|
|
||||||
|
sig { params(args: T.untyped, block: T.untyped).returns(T.untyped) }
|
||||||
|
def api_source(*args, &block); end
|
||||||
|
|
||||||
sig { params(args: T.untyped, block: T.untyped).returns(T::Boolean) }
|
sig { params(args: T.untyped, block: T.untyped).returns(T::Boolean) }
|
||||||
def autobump?(*args, &block); end
|
def autobump?(*args, &block); end
|
||||||
|
|
||||||
|
|||||||
@ -533,5 +533,21 @@ RSpec.describe Cask::Cask, :cask do
|
|||||||
expect(h["artifacts"].first[:binary].first).to eq "$APPDIR/some/path"
|
expect(h["artifacts"].first[:binary].first).to eq "$APPDIR/some/path"
|
||||||
expect(h["caveats"]).to eq "$HOMEBREW_PREFIX and /$HOME\n"
|
expect(h["caveats"]).to eq "$HOMEBREW_PREFIX and /$HOME\n"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context "when loaded from json file" do
|
||||||
|
let(:expected_json) { (TEST_FIXTURE_DIR/"cask/everything-with-variations.json").read.strip }
|
||||||
|
|
||||||
|
it "returns expected hash with variations" do
|
||||||
|
expect(Homebrew::API::Cask).not_to receive(:source_download)
|
||||||
|
cask = Cask::CaskLoader::FromAPILoader.new("everything-with-variations", from_json: JSON.parse(expected_json))
|
||||||
|
.load(config: nil)
|
||||||
|
|
||||||
|
hash = cask.to_hash_with_variations
|
||||||
|
|
||||||
|
expect(cask.loaded_from_api?).to be true
|
||||||
|
expect(hash).to be_a(Hash)
|
||||||
|
expect(JSON.pretty_generate(hash)).to eq(expected_json)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -292,8 +292,12 @@ RSpec.describe Formulary do
|
|||||||
def formula_json_contents(extra_items = {})
|
def formula_json_contents(extra_items = {})
|
||||||
{
|
{
|
||||||
formula_name => {
|
formula_name => {
|
||||||
|
"name" => formula_name,
|
||||||
"desc" => "testball",
|
"desc" => "testball",
|
||||||
"homepage" => "https://example.com",
|
"homepage" => "https://example.com",
|
||||||
|
"installed" => [],
|
||||||
|
"outdated" => false,
|
||||||
|
"pinned" => false,
|
||||||
"license" => "MIT",
|
"license" => "MIT",
|
||||||
"revision" => 0,
|
"revision" => 0,
|
||||||
"version_scheme" => 0,
|
"version_scheme" => 0,
|
||||||
@ -340,6 +344,7 @@ RSpec.describe Formulary do
|
|||||||
"conflicts_with" => ["conflicting_formula"],
|
"conflicts_with" => ["conflicting_formula"],
|
||||||
"conflicts_with_reasons" => ["it does"],
|
"conflicts_with_reasons" => ["it does"],
|
||||||
"link_overwrite" => ["bin/abc"],
|
"link_overwrite" => ["bin/abc"],
|
||||||
|
"linked_keg" => nil,
|
||||||
"caveats" => "example caveat string\n/$HOME\n$HOMEBREW_PREFIX",
|
"caveats" => "example caveat string\n/$HOME\n$HOMEBREW_PREFIX",
|
||||||
"service" => {
|
"service" => {
|
||||||
"name" => { macos: "custom.launchd.name", linux: "custom.systemd.name" },
|
"name" => { macos: "custom.launchd.name", linux: "custom.systemd.name" },
|
||||||
@ -447,6 +452,17 @@ RSpec.describe Formulary do
|
|||||||
end.to raise_error("Cannot build from source from abstract formula.")
|
end.to raise_error("Cannot build from source from abstract formula.")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "returns a Formula that can regenerate its JSON API" do
|
||||||
|
allow(Homebrew::API::Formula).to receive(:all_formulae).and_return formula_json_contents
|
||||||
|
|
||||||
|
formula = described_class.factory(formula_name)
|
||||||
|
expect(formula).to be_a(Formula)
|
||||||
|
expect(formula.loaded_from_api?).to be true
|
||||||
|
|
||||||
|
expected_hash = formula_json_contents[formula_name]
|
||||||
|
expect(formula.to_hash_with_variations).to eq(expected_hash)
|
||||||
|
end
|
||||||
|
|
||||||
it "returns a deprecated Formula when given a name" do
|
it "returns a deprecated Formula when given a name" do
|
||||||
allow(Homebrew::API::Formula).to receive(:all_formulae).and_return formula_json_contents(deprecate_json)
|
allow(Homebrew::API::Formula).to receive(:all_formulae).and_return formula_json_contents(deprecate_json)
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,122 @@
|
|||||||
|
{
|
||||||
|
"token": "everything-with-variations",
|
||||||
|
"full_token": "everything-with-variations",
|
||||||
|
"old_tokens": [],
|
||||||
|
"tap": "homebrew/cask",
|
||||||
|
"name": [
|
||||||
|
"Everything"
|
||||||
|
],
|
||||||
|
"desc": "Little bit of everything",
|
||||||
|
"homepage": "https://www.everything.app/",
|
||||||
|
"url": "https://cachefly.everything.app/releases/Everything_1.2.3.zip",
|
||||||
|
"url_specs": {
|
||||||
|
"cookies": {
|
||||||
|
"ALL": "1234"
|
||||||
|
},
|
||||||
|
"user_agent": ":fake"
|
||||||
|
},
|
||||||
|
"version": "1.2.3",
|
||||||
|
"autobump": true,
|
||||||
|
"no_autobump_message": null,
|
||||||
|
"skip_livecheck": false,
|
||||||
|
"installed": null,
|
||||||
|
"installed_time": null,
|
||||||
|
"bundle_version": null,
|
||||||
|
"bundle_short_version": null,
|
||||||
|
"outdated": false,
|
||||||
|
"sha256": "c64c05bdc0be845505d6e55e69e696a7f50d40846e76155f0c85d5ff5e7bbb84",
|
||||||
|
"artifacts": [
|
||||||
|
{
|
||||||
|
"uninstall": [
|
||||||
|
{
|
||||||
|
"launchctl": "com.every.thing.agent",
|
||||||
|
"signal": [
|
||||||
|
[
|
||||||
|
"TERM",
|
||||||
|
"com.every.thing.controller1"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"TERM",
|
||||||
|
"com.every.thing.bin"
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"kext": "com.every.thing.driver",
|
||||||
|
"delete": "/Library/EverythingHelperTools"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"installer": [
|
||||||
|
{
|
||||||
|
"script": {
|
||||||
|
"executable": "~/just/another/path/install.sh",
|
||||||
|
"args": [
|
||||||
|
"--mode=silent"
|
||||||
|
],
|
||||||
|
"sudo": true,
|
||||||
|
"print_stderr": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"app": [
|
||||||
|
"Everything.app"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"zap": [
|
||||||
|
{
|
||||||
|
"trash": [
|
||||||
|
"~/.everything",
|
||||||
|
"~/Library/Everything"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"caveats": "Installing everything might take a while...\n\neverything requires a kernel extension to work.\nIf the installation fails, retry after you enable it in:\n System Settings → Privacy & Security\n\nFor more information, refer to vendor documentation or this Apple Technical Note:\n https://developer.apple.com/library/content/technotes/tn2459/_index.html\n",
|
||||||
|
"depends_on": {
|
||||||
|
"cask": [
|
||||||
|
"something"
|
||||||
|
],
|
||||||
|
"macos": {
|
||||||
|
">=": [
|
||||||
|
"10.11"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"conflicts_with": {
|
||||||
|
"formula": [
|
||||||
|
"nothing"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"container": {
|
||||||
|
"type": "naked"
|
||||||
|
},
|
||||||
|
"auto_updates": true,
|
||||||
|
"deprecated": false,
|
||||||
|
"deprecation_date": null,
|
||||||
|
"deprecation_reason": null,
|
||||||
|
"deprecation_replacement_formula": null,
|
||||||
|
"deprecation_replacement_cask": null,
|
||||||
|
"disabled": false,
|
||||||
|
"disable_date": null,
|
||||||
|
"disable_reason": null,
|
||||||
|
"disable_replacement_formula": null,
|
||||||
|
"disable_replacement_cask": null,
|
||||||
|
"tap_git_head": "abcdef1234567890abcdef1234567890abcdef12",
|
||||||
|
"languages": [
|
||||||
|
"en",
|
||||||
|
"eo"
|
||||||
|
],
|
||||||
|
"ruby_source_path": "Casks/everything-with-variations.rb",
|
||||||
|
"ruby_source_checksum": {
|
||||||
|
"sha256": "d8d0d6b2e5ff65388eccb82236fd3aa157b4a29bb043a1f72b97f0e9b70e8320"
|
||||||
|
},
|
||||||
|
"variations": {
|
||||||
|
"arm64_monterey": {
|
||||||
|
"url": "https://cachefly.everything.app/releases/arm64_monterey/Everything_1.2.3.zip"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user