Overhaul Formula/Cask JSON generation
- Use constants for placeholders - Monkeypatch to set `HOMEBREW_PREFIX` consistently to placeholder - Use environment variable to set `Dir.home` consistently to placeholder - Use `appdir` short-circuit to set `Cask#appdir` consistently to placeholder - Use `Cask.generating_hash!` to enable "generating mode" with these patches - Fix `Formula#caveats` from JSON Fixes #14505 Fixes #14595
This commit is contained in:
parent
66c9d5f2af
commit
237eec8ef8
@ -19,10 +19,48 @@ module Cask
|
||||
extend Searchable
|
||||
include Metadata
|
||||
|
||||
attr_reader :token, :sourcefile_path, :source, :config, :default_config, :loaded_from_api
|
||||
HOME_PLACEHOLDER = "$HOME"
|
||||
HOMEBREW_PREFIX_PLACEHOLDER = "$HOMEBREW_PREFIX"
|
||||
APPDIR_PLACEHOLDER = "$APPDIR"
|
||||
|
||||
# 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_accessor :download, :allow_reassignment
|
||||
|
||||
class << self
|
||||
def generating_hash!
|
||||
return if generating_hash?
|
||||
|
||||
# Apply monkeypatches for API generation
|
||||
@old_homebrew_prefix = HOMEBREW_PREFIX
|
||||
@old_home = Dir.home
|
||||
Object.send(:remove_const, :HOMEBREW_PREFIX)
|
||||
Object.const_set(:HOMEBREW_PREFIX, Pathname(HOMEBREW_PREFIX_PLACEHOLDER))
|
||||
ENV["HOME"] = HOME_PLACEHOLDER
|
||||
|
||||
@generating_hash = true
|
||||
end
|
||||
|
||||
def generated_hash!
|
||||
return unless generating_hash?
|
||||
|
||||
# Revert monkeypatches for API generation
|
||||
Object.send(:remove_const, :HOMEBREW_PREFIX)
|
||||
Object.const_set(:HOMEBREW_PREFIX, @old_homebrew_prefix)
|
||||
ENV["HOME"] = @old_home
|
||||
|
||||
@generating_hash = false
|
||||
end
|
||||
|
||||
def generating_hash?
|
||||
@generating_hash ||= false
|
||||
@generating_hash == true
|
||||
end
|
||||
end
|
||||
|
||||
def self.all
|
||||
# TODO: ideally avoid using ARGV by moving to e.g. CLI::Parser
|
||||
if ARGV.exclude?("--eval-all") && !Homebrew::EnvConfig.eval_all?
|
||||
@ -45,13 +83,14 @@ module Cask
|
||||
end
|
||||
|
||||
def initialize(token, sourcefile_path: nil, source: nil, tap: nil, config: nil,
|
||||
allow_reassignment: false, loaded_from_api: false, &block)
|
||||
allow_reassignment: false, loaded_from_api: false, loader: nil, &block)
|
||||
@token = token
|
||||
@sourcefile_path = sourcefile_path
|
||||
@source = source
|
||||
@tap = tap
|
||||
@allow_reassignment = allow_reassignment
|
||||
@loaded_from_api = loaded_from_api
|
||||
@loader = loader
|
||||
@block = block
|
||||
|
||||
@default_config = config || Config.new
|
||||
@ -251,7 +290,7 @@ module Cask
|
||||
"outdated" => outdated?,
|
||||
"sha256" => sha256,
|
||||
"artifacts" => artifacts_list,
|
||||
"caveats" => (to_h_string_gsubs(caveats) unless caveats.empty?),
|
||||
"caveats" => (caveats unless caveats.empty?),
|
||||
"depends_on" => depends_on,
|
||||
"conflicts_with" => conflicts_with,
|
||||
"container" => container&.pairs,
|
||||
@ -315,52 +354,10 @@ module Cask
|
||||
when Artifact::AbstractFlightBlock
|
||||
# Only indicate whether this block is used as we don't load it from the API
|
||||
{ artifact.summarize => nil }
|
||||
when Artifact::Relocated
|
||||
# Don't replace the Homebrew prefix in the source path since the source could include /usr/local
|
||||
source, *args = artifact.to_args
|
||||
{ artifact.class.dsl_key => [to_h_string_gsubs(source, replace_prefix: false), *to_h_gsubs(args)] }
|
||||
else
|
||||
{ artifact.class.dsl_key => to_h_gsubs(artifact.to_args) }
|
||||
{ artifact.class.dsl_key => artifact.to_args }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def to_h_string_gsubs(string, replace_prefix: true)
|
||||
string = string.to_s.gsub(Dir.home, "$HOME")
|
||||
|
||||
if replace_prefix
|
||||
string.gsub(HOMEBREW_PREFIX, "$(brew --prefix)")
|
||||
else
|
||||
string.gsub(Caskroom.path, "$(brew --prefix)/Caskroom")
|
||||
end
|
||||
end
|
||||
|
||||
def to_h_array_gsubs(array)
|
||||
array.to_a.map do |value|
|
||||
to_h_gsubs(value)
|
||||
end
|
||||
end
|
||||
|
||||
def to_h_hash_gsubs(hash)
|
||||
hash.to_h.transform_values do |value|
|
||||
to_h_gsubs(value)
|
||||
end
|
||||
rescue TypeError
|
||||
to_h_array_gsubs(hash)
|
||||
end
|
||||
|
||||
def to_h_gsubs(value)
|
||||
return value if value.blank?
|
||||
|
||||
if value.respond_to? :to_h
|
||||
to_h_hash_gsubs(value)
|
||||
elsif value.respond_to? :to_a
|
||||
to_h_array_gsubs(value)
|
||||
elsif [true, false].include? value
|
||||
value
|
||||
else
|
||||
to_h_string_gsubs(value)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -237,13 +237,9 @@ module Cask
|
||||
return FromContentLoader.new(cask_source).load(config: config)
|
||||
end
|
||||
|
||||
# convert generic string replacements into actual ones
|
||||
json_cask[:artifacts] = json_cask[:artifacts].map(&method(:from_h_hash_gsubs))
|
||||
json_cask[:caveats] = from_h_string_gsubs(json_cask[:caveats])
|
||||
|
||||
tap = Tap.fetch(json_cask[:tap]) if json_cask[:tap].to_s.include?("/")
|
||||
|
||||
Cask.new(token, tap: tap, source: cask_source, config: config, loaded_from_api: true) do
|
||||
Cask.new(token, tap: tap, source: cask_source, config: config, loaded_from_api: true, loader: self) do
|
||||
version json_cask[:version]
|
||||
|
||||
if json_cask[:sha256] == "no_check"
|
||||
@ -300,45 +296,53 @@ module Cask
|
||||
end
|
||||
|
||||
json_cask[:artifacts].each do |artifact|
|
||||
# convert generic string replacements into actual ones
|
||||
artifact = cask.loader.from_h_hash_gsubs(artifact, appdir)
|
||||
key = artifact.keys.first
|
||||
send(key, *artifact[key])
|
||||
end
|
||||
|
||||
caveats json_cask[:caveats] if json_cask[:caveats].present?
|
||||
if json_cask[:caveats].present?
|
||||
# convert generic string replacements into actual ones
|
||||
json_cask[:caveats] = cask.loader.from_h_string_gsubs(json_cask[:caveats], appdir)
|
||||
caveats json_cask[:caveats]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def from_h_string_gsubs(string)
|
||||
def from_h_string_gsubs(string, appdir)
|
||||
# TODO: HOMEBREW_OLD_PREFIX_PLACEHOLDER can be removed when API JSON is
|
||||
# regenerated with HOMEBREW_PREFIX_PLACEHOLDER.
|
||||
string.to_s
|
||||
.gsub("$HOME", Dir.home)
|
||||
.gsub("$(brew --prefix)", HOMEBREW_PREFIX)
|
||||
.gsub(Cask::HOME_PLACEHOLDER, Dir.home)
|
||||
.gsub(Cask::HOMEBREW_PREFIX_PLACEHOLDER, HOMEBREW_PREFIX)
|
||||
.gsub(Cask::APPDIR_PLACEHOLDER, appdir)
|
||||
.gsub(Cask::HOMEBREW_OLD_PREFIX_PLACEHOLDER, HOMEBREW_PREFIX)
|
||||
end
|
||||
|
||||
def from_h_array_gsubs(array)
|
||||
def from_h_array_gsubs(array, appdir)
|
||||
array.to_a.map do |value|
|
||||
from_h_gsubs(value)
|
||||
from_h_gsubs(value, appdir)
|
||||
end
|
||||
end
|
||||
|
||||
def from_h_hash_gsubs(hash)
|
||||
def from_h_hash_gsubs(hash, appdir)
|
||||
hash.to_h.transform_values do |value|
|
||||
from_h_gsubs(value)
|
||||
from_h_gsubs(value, appdir)
|
||||
end
|
||||
rescue TypeError
|
||||
from_h_array_gsubs(hash)
|
||||
from_h_array_gsubs(hash, appdir)
|
||||
end
|
||||
|
||||
def from_h_gsubs(value)
|
||||
def from_h_gsubs(value, appdir)
|
||||
return value if value.blank?
|
||||
|
||||
if value.respond_to? :to_h
|
||||
from_h_hash_gsubs(value)
|
||||
from_h_hash_gsubs(value, appdir)
|
||||
elsif value.respond_to? :to_a
|
||||
from_h_array_gsubs(value)
|
||||
from_h_array_gsubs(value, appdir)
|
||||
elsif value.is_a? String
|
||||
from_h_string_gsubs(value)
|
||||
from_h_string_gsubs(value, appdir)
|
||||
else
|
||||
value
|
||||
end
|
||||
|
@ -376,6 +376,8 @@ module Cask
|
||||
|
||||
# @api public
|
||||
def appdir
|
||||
return Cask::APPDIR_PLACEHOLDER if Cask.generating_hash?
|
||||
|
||||
cask.config.appdir
|
||||
end
|
||||
end
|
||||
|
@ -2119,7 +2119,7 @@ class Formula
|
||||
"uses_from_macos" => uses_from_macos_elements.uniq,
|
||||
"requirements" => [],
|
||||
"conflicts_with" => conflicts.map(&:name),
|
||||
"caveats" => caveats&.gsub(HOMEBREW_PREFIX, "$(brew --prefix)"),
|
||||
"caveats" => caveats&.gsub(HOMEBREW_PREFIX, HOMEBREW_PREFIX_PLACEHOLDER),
|
||||
"installed" => [],
|
||||
"linked_keg" => linked_version&.to_s,
|
||||
"pinned" => pinned?,
|
||||
|
@ -251,6 +251,7 @@ module Formulary
|
||||
@caveats_string = json_formula["caveats"]
|
||||
def caveats
|
||||
self.class.instance_variable_get(:@caveats_string)
|
||||
&.gsub(HOMEBREW_PREFIX_PLACEHOLDER, HOMEBREW_PREFIX)
|
||||
end
|
||||
|
||||
@tap_git_head_string = json_formula["tap_git_head"]
|
||||
|
@ -64,6 +64,7 @@ HOMEBREW_MACOS_ARM_DEFAULT_PREFIX = "/opt/homebrew"
|
||||
HOMEBREW_MACOS_ARM_DEFAULT_REPOSITORY = HOMEBREW_MACOS_ARM_DEFAULT_PREFIX
|
||||
HOMEBREW_LINUX_DEFAULT_PREFIX = "/home/linuxbrew/.linuxbrew"
|
||||
HOMEBREW_LINUX_DEFAULT_REPOSITORY = "#{HOMEBREW_LINUX_DEFAULT_PREFIX}/Homebrew"
|
||||
HOMEBREW_PREFIX_PLACEHOLDER = "$HOMEBREW_PREFIX"
|
||||
|
||||
HOMEBREW_PULL_API_REGEX =
|
||||
%r{https://api\.github\.com/repos/([\w-]+)/([\w-]+)?/pulls/(\d+)}.freeze
|
||||
|
@ -300,5 +300,18 @@ describe Cask::Cask, :cask do
|
||||
expect(h).to be_a(Hash)
|
||||
expect(JSON.pretty_generate(h["variations"])).to eq expected_sha256_variations.strip
|
||||
end
|
||||
|
||||
it "returns the correct hash placeholders" do
|
||||
described_class.generating_hash!
|
||||
expect(described_class).to be_generating_hash
|
||||
c = Cask::CaskLoader.load("placeholders")
|
||||
h = c.to_hash_with_variations
|
||||
described_class.generated_hash!
|
||||
expect(described_class).not_to be_generating_hash
|
||||
|
||||
expect(h).to be_a(Hash)
|
||||
expect(h["artifacts"].first[:binary].first).to eq "$APPDIR/some/path"
|
||||
expect(h["caveats"]).to eq "$HOMEBREW_PREFIX and $HOME\n"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -117,7 +117,7 @@ describe Cask::Cmd::List, :cask do
|
||||
{
|
||||
"zap": [
|
||||
{
|
||||
"trash": "$HOME/support/fixtures/cask/caffeine/org.example.caffeine.plist"
|
||||
"trash": "#{TEST_FIXTURE_DIR}/cask/caffeine/org.example.caffeine.plist"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -0,0 +1,11 @@
|
||||
cask "placeholders" do
|
||||
version "2.61"
|
||||
sha256 "e44ffa103fbf83f55c8d0b1bea309a43b2880798dae8620b1ee8da5e1095ec68"
|
||||
|
||||
url "file://#{TEST_FIXTURE_DIR}/cask/transmission-2.61.dmg"
|
||||
homepage "https://brew.sh/placeholders"
|
||||
|
||||
binary "#{appdir}/some/path"
|
||||
|
||||
caveats "#{HOMEBREW_PREFIX} and #{Dir.home}"
|
||||
end
|
Loading…
x
Reference in New Issue
Block a user