
- I originally thought this was short for "function", but upon closer inspection all its usages are to do with filenames. So, use "filename", it's clearer.
141 lines
4.5 KiB
Ruby
141 lines
4.5 KiB
Ruby
# typed: true
|
|
# frozen_string_literal: true
|
|
|
|
require "formula"
|
|
require "cask/cask_loader"
|
|
|
|
# Helper module for validating syntax in taps.
|
|
#
|
|
# @api private
|
|
module Readall
|
|
class << self
|
|
def valid_ruby_syntax?(ruby_files)
|
|
failed = T.let(false, T::Boolean)
|
|
ruby_files.each do |ruby_file|
|
|
# As a side effect, print syntax errors/warnings to `$stderr`.
|
|
failed = true if syntax_errors_or_warnings?(ruby_file)
|
|
end
|
|
!failed
|
|
end
|
|
|
|
def valid_aliases?(alias_dir, formula_dir)
|
|
return true unless alias_dir.directory?
|
|
|
|
failed = T.let(false, T::Boolean)
|
|
alias_dir.each_child do |f|
|
|
if !f.symlink?
|
|
onoe "Non-symlink alias: #{f}"
|
|
failed = true
|
|
elsif !f.file?
|
|
onoe "Non-file alias: #{f}"
|
|
failed = true
|
|
end
|
|
|
|
if (formula_dir/"#{f.basename}.rb").exist?
|
|
onoe "Formula duplicating alias: #{f}"
|
|
failed = true
|
|
end
|
|
end
|
|
!failed
|
|
end
|
|
|
|
def valid_formulae?(formulae, bottle_tag: nil)
|
|
success = T.let(true, T::Boolean)
|
|
formulae.each do |file|
|
|
base = Formulary.factory(file)
|
|
next if bottle_tag.blank? || !base.path.exist? || !base.class.on_system_blocks_exist?
|
|
|
|
formula_contents = base.path.read
|
|
|
|
readall_namespace = Formulary.class_s("Readall#{bottle_tag.to_sym.capitalize}")
|
|
readall_formula_class = Formulary.load_formula(base.name, base.path, formula_contents, readall_namespace,
|
|
flags: base.class.build_flags, ignore_errors: true)
|
|
readall_formula_class.new(base.name, base.path, :stable,
|
|
alias_path: base.alias_path, force_bottle: base.force_bottle)
|
|
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?(casks, bottle_tag: nil)
|
|
return true if bottle_tag.present? && bottle_tag.system == :linux
|
|
|
|
success = T.let(true, T::Boolean)
|
|
casks.each do |file|
|
|
cask = Cask::CaskLoader.load(file)
|
|
|
|
# Fine to have missing URLs for unsupported macOS
|
|
macos_req = cask.depends_on.macos
|
|
next if macos_req&.version && Array(macos_req.version).none? do |macos_version|
|
|
bottle_tag.to_macos_version.public_send(macos_req.comparator, macos_version)
|
|
end
|
|
|
|
raise "Missing URL" if cask.url.nil?
|
|
rescue Interrupt
|
|
raise
|
|
rescue Exception => e # rubocop:disable Lint/RescueException
|
|
onoe "Invalid cask (#{bottle_tag}): #{file}"
|
|
$stderr.puts e
|
|
success = false
|
|
end
|
|
success
|
|
end
|
|
|
|
def valid_tap?(tap, options = {})
|
|
success = true
|
|
if options[:aliases]
|
|
valid_aliases = valid_aliases?(tap.alias_dir, tap.formula_dir)
|
|
success = false unless valid_aliases
|
|
end
|
|
if options[:no_simulate]
|
|
success = false unless valid_formulae?(tap.formula_files)
|
|
success = false unless valid_casks?(tap.cask_files)
|
|
else
|
|
arches = [:arm, :intel]
|
|
os_names = [*MacOSVersions::SYMBOLS.keys, :linux]
|
|
arches.each do |arch|
|
|
os_names.each do |os_name|
|
|
bottle_tag = Utils::Bottles::Tag.new(system: os_name, arch: arch)
|
|
next unless bottle_tag.valid_combination?
|
|
|
|
Homebrew::SimulateSystem.arch = arch
|
|
Homebrew::SimulateSystem.os = os_name
|
|
|
|
success = false unless valid_formulae?(tap.formula_files, bottle_tag: bottle_tag)
|
|
success = false unless valid_casks?(tap.cask_files, bottle_tag: bottle_tag)
|
|
|
|
Homebrew::SimulateSystem.clear
|
|
end
|
|
end
|
|
end
|
|
success
|
|
end
|
|
|
|
private
|
|
|
|
def syntax_errors_or_warnings?(filename)
|
|
# Retrieve messages about syntax errors/warnings printed to `$stderr`.
|
|
_, err, status = system_command(RUBY_PATH, args: ["-c", "-w", filename], print_stderr: false)
|
|
|
|
# Ignore unnecessary warning about named capture conflicts.
|
|
# See https://bugs.ruby-lang.org/issues/12359.
|
|
messages = err.lines
|
|
.grep_v(/named capture conflicts a local variable/)
|
|
.join
|
|
|
|
$stderr.print messages
|
|
|
|
# Only syntax errors result in a non-zero status code. To detect syntax
|
|
# warnings we also need to inspect the output to `$stderr`.
|
|
!status.success? || !messages.chomp.empty?
|
|
end
|
|
end
|
|
end
|
|
|
|
require "extend/os/readall"
|