Clean up files that use to include cachable

These were changed to extend to make it easier to determine
where the classes come to in the extended callback but that
means that the file is somewhat inconsistent. On the one
hand we're using class methods and on the other we're extend
self. This cleans that up but now the diff is atrocious and
the blame is even worse. Oh well...
This commit is contained in:
apainintheneck 2024-02-26 21:21:38 -08:00
parent 5cc1c85a5f
commit bea2dc65fe
3 changed files with 224 additions and 232 deletions

View File

@ -12,80 +12,78 @@ module Homebrew
module Cask module Cask
extend Cachable extend Cachable
class << self private_class_method :cache
private :cache
sig { params(token: String).returns(Hash) } sig { params(token: String).returns(Hash) }
def fetch(token) def self.fetch(token)
Homebrew::API.fetch "cask/#{token}.json" Homebrew::API.fetch "cask/#{token}.json"
end end
sig { params(cask: ::Cask::Cask).returns(::Cask::Cask) } sig { params(cask: ::Cask::Cask).returns(::Cask::Cask) }
def source_download(cask) def self.source_download(cask)
path = cask.ruby_source_path.to_s || "Casks/#{cask.token}.rb" path = cask.ruby_source_path.to_s || "Casks/#{cask.token}.rb"
sha256 = cask.ruby_source_checksum[:sha256] sha256 = cask.ruby_source_checksum[:sha256]
checksum = Checksum.new(sha256) if sha256 checksum = Checksum.new(sha256) if sha256
git_head = cask.tap_git_head || "HEAD" git_head = cask.tap_git_head || "HEAD"
tap = cask.tap&.full_name || "Homebrew/homebrew-cask" tap = cask.tap&.full_name || "Homebrew/homebrew-cask"
download = Homebrew::API::Download.new( download = Homebrew::API::Download.new(
"https://raw.githubusercontent.com/#{tap}/#{git_head}/#{path}", "https://raw.githubusercontent.com/#{tap}/#{git_head}/#{path}",
checksum, checksum,
mirrors: [ mirrors: [
"#{HOMEBREW_API_DEFAULT_DOMAIN}/cask-source/#{File.basename(path)}", "#{HOMEBREW_API_DEFAULT_DOMAIN}/cask-source/#{File.basename(path)}",
], ],
cache: HOMEBREW_CACHE_API_SOURCE/"#{tap}/#{git_head}/Cask", cache: HOMEBREW_CACHE_API_SOURCE/"#{tap}/#{git_head}/Cask",
) )
download.fetch download.fetch
::Cask::CaskLoader::FromPathLoader.new(download.symlink_location) ::Cask::CaskLoader::FromPathLoader.new(download.symlink_location)
.load(config: cask.config) .load(config: cask.config)
end end
sig { returns(T::Boolean) } sig { returns(T::Boolean) }
def download_and_cache_data! def self.download_and_cache_data!
json_casks, updated = Homebrew::API.fetch_json_api_file "cask.jws.json" json_casks, updated = Homebrew::API.fetch_json_api_file "cask.jws.json"
cache["renames"] = {} cache["renames"] = {}
cache["casks"] = json_casks.to_h do |json_cask| cache["casks"] = json_casks.to_h do |json_cask|
token = json_cask["token"] token = json_cask["token"]
json_cask.fetch("old_tokens", []).each do |old_token| json_cask.fetch("old_tokens", []).each do |old_token|
cache["renames"][old_token] = token cache["renames"][old_token] = token
end
[token, json_cask.except("token")]
end end
updated [token, json_cask.except("token")]
end
private :download_and_cache_data!
sig { returns(T::Hash[String, Hash]) }
def all_casks
unless cache.key?("casks")
json_updated = download_and_cache_data!
write_names(regenerate: json_updated)
end
cache.fetch("casks")
end end
sig { returns(T::Hash[String, String]) } updated
def all_renames end
unless cache.key?("renames") private_class_method :download_and_cache_data!
json_updated = download_and_cache_data!
write_names(regenerate: json_updated)
end
cache.fetch("renames") sig { returns(T::Hash[String, Hash]) }
def self.all_casks
unless cache.key?("casks")
json_updated = download_and_cache_data!
write_names(regenerate: json_updated)
end end
sig { params(regenerate: T::Boolean).void } cache.fetch("casks")
def write_names(regenerate: false) end
download_and_cache_data! unless cache.key?("casks")
Homebrew::API.write_names_file(all_casks.keys, "cask", regenerate: regenerate) sig { returns(T::Hash[String, String]) }
def self.all_renames
unless cache.key?("renames")
json_updated = download_and_cache_data!
write_names(regenerate: json_updated)
end end
cache.fetch("renames")
end
sig { params(regenerate: T::Boolean).void }
def self.write_names(regenerate: false)
download_and_cache_data! unless cache.key?("casks")
Homebrew::API.write_names_file(all_casks.keys, "cask", regenerate: regenerate)
end end
end end
end end

