Make Cask#to_h work without the API

Set metadata when we load casks from the source API.

Set `@tap_git_head` manually.

Also, allow `auto_update` to receive false.
This is only done for consistency.

Stop double printing the `kext` caveat.

Handle Array elements correctly when substituting
path elements in artifacts. This affected how the
Uninstall Signal keys were evaluated (they are
represented as arrays of arrays).
This commit is contained in:
apainintheneck 2023-02-18 12:08:54 -08:00
parent 39dd7e987d
commit c19017c6bd
6 changed files with 32 additions and 22 deletions

View File

@ -45,6 +45,8 @@ module Cask
directives[:signal] = Array(directives[:signal]).flatten.each_slice(2).to_a
@directives = directives
# This is already included when loading from the API.
return if cask.loaded_from_api?
return unless directives.key?(:kext)
cask.caveats do

View File

@ -17,6 +17,7 @@ module Cask
extend Forwardable
extend Searchable
extend Predicable
include Metadata
# Needs a leading slash to avoid `File.expand.path` complaining about non-absolute home.
@ -27,10 +28,11 @@ module Cask
# TODO: can be removed when API JSON is regenerated with HOMEBREW_PREFIX_PLACEHOLDER.
HOMEBREW_OLD_PREFIX_PLACEHOLDER = "$(brew --prefix)"
attr_reader :token, :sourcefile_path, :source, :config, :default_config, :loaded_from_api, :loader
attr_reader :token, :sourcefile_path, :source, :config, :default_config, :loader
attr_accessor :download, :allow_reassignment
attr_predicate :loaded_from_api?
class << self
def generating_hash!
return if generating_hash?
@ -83,14 +85,14 @@ module Cask
@tap
end
def initialize(token, sourcefile_path: nil, source: nil, tap: nil,
def initialize(token, sourcefile_path: nil, source: nil, tap: nil, loaded_from_api: false,
config: nil, allow_reassignment: false, loader: nil, &block)
@token = token
@sourcefile_path = sourcefile_path
@source = source
@tap = tap
@allow_reassignment = allow_reassignment
@loaded_from_api = false
@loaded_from_api = loaded_from_api
@loader = loader
@block = block
@ -278,7 +280,8 @@ module Cask
end
def populate_from_api!(json_cask)
@loaded_from_api = true
raise ArgumentError, "Expected cask to be loaded from the API" unless loaded_from_api?
@languages = json_cask[:languages]
@tap_git_head = json_cask[:tap_git_head]
@ruby_source_checksum = json_cask[:ruby_source_checksum].freeze
@ -334,7 +337,7 @@ module Cask
end
def to_hash_with_variations
if loaded_from_api && !Homebrew::EnvConfig.no_install_from_api?
if loaded_from_api? && !Homebrew::EnvConfig.no_install_from_api?
return api_to_local_hash(Homebrew::API::Cask.all_casks[token])
end

View File

@ -219,11 +219,17 @@ module Cask
def load(config:)
json_cask = @from_json || Homebrew::API::Cask.all_casks[token]
cask_source = JSON.pretty_generate(json_cask)
cask_options = {
loaded_from_api: true,
source: JSON.pretty_generate(json_cask),
config: config,
loader: self,
}
json_cask = Homebrew::API.merge_variations(json_cask).deep_symbolize_keys.freeze
tap = Tap.fetch(json_cask[:tap]) if json_cask[:tap].to_s.include?("/")
cask_options[:tap] = Tap.fetch(json_cask[:tap]) if json_cask[:tap].to_s.include?("/")
user_agent = json_cask.dig(:url_specs, :user_agent)
json_cask[:url_specs][:user_agent] = user_agent[1..].to_sym if user_agent && user_agent[0] == ":"
@ -231,7 +237,7 @@ module Cask
json_cask[:url_specs][:using] = using.to_sym
end
api_cask = Cask.new(token, tap: tap, source: cask_source, config: config, loader: self) do
api_cask = Cask.new(token, **cask_options) do
version json_cask[:version]
if json_cask[:sha256] == "no_check"
@ -248,7 +254,7 @@ module Cask
desc json_cask[:desc]
homepage json_cask[:homepage]
auto_updates json_cask[:auto_updates] if json_cask[:auto_updates].present?
auto_updates json_cask[:auto_updates] unless json_cask[:auto_updates].nil?
conflicts_with(**json_cask[:conflicts_with]) if json_cask[:conflicts_with].present?
if json_cask[:depends_on].present?
@ -289,7 +295,7 @@ module Cask
json_cask[:artifacts].each do |artifact|
# convert generic string replacements into actual ones
artifact = cask.loader.from_h_hash_gsubs(artifact, appdir)
artifact = cask.loader.from_h_gsubs(artifact, appdir)
key = artifact.keys.first
if artifact[key].nil?
# for artifacts with blocks that can't be loaded from the API
@ -328,18 +334,17 @@ module Cask
hash.to_h.transform_values do |value|
from_h_gsubs(value, appdir)
end
rescue TypeError
from_h_array_gsubs(hash, appdir)
end
def from_h_gsubs(value, appdir)
return value if value.blank?
if value.respond_to? :to_h
case value
when Hash
from_h_hash_gsubs(value, appdir)
elsif value.respond_to? :to_a
when Array
from_h_array_gsubs(value, appdir)
elsif value.is_a? String
when String
from_h_string_gsubs(value, appdir)
else
value

View File

@ -64,7 +64,7 @@ module Cask
def fetch(quiet: nil, timeout: nil)
odebug "Cask::Installer#fetch"
load_cask_from_source_api! if @cask.loaded_from_api && @cask.caskfile_only?
load_cask_from_source_api! if @cask.loaded_from_api? && @cask.caskfile_only?
verify_has_sha if require_sha? && !force?
@ -382,7 +382,7 @@ module Cask
return if @cask.source.blank?
extension = @cask.loaded_from_api ? "json" : "rb"
extension = @cask.loaded_from_api? ? "json" : "rb"
(metadata_subdir/"#{@cask.token}.#{extension}").write @cask.source
old_savedir&.rmtree
end
@ -559,7 +559,7 @@ module Cask
end
end
load_cask_from_source_api! if @cask.loaded_from_api && @cask.caskfile_only?
load_cask_from_source_api! if @cask.loaded_from_api? && @cask.caskfile_only?
# otherwise we default to the current cask
end

View File

@ -66,7 +66,7 @@ describe Cask::CaskLoader::FromAPILoader, :cask do
it "loads from JSON API" do
expect(cask_from_api).to be_a(Cask::Cask)
expect(cask_from_api.token).to eq(cask_token)
expect(cask_from_api.loaded_from_api).to be(true)
expect(cask_from_api.loaded_from_api?).to be(true)
expect(cask_from_api.caskfile_only?).to be(caskfile_only)
end
end

View File

@ -244,7 +244,7 @@ describe Cask::Installer, :cask do
expect(Homebrew::API::Cask).to receive(:fetch_source).once.and_return(content)
caffeine = Cask::CaskLoader.load(path)
expect(caffeine).to receive(:loaded_from_api).once.and_return(true)
expect(caffeine).to receive(:loaded_from_api?).once.and_return(true)
expect(caffeine).to receive(:caskfile_only?).once.and_return(true)
described_class.new(caffeine).install
@ -299,7 +299,7 @@ describe Cask::Installer, :cask do
expect(Homebrew::API::Cask).to receive(:fetch_source).twice.and_return(content)
caffeine = Cask::CaskLoader.load(path)
expect(caffeine).to receive(:loaded_from_api).twice.and_return(true)
expect(caffeine).to receive(:loaded_from_api?).twice.and_return(true)
expect(caffeine).to receive(:caskfile_only?).twice.and_return(true)
expect(caffeine).to receive(:installed_caskfile).once.and_return(invalid_path)