View File

@ -12,93 +12,91 @@ module Homebrew
module Formula module Formula
extend Cachable extend Cachable
class << self private_class_method :cache
private :cache
sig { params(name: String).returns(Hash) } sig { params(name: String).returns(Hash) }
def fetch(name) def self.fetch(name)
Homebrew::API.fetch "formula/#{name}.json" Homebrew::API.fetch "formula/#{name}.json"
end end
sig { params(formula: ::Formula).returns(::Formula) } sig { params(formula: ::Formula).returns(::Formula) }
def source_download(formula) def self.source_download(formula)
path = formula.ruby_source_path || "Formula/#{formula.name}.rb" path = formula.ruby_source_path || "Formula/#{formula.name}.rb"
git_head = formula.tap_git_head || "HEAD" git_head = formula.tap_git_head || "HEAD"
tap = formula.tap&.full_name || "Homebrew/homebrew-core" tap = formula.tap&.full_name || "Homebrew/homebrew-core"
download = Homebrew::API::Download.new( download = Homebrew::API::Download.new(
"https://raw.githubusercontent.com/#{tap}/#{git_head}/#{path}", "https://raw.githubusercontent.com/#{tap}/#{git_head}/#{path}",
formula.ruby_source_checksum, formula.ruby_source_checksum,
cache: HOMEBREW_CACHE_API_SOURCE/"#{tap}/#{git_head}/Formula", cache: HOMEBREW_CACHE_API_SOURCE/"#{tap}/#{git_head}/Formula",
) )
download.fetch download.fetch
Formulary.factory(download.symlink_location, Formulary.factory(download.symlink_location,
formula.active_spec_sym, formula.active_spec_sym,
alias_path: formula.alias_path, alias_path: formula.alias_path,
flags: formula.class.build_flags) flags: formula.class.build_flags)
end end
sig { returns(T::Boolean) } sig { returns(T::Boolean) }
def download_and_cache_data! def self.download_and_cache_data!
json_formulae, updated = Homebrew::API.fetch_json_api_file "formula.jws.json" json_formulae, updated = Homebrew::API.fetch_json_api_file "formula.jws.json"
cache["aliases"] = {} cache["aliases"] = {}
cache["renames"] = {} cache["renames"] = {}
cache["formulae"] = json_formulae.to_h do |json_formula| cache["formulae"] = json_formulae.to_h do |json_formula|
json_formula["aliases"].each do |alias_name| json_formula["aliases"].each do |alias_name|
cache["aliases"][alias_name] = json_formula["name"] cache["aliases"][alias_name] = json_formula["name"]
end end
(json_formula["oldnames"] || [json_formula["oldname"]].compact).each do |oldname| (json_formula["oldnames"] || [json_formula["oldname"]].compact).each do |oldname|
cache["renames"][oldname] = json_formula["name"] cache["renames"][oldname] = json_formula["name"]
end
[json_formula["name"], json_formula.except("name")]
end end
updated [json_formula["name"], json_formula.except("name")]
end
private :download_and_cache_data!
sig { returns(T::Hash[String, Hash]) }
def all_formulae
unless cache.key?("formulae")
json_updated = download_and_cache_data!
write_names_and_aliases(regenerate: json_updated)
end
cache["formulae"]
end end
sig { returns(T::Hash[String, String]) } updated
def all_aliases end
unless cache.key?("aliases") private_class_method :download_and_cache_data!
json_updated = download_and_cache_data!
write_names_and_aliases(regenerate: json_updated)
end
cache["aliases"] sig { returns(T::Hash[String, Hash]) }
def self.all_formulae
unless cache.key?("formulae")
json_updated = download_and_cache_data!
write_names_and_aliases(regenerate: json_updated)
end end
sig { returns(T::Hash[String, String]) } cache["formulae"]
def all_renames end
unless cache.key?("renames")
json_updated = download_and_cache_data!
write_names_and_aliases(regenerate: json_updated)
end
cache["renames"] sig { returns(T::Hash[String, String]) }
def self.all_aliases
unless cache.key?("aliases")
json_updated = download_and_cache_data!
write_names_and_aliases(regenerate: json_updated)
end end
sig { params(regenerate: T::Boolean).void } cache["aliases"]
def write_names_and_aliases(regenerate: false) end
download_and_cache_data! unless cache.key?("formulae")
return unless Homebrew::API.write_names_file(all_formulae.keys, "formula", regenerate: regenerate) sig { returns(T::Hash[String, String]) }
def self.all_renames
unless cache.key?("renames")
json_updated = download_and_cache_data!
write_names_and_aliases(regenerate: json_updated)
end
(HOMEBREW_CACHE_API/"formula_aliases.txt").open("w") do |file| cache["renames"]
all_aliases.each do |alias_name, real_name| end
file.puts "#{alias_name}|#{real_name}"
end sig { params(regenerate: T::Boolean).void }
def self.write_names_and_aliases(regenerate: false)
download_and_cache_data! unless cache.key?("formulae")
return unless Homebrew::API.write_names_file(all_formulae.keys, "formula", regenerate: regenerate)
(HOMEBREW_CACHE_API/"formula_aliases.txt").open("w") do |file|
all_aliases.each do |alias_name, real_name|
file.puts "#{alias_name}|#{real_name}"
end end
end end
end end

View File

@ -10,127 +10,123 @@ require "system_command"
# @api private # @api private
module Readall module Readall
extend Cachable extend Cachable
extend SystemCommand::Mixin
class << self # TODO: remove this once the `MacOS` module is undefined on Linux
include SystemCommand::Mixin MACOS_MODULE_REGEX = /\b(MacOS|OS::Mac)(\.|::)\b/
private_constant :MACOS_MODULE_REGEX
# TODO: remove this once the `MacOS` module is undefined on Linux private_class_method :cache
MACOS_MODULE_REGEX = /\b(MacOS|OS::Mac)(\.|::)\b/
private_constant :MACOS_MODULE_REGEX
private :cache def self.valid_ruby_syntax?(ruby_files)
failed = T.let(false, T::Boolean)
def valid_ruby_syntax?(ruby_files) ruby_files.each do |ruby_file|
failed = T.let(false, T::Boolean) # As a side effect, print syntax errors/warnings to `$stderr`.
ruby_files.each do |ruby_file| failed = true if syntax_errors_or_warnings?(ruby_file)
# As a side effect, print syntax errors/warnings to `$stderr`.
failed = true if syntax_errors_or_warnings?(ruby_file)
end
!failed
end end
!failed
end
def valid_aliases?(alias_dir, formula_dir) def self.valid_aliases?(alias_dir, formula_dir)
return true unless alias_dir.directory? return true unless alias_dir.directory?
failed = T.let(false, T::Boolean) failed = T.let(false, T::Boolean)
alias_dir.each_child do |f| alias_dir.each_child do |f|
if !f.symlink? if !f.symlink?
onoe "Non-symlink alias: #{f}" onoe "Non-symlink alias: #{f}"
failed = true failed = true
elsif !f.file? elsif !f.file?
onoe "Non-file alias: #{f}" onoe "Non-file alias: #{f}"
failed = true failed = true
end
if formula_dir.glob("**/#{f.basename}.rb").any?(&:exist?)
onoe "Formula duplicating alias: #{f}"
failed = true
end
end
!failed
end
def valid_formulae?(tap, bottle_tag: nil)
cache[:valid_formulae] ||= {}
success = T.let(true, T::Boolean)
tap.formula_files.each do |file|
valid = cache[:valid_formulae][file]
next if valid == true || valid&.include?(bottle_tag)
formula_name = file.basename(".rb").to_s
formula_contents = file.read(encoding: "UTF-8")
readall_namespace = "ReadallNamespace"
readall_formula_class = Formulary.load_formula(formula_name, file, formula_contents, readall_namespace,
flags: [], ignore_errors: false)
readall_formula = readall_formula_class.new(formula_name, file, :stable, tap: tap)
readall_formula.to_hash
# TODO: Remove check for MACOS_MODULE_REGEX once the `MacOS` module is undefined on Linux
cache[:valid_formulae][file] = if readall_formula.on_system_blocks_exist? ||
formula_contents.match?(MACOS_MODULE_REGEX)
[bottle_tag, *cache[:valid_formulae][file]]
else
true
end
rescue Interrupt
raise
rescue Exception => e # rubocop:disable Lint/RescueException
onoe "Invalid formula (#{bottle_tag}): #{file}"
$stderr.puts e
success = false
end
success
end
def valid_casks?(_tap, os_name: nil, arch: nil)
true
end
def valid_tap?(tap, aliases: false, no_simulate: false, os_arch_combinations: OnSystem::ALL_OS_ARCH_COMBINATIONS)
success = true
if aliases
valid_aliases = valid_aliases?(tap.alias_dir, tap.formula_dir)
success = false unless valid_aliases
end end
if no_simulate if formula_dir.glob("**/#{f.basename}.rb").any?(&:exist?)
success = false unless valid_formulae?(tap) onoe "Formula duplicating alias: #{f}"
success = false unless valid_casks?(tap) failed = true
end
end
!failed
end
def self.valid_formulae?(tap, bottle_tag: nil)
cache[:valid_formulae] ||= {}
success = T.let(true, T::Boolean)
tap.formula_files.each do |file|
valid = cache[:valid_formulae][file]
next if valid == true || valid&.include?(bottle_tag)
formula_name = file.basename(".rb").to_s
formula_contents = file.read(encoding: "UTF-8")
readall_namespace = "ReadallNamespace"
readall_formula_class = Formulary.load_formula(formula_name, file, formula_contents, readall_namespace,
flags: [], ignore_errors: false)
readall_formula = readall_formula_class.new(formula_name, file, :stable, tap: tap)
readall_formula.to_hash
# TODO: Remove check for MACOS_MODULE_REGEX once the `MacOS` module is undefined on Linux
cache[:valid_formulae][file] = if readall_formula.on_system_blocks_exist? ||
formula_contents.match?(MACOS_MODULE_REGEX)
[bottle_tag, *cache[:valid_formulae][file]]
else else
os_arch_combinations.each do |os, arch| true
bottle_tag = Utils::Bottles::Tag.new(system: os, arch: arch) end
next unless bottle_tag.valid_combination? rescue Interrupt
raise
rescue Exception => e # rubocop:disable Lint/RescueException
onoe "Invalid formula (#{bottle_tag}): #{file}"
$stderr.puts e
success = false
end
success
end
Homebrew::SimulateSystem.with os: os, arch: arch do def self.valid_casks?(_tap, os_name: nil, arch: nil)
success = false unless valid_formulae?(tap, bottle_tag: bottle_tag) true
success = false unless valid_casks?(tap, os_name: os, arch: arch) end
end
def self.valid_tap?(tap, aliases: false, no_simulate: false,
os_arch_combinations: OnSystem::ALL_OS_ARCH_COMBINATIONS)
success = true
if aliases
valid_aliases = valid_aliases?(tap.alias_dir, tap.formula_dir)
success = false unless valid_aliases
end
if no_simulate
success = false unless valid_formulae?(tap)
success = false unless valid_casks?(tap)
else
os_arch_combinations.each do |os, arch|
bottle_tag = Utils::Bottles::Tag.new(system: os, arch: arch)
next unless bottle_tag.valid_combination?
Homebrew::SimulateSystem.with os: os, arch: arch do
success = false unless valid_formulae?(tap, bottle_tag: bottle_tag)
success = false unless valid_casks?(tap, os_name: os, arch: arch)
end end
end end
success
end end
private success
end
def syntax_errors_or_warnings?(filename) private_class_method def self.syntax_errors_or_warnings?(filename)
# Retrieve messages about syntax errors/warnings printed to `$stderr`. # Retrieve messages about syntax errors/warnings printed to `$stderr`.
_, err, status = system_command(RUBY_PATH, args: ["-c", "-w", filename], print_stderr: false) _, err, status = system_command(RUBY_PATH, args: ["-c", "-w", filename], print_stderr: false)
# Ignore unnecessary warning about named capture conflicts. # Ignore unnecessary warning about named capture conflicts.
# See https://bugs.ruby-lang.org/issues/12359. # See https://bugs.ruby-lang.org/issues/12359.
messages = err.lines messages = err.lines
.grep_v(/named capture conflicts a local variable/) .grep_v(/named capture conflicts a local variable/)
.join .join
$stderr.print messages $stderr.print messages
# Only syntax errors result in a non-zero status code. To detect syntax # Only syntax errors result in a non-zero status code. To detect syntax
# warnings we also need to inspect the output to `$stderr`. # warnings we also need to inspect the output to `$stderr`.
!status.success? || !messages.chomp.empty? !status.success? || !messages.chomp.empty?
end
end end
end end