Add --os=all and --arch=all options.
This commit is contained in:
parent
f7b3225574
commit
486c3765ce
@ -33,13 +33,15 @@ module Homebrew
|
||||
end
|
||||
|
||||
def freeze_named_args!(named_args, cask_options:)
|
||||
options = {}
|
||||
options[:force_bottle] = true if self[:force_bottle?]
|
||||
options[:override_spec] = :head if self[:HEAD?]
|
||||
options[:flags] = flags_only unless flags_only.empty?
|
||||
self[:named] = NamedArgs.new(
|
||||
*named_args.freeze,
|
||||
override_spec: spec(nil),
|
||||
force_bottle: self[:force_bottle?],
|
||||
flags: flags_only,
|
||||
cask_options: cask_options,
|
||||
parent: self,
|
||||
parent: self,
|
||||
cask_options: cask_options,
|
||||
**options,
|
||||
)
|
||||
end
|
||||
|
||||
@ -98,6 +100,44 @@ module Homebrew
|
||||
return :cask if cask? && !formula?
|
||||
end
|
||||
|
||||
sig { returns(T::Array[[Symbol, Symbol]]) }
|
||||
def os_arch_combinations
|
||||
skip_invalid_combinations = false
|
||||
|
||||
oses = case (os_sym = os&.to_sym)
|
||||
when nil
|
||||
[SimulateSystem.current_os]
|
||||
when :all
|
||||
skip_invalid_combinations = true
|
||||
|
||||
[
|
||||
*MacOSVersions::SYMBOLS.keys,
|
||||
:linux,
|
||||
]
|
||||
else
|
||||
[os_sym]
|
||||
end
|
||||
|
||||
arches = case (arch_sym = arch&.to_sym)
|
||||
when nil
|
||||
[SimulateSystem.current_arch]
|
||||
when :all
|
||||
skip_invalid_combinations = true
|
||||
OnSystem::ARCH_OPTIONS
|
||||
else
|
||||
[arch_sym]
|
||||
end
|
||||
|
||||
oses.product(arches).select do |os, arch|
|
||||
if skip_invalid_combinations
|
||||
bottle_tag = Utils::Bottles::Tag.new(system: os, arch: arch)
|
||||
bottle_tag.valid_combination?
|
||||
else
|
||||
true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def option_to_name(option)
|
||||
@ -124,14 +164,6 @@ module Homebrew
|
||||
@cli_args.freeze
|
||||
end
|
||||
|
||||
def spec(default = :stable)
|
||||
if self[:HEAD?]
|
||||
:head
|
||||
else
|
||||
default
|
||||
end
|
||||
end
|
||||
|
||||
def respond_to_missing?(method_name, *)
|
||||
@table.key?(method_name)
|
||||
end
|
||||
|
||||
@ -240,6 +240,9 @@ module Homebrew
|
||||
sig { returns(T.nilable(T::Array[String])) }
|
||||
def only; end
|
||||
|
||||
sig { returns(T.nilable(String)) }
|
||||
def os; end
|
||||
|
||||
sig { returns(T.nilable(T::Array[String])) }
|
||||
def except; end
|
||||
|
||||
@ -270,6 +273,9 @@ module Homebrew
|
||||
sig { returns(T::Boolean) }
|
||||
def s?; end
|
||||
|
||||
sig { returns(T.nilable(String)) }
|
||||
def arch; end
|
||||
|
||||
sig { returns(T.nilable(String)) }
|
||||
def appdir; end
|
||||
|
||||
|
||||
@ -11,7 +11,24 @@ module Homebrew
|
||||
#
|
||||
# @api private
|
||||
class NamedArgs < Array
|
||||
def initialize(*args, parent: Args.new, override_spec: nil, force_bottle: false, flags: [], cask_options: false)
|
||||
sig {
|
||||
params(
|
||||
args: String,
|
||||
parent: Args,
|
||||
override_spec: Symbol,
|
||||
force_bottle: T::Boolean,
|
||||
flags: T::Array[String],
|
||||
cask_options: T::Boolean,
|
||||
).void
|
||||
}
|
||||
def initialize(
|
||||
*args,
|
||||
parent: Args.new,
|
||||
override_spec: T.unsafe(nil),
|
||||
force_bottle: T.unsafe(nil),
|
||||
flags: T.unsafe(nil),
|
||||
cask_options: false
|
||||
)
|
||||
require "cask/cask"
|
||||
require "cask/cask_loader"
|
||||
require "formulary"
|
||||
@ -50,11 +67,17 @@ module Homebrew
|
||||
warn: T::Boolean,
|
||||
).returns(T::Array[T.any(Formula, Keg, Cask::Cask)])
|
||||
}
|
||||
def to_formulae_and_casks(only: parent&.only_formula_or_cask, ignore_unavailable: nil, method: nil, uniq: true,
|
||||
warn: true)
|
||||
def to_formulae_and_casks(
|
||||
only: parent&.only_formula_or_cask,
|
||||
ignore_unavailable: nil,
|
||||
method: T.unsafe(nil),
|
||||
uniq: true,
|
||||
warn: T.unsafe(nil)
|
||||
)
|
||||
@to_formulae_and_casks ||= {}
|
||||
@to_formulae_and_casks[only] ||= downcased_unique_named.flat_map do |name|
|
||||
load_formula_or_cask(name, only: only, method: method, warn: warn)
|
||||
options = { warn: warn }.compact
|
||||
load_formula_or_cask(name, only: only, method: method, **options)
|
||||
rescue FormulaUnreadableError, FormulaClassUnavailableError,
|
||||
TapFormulaUnreadableError, TapFormulaClassUnavailableError,
|
||||
Cask::CaskUnreadableError
|
||||
@ -88,14 +111,15 @@ module Homebrew
|
||||
end.uniq.freeze
|
||||
end
|
||||
|
||||
def load_formula_or_cask(name, only: nil, method: nil, warn: true)
|
||||
def load_formula_or_cask(name, only: nil, method: nil, warn: nil)
|
||||
unreadable_error = nil
|
||||
|
||||
if only != :cask
|
||||
begin
|
||||
formula = case method
|
||||
when nil, :factory
|
||||
Formulary.factory(name, *spec, force_bottle: @force_bottle, flags: @flags, warn: warn)
|
||||
options = { warn: warn, force_bottle: @force_bottle, flags: @flags }.compact
|
||||
Formulary.factory(name, *@override_spec, **options)
|
||||
when :resolve
|
||||
resolve_formula(name)
|
||||
when :latest_kegs
|
||||
@ -126,7 +150,8 @@ module Homebrew
|
||||
|
||||
begin
|
||||
config = Cask::Config.from_args(@parent) if @cask_options
|
||||
cask = Cask::CaskLoader.load(name, config: config, warn: warn)
|
||||
options = { warn: warn }.compact
|
||||
cask = Cask::CaskLoader.load(name, config: config, **options)
|
||||
|
||||
if unreadable_error.present?
|
||||
onoe <<~EOS
|
||||
@ -177,7 +202,7 @@ module Homebrew
|
||||
private :load_formula_or_cask
|
||||
|
||||
def resolve_formula(name)
|
||||
Formulary.resolve(name, spec: spec, force_bottle: @force_bottle, flags: @flags)
|
||||
Formulary.resolve(name, **{ spec: @override_spec, force_bottle: @force_bottle, flags: @flags }.compact)
|
||||
end
|
||||
private :resolve_formula
|
||||
|
||||
@ -306,11 +331,6 @@ module Homebrew
|
||||
end.uniq
|
||||
end
|
||||
|
||||
def spec
|
||||
@override_spec
|
||||
end
|
||||
private :spec
|
||||
|
||||
def resolve_kegs(name)
|
||||
raise UsageError if name.blank?
|
||||
|
||||
|
||||
@ -16,6 +16,12 @@ module Homebrew
|
||||
|
||||
If <formula> is provided, display the file or directory used to cache <formula>.
|
||||
EOS
|
||||
flag "--os=",
|
||||
description: "Show cache file for the given operating system." \
|
||||
"(Pass `all` to show cache files for all operating systems.)"
|
||||
flag "--arch=",
|
||||
description: "Show cache file for the given CPU architecture." \
|
||||
"(Pass `all` to show cache files for all architectures.)"
|
||||
switch "-s", "--build-from-source",
|
||||
description: "Show the cache file used when building from source."
|
||||
switch "--force-bottle",
|
||||
@ -31,6 +37,8 @@ module Homebrew
|
||||
|
||||
conflicts "--build-from-source", "--force-bottle", "--bottle-tag", "--HEAD", "--cask"
|
||||
conflicts "--formula", "--cask"
|
||||
conflicts "--os", "--bottle-tag"
|
||||
conflicts "--arch", "--bottle-tag"
|
||||
|
||||
named_args [:formula, :cask]
|
||||
end
|
||||
@ -46,21 +54,62 @@ module Homebrew
|
||||
end
|
||||
|
||||
formulae_or_casks = args.named.to_formulae_and_casks
|
||||
os_arch_combinations = args.os_arch_combinations
|
||||
|
||||
formulae_or_casks.each do |formula_or_cask|
|
||||
if formula_or_cask.is_a? Formula
|
||||
print_formula_cache formula_or_cask, args: args
|
||||
case formula_or_cask
|
||||
when Formula
|
||||
formula = T.cast(formula_or_cask, Formula)
|
||||
ref = formula.loaded_from_api? ? formula.full_name : formula.path
|
||||
|
||||
os_arch_combinations.each do |os, arch|
|
||||
SimulateSystem.with os: os, arch: arch do
|
||||
Formulary.clear_cache
|
||||
formula = Formulary.factory(ref)
|
||||
print_formula_cache(formula, os: os, arch: arch, args: args)
|
||||
end
|
||||
end
|
||||
else
|
||||
print_cask_cache formula_or_cask
|
||||
cask = formula_or_cask
|
||||
ref = cask.loaded_from_api? ? cask.full_token : cask.sourcefile_path
|
||||
|
||||
os_arch_combinations.each do |os, arch|
|
||||
next if os == :linux
|
||||
|
||||
SimulateSystem.with os: os, arch: arch do
|
||||
cask = Cask::CaskLoader.load(ref)
|
||||
print_cask_cache(cask)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
sig { params(formula: Formula, args: CLI::Args).void }
|
||||
def self.print_formula_cache(formula, args:)
|
||||
if fetch_bottle?(formula, force_bottle: args.force_bottle?, bottle_tag: args.bottle_tag&.to_sym,
|
||||
build_from_source_formulae: args.build_from_source_formulae)
|
||||
puts formula.bottle_for_tag(args.bottle_tag&.to_sym)&.cached_download
|
||||
sig { params(formula: Formula, os: Symbol, arch: Symbol, args: CLI::Args).void }
|
||||
def self.print_formula_cache(formula, os:, arch:, args:)
|
||||
if fetch_bottle?(
|
||||
formula,
|
||||
force_bottle: args.force_bottle?,
|
||||
bottle_tag: args.bottle_tag&.to_sym,
|
||||
build_from_source_formulae: args.build_from_source_formulae,
|
||||
os: args.os&.to_sym,
|
||||
arch: args.arch&.to_sym,
|
||||
)
|
||||
bottle_tag = if (bottle_tag = args.bottle_tag&.to_sym)
|
||||
# TODO: odeprecate "--bottle-tag"
|
||||
Utils::Bottles::Tag.from_symbol(bottle_tag)
|
||||
else
|
||||
Utils::Bottles::Tag.new(system: os, arch: arch)
|
||||
end
|
||||
|
||||
bottle = formula.bottle_for_tag(bottle_tag)
|
||||
|
||||
if bottle.nil?
|
||||
opoo "Bottle for tag #{bottle_tag.to_sym.inspect} is unavailable."
|
||||
return
|
||||
end
|
||||
|
||||
puts bottle.cached_download
|
||||
elsif args.HEAD?
|
||||
puts formula.head.cached_download
|
||||
else
|
||||
|
||||
@ -18,12 +18,14 @@ module Homebrew
|
||||
Download a bottle (if available) or source packages for <formula>e
|
||||
and binaries for <cask>s. For files, also print SHA-256 checksums.
|
||||
EOS
|
||||
# This is needed for downloading ARM casks in CI.
|
||||
flag "--arch=",
|
||||
description: "Download for the given CPU architecture.",
|
||||
hidden: true
|
||||
flag "--bottle-tag=",
|
||||
description: "Download a bottle for given tag."
|
||||
flag "--os=",
|
||||
description: "Download for the given operating system." \
|
||||
"(Pass `all` to download for all operating systems.)"
|
||||
flag "--arch=",
|
||||
description: "Download for the given CPU architecture." \
|
||||
"(Pass `all` to download for all architectures.)"
|
||||
flag "--bottle-tag=",
|
||||
description: "Download a bottle for given tag."
|
||||
switch "--HEAD",
|
||||
description: "Fetch HEAD version instead of stable version."
|
||||
switch "-f", "--force",
|
||||
@ -60,6 +62,8 @@ module Homebrew
|
||||
conflicts "--cask", "--force-bottle"
|
||||
conflicts "--cask", "--bottle-tag"
|
||||
conflicts "--formula", "--cask"
|
||||
conflicts "--os", "--bottle-tag"
|
||||
conflicts "--arch", "--bottle-tag"
|
||||
|
||||
named_args [:formula, :cask], min: 1
|
||||
end
|
||||
@ -68,17 +72,14 @@ module Homebrew
|
||||
def self.fetch
|
||||
args = fetch_args.parse
|
||||
|
||||
if (arch = args.arch)
|
||||
SimulateSystem.arch = arch.to_sym
|
||||
end
|
||||
Formulary.enable_factory_cache!
|
||||
|
||||
bucket = if args.deps?
|
||||
args.named.to_formulae_and_casks.flat_map do |formula_or_cask|
|
||||
case formula_or_cask
|
||||
when Formula
|
||||
f = formula_or_cask
|
||||
|
||||
[f, *f.recursive_dependencies.map(&:to_formula)]
|
||||
formula = formula_or_cask
|
||||
[formula, *formula.recursive_dependencies.map(&:to_formula)]
|
||||
else
|
||||
formula_or_cask
|
||||
end
|
||||
@ -87,52 +88,92 @@ module Homebrew
|
||||
args.named.to_formulae_and_casks
|
||||
end.uniq
|
||||
|
||||
os_arch_combinations = args.os_arch_combinations
|
||||
|
||||
puts "Fetching: #{bucket * ", "}" if bucket.size > 1
|
||||
bucket.each do |formula_or_cask|
|
||||
case formula_or_cask
|
||||
when Formula
|
||||
f = formula_or_cask
|
||||
formula = T.cast(formula_or_cask, Formula)
|
||||
ref = formula.loaded_from_api? ? formula.full_name : formula.path
|
||||
|
||||
f.print_tap_action verb: "Fetching"
|
||||
os_arch_combinations.each do |os, arch|
|
||||
SimulateSystem.with os: os, arch: arch do
|
||||
Formulary.clear_cache
|
||||
formula = Formulary.factory(ref)
|
||||
|
||||
fetched_bottle = false
|
||||
if fetch_bottle?(f, force_bottle: args.force_bottle?, bottle_tag: args.bottle_tag&.to_sym,
|
||||
build_from_source_formulae: args.build_from_source_formulae)
|
||||
begin
|
||||
f.clear_cache if args.force?
|
||||
f.fetch_bottle_tab
|
||||
fetch_formula(f.bottle_for_tag(args.bottle_tag&.to_sym), args: args)
|
||||
rescue Interrupt
|
||||
raise
|
||||
rescue => e
|
||||
raise if Homebrew::EnvConfig.developer?
|
||||
formula.print_tap_action verb: "Fetching"
|
||||
|
||||
fetched_bottle = false
|
||||
onoe e.message
|
||||
opoo "Bottle fetch failed, fetching the source instead."
|
||||
else
|
||||
fetched_bottle = true
|
||||
if fetch_bottle?(
|
||||
formula,
|
||||
force_bottle: args.force_bottle?,
|
||||
bottle_tag: args.bottle_tag&.to_sym,
|
||||
build_from_source_formulae: args.build_from_source_formulae,
|
||||
os: args.os&.to_sym,
|
||||
arch: args.arch&.to_sym,
|
||||
)
|
||||
begin
|
||||
formula.clear_cache if args.force?
|
||||
|
||||
# TODO: Deprecate `--bottle-tag`.
|
||||
bottle_tag = if (bottle_tag = args.bottle_tag&.to_sym)
|
||||
Utils::Bottles::Tag.from_symbol(bottle_tag)
|
||||
else
|
||||
Utils::Bottles::Tag.new(system: os, arch: arch)
|
||||
end
|
||||
|
||||
bottle = formula.bottle_for_tag(bottle_tag)
|
||||
|
||||
if bottle.nil?
|
||||
opoo "Bottle for tag #{bottle_tag.to_sym.inspect} is unavailable."
|
||||
next
|
||||
end
|
||||
|
||||
formula.fetch_bottle_tab
|
||||
fetch_formula(bottle, args: args)
|
||||
rescue Interrupt
|
||||
raise
|
||||
rescue => e
|
||||
raise if Homebrew::EnvConfig.developer?
|
||||
|
||||
fetched_bottle = false
|
||||
onoe e.message
|
||||
opoo "Bottle fetch failed, fetching the source instead."
|
||||
else
|
||||
fetched_bottle = true
|
||||
end
|
||||
end
|
||||
|
||||
next if fetched_bottle
|
||||
|
||||
fetch_formula(formula, args: args)
|
||||
|
||||
formula.resources.each do |r|
|
||||
fetch_resource(r, args: args)
|
||||
r.patches.each { |p| fetch_patch(p, args: args) if p.external? }
|
||||
end
|
||||
|
||||
formula.patchlist.each { |p| fetch_patch(p, args: args) if p.external? }
|
||||
end
|
||||
end
|
||||
|
||||
next if fetched_bottle
|
||||
|
||||
fetch_formula(f, args: args)
|
||||
|
||||
f.resources.each do |r|
|
||||
fetch_resource(r, args: args)
|
||||
r.patches.each { |p| fetch_patch(p, args: args) if p.external? }
|
||||
end
|
||||
|
||||
f.patchlist.each { |p| fetch_patch(p, args: args) if p.external? }
|
||||
else
|
||||
cask = formula_or_cask
|
||||
ref = cask.loaded_from_api? ? cask.full_token : cask.sourcefile_path
|
||||
|
||||
quarantine = args.quarantine?
|
||||
quarantine = true if quarantine.nil?
|
||||
os_arch_combinations.each do |os, arch|
|
||||
next if os == :linux
|
||||
|
||||
download = Cask::Download.new(cask, quarantine: quarantine)
|
||||
fetch_cask(download, args: args)
|
||||
SimulateSystem.with os: os, arch: arch do
|
||||
cask = Cask::CaskLoader.load(ref)
|
||||
|
||||
quarantine = args.quarantine?
|
||||
quarantine = true if quarantine.nil?
|
||||
|
||||
download = Cask::Download.new(cask, quarantine: quarantine)
|
||||
fetch_cask(download, args: args)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -29,10 +29,10 @@ module Homebrew
|
||||
locally available formulae and casks and skip style checks. Will exit with a
|
||||
non-zero status if any errors are found.
|
||||
EOS
|
||||
# This is needed for auditing ARM casks in CI.
|
||||
flag "--arch=",
|
||||
description: "Audit the given CPU architecture.",
|
||||
hidden: true
|
||||
flag "--os=",
|
||||
description: "Audit the given operating system. (Pass `all` to audit all operating systems.)"
|
||||
flag "--arch=",
|
||||
description: "Audit the given CPU architecture. (Pass `all` to audit all architectures.)"
|
||||
switch "--strict",
|
||||
description: "Run additional, stricter style checks."
|
||||
switch "--git",
|
||||
@ -106,9 +106,9 @@ module Homebrew
|
||||
def self.audit
|
||||
args = audit_args.parse
|
||||
|
||||
if (arch = args.arch)
|
||||
SimulateSystem.arch = arch.to_sym
|
||||
end
|
||||
Formulary.enable_factory_cache!
|
||||
|
||||
os_arch_combinations = args.os_arch_combinations
|
||||
|
||||
Homebrew.auditing = true
|
||||
inject_dump_stats!(FormulaAuditor, /^audit_/) if args.audit_debug?
|
||||
@ -200,7 +200,12 @@ module Homebrew
|
||||
spdx_license_data = SPDX.license_data
|
||||
spdx_exception_data = SPDX.exception_data
|
||||
new_formula_problem_lines = T.let([], T::Array[String])
|
||||
formula_results = audit_formulae.sort.to_h do |f|
|
||||
|
||||
formula_results = {}
|
||||
|
||||
audit_formulae.sort.each do |f|
|
||||
path = f.path
|
||||
|
||||
only = only_cops ? ["style"] : args.only
|
||||
options = {
|
||||
new_formula: new_formula,
|
||||
@ -214,63 +219,83 @@ module Homebrew
|
||||
style_offenses: style_offenses&.for_path(f.path),
|
||||
}.compact
|
||||
|
||||
audit_proc = proc { FormulaAuditor.new(f, **options).tap(&:audit) }
|
||||
os_arch_combinations.each do |os, arch|
|
||||
SimulateSystem.with os: os, arch: arch do
|
||||
odebug "Auditing Formula #{f} on os #{os} and arch #{arch}"
|
||||
|
||||
# Audit requires full Ruby source so disable API.
|
||||
# We shouldn't do this for taps however so that we don't unnecessarily require a full Homebrew/core clone.
|
||||
fa = if f.core_formula?
|
||||
without_api(&audit_proc)
|
||||
else
|
||||
audit_proc.call
|
||||
end
|
||||
Formulary.clear_cache
|
||||
f = Formulary.factory(path)
|
||||
|
||||
if fa.problems.any? || fa.new_formula_problems.any?
|
||||
formula_count += 1
|
||||
problem_count += fa.problems.size
|
||||
problem_lines = format_problem_lines(fa.problems)
|
||||
corrected_problem_count += options.fetch(:style_offenses, []).count(&:corrected?)
|
||||
new_formula_problem_lines += format_problem_lines(fa.new_formula_problems)
|
||||
if args.display_filename?
|
||||
puts problem_lines.map { |s| "#{f.path}: #{s}" }
|
||||
else
|
||||
puts "#{f.full_name}:", problem_lines.map { |s| " #{s}" }
|
||||
audit_proc = proc { FormulaAuditor.new(f, **options).tap(&:audit) }
|
||||
|
||||
# Audit requires full Ruby source so disable API.
|
||||
# We shouldn't do this for taps however so that we don't unnecessarily require a full Homebrew/core clone.
|
||||
fa = if f.core_formula?
|
||||
without_api(&audit_proc)
|
||||
else
|
||||
audit_proc.call
|
||||
end
|
||||
|
||||
if fa.problems.any? || fa.new_formula_problems.any?
|
||||
formula_count += 1
|
||||
problem_count += fa.problems.size
|
||||
problem_lines = format_problem_lines(fa.problems)
|
||||
corrected_problem_count += options.fetch(:style_offenses, []).count(&:corrected?)
|
||||
new_formula_problem_lines += format_problem_lines(fa.new_formula_problems)
|
||||
if args.display_filename?
|
||||
puts problem_lines.map { |s| "#{f.path}: #{s}" }
|
||||
else
|
||||
puts "#{f.full_name}:", problem_lines.map { |s| " #{s}" }
|
||||
end
|
||||
end
|
||||
|
||||
formula_results.deep_merge!({ f.path => fa.problems + fa.new_formula_problems })
|
||||
end
|
||||
end
|
||||
|
||||
[f.path, fa.problems + fa.new_formula_problems]
|
||||
end
|
||||
|
||||
cask_results = if audit_casks.empty?
|
||||
{}
|
||||
else
|
||||
cask_results = {}
|
||||
|
||||
if audit_casks.any?
|
||||
require "cask/auditor"
|
||||
|
||||
if args.display_failures_only?
|
||||
odeprecated "`brew audit <cask> --display-failures-only`", "`brew audit <cask>` without the argument"
|
||||
end
|
||||
end
|
||||
|
||||
require "cask/auditor"
|
||||
audit_casks.each do |cask|
|
||||
path = cask.sourcefile_path
|
||||
|
||||
audit_casks.to_h do |cask|
|
||||
odebug "Auditing Cask #{cask}"
|
||||
errors = Cask::Auditor.audit(
|
||||
cask,
|
||||
# For switches, we add `|| nil` so that `nil` will be passed
|
||||
# instead of `false` if they aren't set.
|
||||
# This way, we can distinguish between "not set" and "set to false".
|
||||
audit_online: (args.online? || nil),
|
||||
audit_strict: (args.strict? || nil),
|
||||
os_arch_combinations.each do |os, arch|
|
||||
next if os == :linux
|
||||
|
||||
# No need for `|| nil` for `--[no-]signing`
|
||||
# because boolean switches are already `nil` if not passed
|
||||
audit_signing: args.signing?,
|
||||
audit_new_cask: (args.new_cask? || nil),
|
||||
audit_token_conflicts: (args.token_conflicts? || nil),
|
||||
quarantine: true,
|
||||
any_named_args: !no_named_args,
|
||||
only: args.only,
|
||||
except: args.except,
|
||||
)
|
||||
[cask.sourcefile_path, errors]
|
||||
SimulateSystem.with os: os, arch: arch do
|
||||
odebug "Auditing Cask #{cask} on os #{os} and arch #{arch}"
|
||||
|
||||
cask = Cask::CaskLoader.load(path)
|
||||
|
||||
errors = Cask::Auditor.audit(
|
||||
cask,
|
||||
# For switches, we add `|| nil` so that `nil` will be passed
|
||||
# instead of `false` if they aren't set.
|
||||
# This way, we can distinguish between "not set" and "set to false".
|
||||
audit_online: (args.online? || nil),
|
||||
audit_strict: (args.strict? || nil),
|
||||
|
||||
# No need for `|| nil` for `--[no-]signing`
|
||||
# because boolean switches are already `nil` if not passed
|
||||
audit_signing: args.signing?,
|
||||
audit_new_cask: (args.new_cask? || nil),
|
||||
audit_token_conflicts: (args.token_conflicts? || nil),
|
||||
quarantine: true,
|
||||
any_named_args: !no_named_args,
|
||||
only: args.only,
|
||||
except: args.except,
|
||||
)
|
||||
|
||||
cask_results.deep_merge!({ cask.sourcefile_path => errors })
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@ -7,6 +7,7 @@ require "cli/parser"
|
||||
|
||||
class String
|
||||
def f(*args)
|
||||
require "formula"
|
||||
Formulary.factory(self, *args)
|
||||
end
|
||||
|
||||
|
||||
@ -343,7 +343,7 @@ module Homebrew
|
||||
nil
|
||||
end
|
||||
if libiconv&.linked_keg&.directory?
|
||||
unless libiconv.keg_only?
|
||||
unless libiconv&.keg_only?
|
||||
<<~EOS
|
||||
A libiconv formula is installed and linked.
|
||||
This will break stuff. For serious. Unlink it.
|
||||
|
||||
@ -4,13 +4,16 @@
|
||||
module Utils
|
||||
module Bottles
|
||||
class << self
|
||||
undef tag
|
||||
module MacOSOverride
|
||||
sig { params(tag: T.nilable(T.any(Symbol, Tag))).returns(Tag) }
|
||||
def tag(tag = nil)
|
||||
return Tag.new(system: MacOS.version.to_sym, arch: Hardware::CPU.arch) if tag.nil?
|
||||
|
||||
def tag(symbol = nil)
|
||||
return Utils::Bottles::Tag.from_symbol(symbol) if symbol.present?
|
||||
|
||||
Utils::Bottles::Tag.new(system: MacOS.version.to_sym, arch: Hardware::CPU.arch)
|
||||
super
|
||||
end
|
||||
end
|
||||
|
||||
prepend MacOSOverride
|
||||
end
|
||||
|
||||
class Collector
|
||||
|
||||
@ -10,12 +10,16 @@ module Homebrew
|
||||
force_bottle: T::Boolean,
|
||||
bottle_tag: T.nilable(Symbol),
|
||||
build_from_source_formulae: T::Array[String],
|
||||
os: T.nilable(Symbol),
|
||||
arch: T.nilable(Symbol),
|
||||
).returns(T::Boolean)
|
||||
}
|
||||
def fetch_bottle?(formula, force_bottle:, bottle_tag:, build_from_source_formulae:)
|
||||
def fetch_bottle?(formula, force_bottle:, bottle_tag:, build_from_source_formulae:, os:, arch:)
|
||||
bottle = formula.bottle
|
||||
|
||||
return true if force_bottle && bottle.present?
|
||||
return true if os.present?
|
||||
return true if arch.present?
|
||||
return true if bottle_tag.present? && formula.bottled?(bottle_tag)
|
||||
|
||||
bottle.present? &&
|
||||
|
||||
@ -385,7 +385,7 @@ class Formula
|
||||
|
||||
# The Bottle object for given tag.
|
||||
# @private
|
||||
sig { params(tag: T.nilable(Symbol)).returns(T.nilable(Bottle)) }
|
||||
sig { params(tag: T.nilable(Utils::Bottles::Tag)).returns(T.nilable(Bottle)) }
|
||||
def bottle_for_tag(tag = nil)
|
||||
Bottle.new(self, bottle_specification, tag) if bottled?(tag)
|
||||
end
|
||||
|
||||
@ -165,7 +165,7 @@ class FormulaInstaller
|
||||
|
||||
return true if formula.local_bottle_path.present?
|
||||
|
||||
bottle = formula.bottle_for_tag(Utils::Bottles.tag.to_sym)
|
||||
bottle = formula.bottle_for_tag(Utils::Bottles.tag)
|
||||
return false if bottle.nil?
|
||||
|
||||
unless bottle.compatible_locations?
|
||||
|
||||
@ -38,11 +38,17 @@ class FormulaVersions
|
||||
end
|
||||
end
|
||||
|
||||
sig { params(rev: String).returns(String) }
|
||||
def file_contents_at_revision(rev)
|
||||
repository.cd { Utils.popen_read("git", "cat-file", "blob", "#{rev}:#{entry_name}") }
|
||||
end
|
||||
|
||||
def formula_at_revision(rev)
|
||||
sig {
|
||||
type_parameters(:U)
|
||||
.params(rev: String, _block: T.proc.params(arg0: Formula).returns(T.type_parameter(:U)))
|
||||
.returns(T.nilable(T.type_parameter(:U)))
|
||||
}
|
||||
def formula_at_revision(rev, &_block)
|
||||
Homebrew.raise_deprecation_exceptions = true
|
||||
|
||||
yield @formula_at_revision[rev] ||= begin
|
||||
|
||||
@ -51,7 +51,12 @@ module Formulary
|
||||
next if type == :formulary_factory
|
||||
|
||||
cached_objects.each_value do |klass|
|
||||
namespace = Utils.deconstantize(klass.name)
|
||||
class_name = klass.name
|
||||
|
||||
# Already removed from namespace.
|
||||
next if class_name.nil?
|
||||
|
||||
namespace = Utils.deconstantize(class_name)
|
||||
next if Utils.deconstantize(namespace) != name
|
||||
|
||||
remove_const(Utils.demodulize(namespace).to_sym)
|
||||
@ -119,6 +124,10 @@ module Formulary
|
||||
end
|
||||
end
|
||||
|
||||
sig {
|
||||
params(name: String, path: Pathname, flags: T::Array[String], ignore_errors: T::Boolean)
|
||||
.returns(T.class_of(Formula))
|
||||
}
|
||||
def self.load_formula_from_path(name, path, flags:, ignore_errors:)
|
||||
contents = path.open("r") { |f| ensure_utf8_encoding(f).read }
|
||||
namespace = "FormulaNamespace#{Digest::MD5.hexdigest(path.to_s)}"
|
||||
@ -127,6 +136,7 @@ module Formulary
|
||||
cache[:path][path] = klass
|
||||
end
|
||||
|
||||
sig { params(name: String, flags: T::Array[String]).returns(T.class_of(Formula)) }
|
||||
def self.load_formula_from_api(name, flags:)
|
||||
namespace = :"FormulaNamespaceAPI#{Digest::MD5.hexdigest(name)}"
|
||||
|
||||
@ -313,15 +323,27 @@ module Formulary
|
||||
end
|
||||
end
|
||||
|
||||
klass = T.cast(klass, T.class_of(Formula))
|
||||
mod.const_set(class_name, klass)
|
||||
|
||||
cache[:api] ||= {}
|
||||
cache[:api][name] = klass
|
||||
end
|
||||
|
||||
def self.resolve(name, spec: nil, force_bottle: false, flags: [])
|
||||
sig { params(name: String, spec: Symbol, force_bottle: T::Boolean, flags: T::Array[String]).returns(Formula) }
|
||||
def self.resolve(
|
||||
name,
|
||||
spec: T.unsafe(nil),
|
||||
force_bottle: T.unsafe(nil),
|
||||
flags: T.unsafe(nil)
|
||||
)
|
||||
options = {
|
||||
force_bottle: force_bottle,
|
||||
flags: flags,
|
||||
}.compact
|
||||
|
||||
if name.include?("/") || File.exist?(name)
|
||||
f = factory(name, *spec, force_bottle: force_bottle, flags: flags)
|
||||
f = factory(name, *spec, **options)
|
||||
if f.any_version_installed?
|
||||
tab = Tab.for_formula(f)
|
||||
resolved_spec = spec || tab.spec
|
||||
@ -334,8 +356,10 @@ module Formulary
|
||||
end
|
||||
else
|
||||
rack = to_rack(name)
|
||||
alias_path = factory(name, force_bottle: force_bottle, flags: flags).alias_path
|
||||
f = from_rack(rack, *spec, alias_path: alias_path, force_bottle: force_bottle, flags: flags)
|
||||
if (alias_path = factory(name, **options).alias_path)
|
||||
options[:alias_path] = alias_path
|
||||
end
|
||||
f = from_rack(rack, *spec, **options)
|
||||
end
|
||||
|
||||
# If this formula was installed with an alias that has since changed,
|
||||
@ -524,12 +548,12 @@ module Formulary
|
||||
|
||||
# Loads tapped formulae.
|
||||
class TapLoader < FormulaLoader
|
||||
def initialize(tapped_name, from: nil, warn: true)
|
||||
def initialize(tapped_name, from:, warn:)
|
||||
name, path, tap = formula_name_path(tapped_name, warn: warn)
|
||||
super name, path, tap: tap
|
||||
end
|
||||
|
||||
def formula_name_path(tapped_name, warn: true)
|
||||
def formula_name_path(tapped_name, warn:)
|
||||
user, repo, name = tapped_name.split("/", 3).map(&:downcase)
|
||||
tap = Tap.fetch user, repo
|
||||
path = find_formula_from_name(name, tap)
|
||||
@ -648,25 +672,46 @@ module Formulary
|
||||
# * a formula pathname
|
||||
# * a formula URL
|
||||
# * a local bottle reference
|
||||
sig {
|
||||
params(
|
||||
ref: T.nilable(T.any(Pathname, String)),
|
||||
spec: Symbol,
|
||||
alias_path: Pathname,
|
||||
from: Symbol,
|
||||
warn: T::Boolean,
|
||||
force_bottle: T::Boolean,
|
||||
flags: T::Array[String],
|
||||
ignore_errors: T::Boolean,
|
||||
).returns(Formula)
|
||||
}
|
||||
def self.factory(
|
||||
ref, spec = :stable, alias_path: nil, from: nil, warn: true,
|
||||
force_bottle: false, flags: [], ignore_errors: false
|
||||
ref,
|
||||
spec = :stable,
|
||||
alias_path: T.unsafe(nil),
|
||||
from: T.unsafe(nil),
|
||||
warn: T.unsafe(nil),
|
||||
force_bottle: T.unsafe(nil),
|
||||
flags: T.unsafe(nil),
|
||||
ignore_errors: T.unsafe(nil)
|
||||
)
|
||||
raise ArgumentError, "Formulae must have a ref!" unless ref
|
||||
|
||||
cache_key = "#{ref}-#{spec}-#{alias_path}-#{from}"
|
||||
if factory_cached? && cache[:formulary_factory] &&
|
||||
cache[:formulary_factory][cache_key]
|
||||
return cache[:formulary_factory][cache_key]
|
||||
end
|
||||
return cache[:formulary_factory][cache_key] if factory_cached? && cache[:formulary_factory]&.key?(cache_key)
|
||||
|
||||
loader_options = { from: from, warn: warn }.compact
|
||||
formula_options = { alias_path: alias_path,
|
||||
force_bottle: force_bottle,
|
||||
flags: flags,
|
||||
ignore_errors: ignore_errors }.compact
|
||||
formula = loader_for(ref, **loader_options)
|
||||
.get_formula(spec, **formula_options)
|
||||
|
||||
formula = loader_for(ref, from: from, warn: warn).get_formula(spec, alias_path: alias_path,
|
||||
force_bottle: force_bottle, flags: flags,
|
||||
ignore_errors: ignore_errors)
|
||||
if factory_cached?
|
||||
cache[:formulary_factory] ||= {}
|
||||
cache[:formulary_factory][cache_key] ||= formula
|
||||
end
|
||||
|
||||
formula
|
||||
end
|
||||
|
||||
@ -676,15 +721,35 @@ module Formulary
|
||||
# @param :alias_path will be used if the formula is found not to be
|
||||
# installed, and discarded if it is installed because the `alias_path` used
|
||||
# to install the formula will be set instead.
|
||||
def self.from_rack(rack, spec = nil, alias_path: nil, force_bottle: false, flags: [])
|
||||
sig {
|
||||
params(
|
||||
rack: Pathname,
|
||||
# Automatically resolves the formula's spec if not specified.
|
||||
spec: Symbol,
|
||||
alias_path: Pathname,
|
||||
force_bottle: T::Boolean,
|
||||
flags: T::Array[String],
|
||||
).returns(Formula)
|
||||
}
|
||||
def self.from_rack(
|
||||
rack, spec = T.unsafe(nil),
|
||||
alias_path: T.unsafe(nil),
|
||||
force_bottle: T.unsafe(nil),
|
||||
flags: T.unsafe(nil)
|
||||
)
|
||||
kegs = rack.directory? ? rack.subdirs.map { |d| Keg.new(d) } : []
|
||||
keg = kegs.find(&:linked?) || kegs.find(&:optlinked?) || kegs.max_by(&:version)
|
||||
|
||||
options = {
|
||||
alias_path: alias_path,
|
||||
force_bottle: force_bottle,
|
||||
flags: flags,
|
||||
}.compact
|
||||
|
||||
if keg
|
||||
from_keg(keg, spec, alias_path: alias_path, force_bottle: force_bottle, flags: flags)
|
||||
from_keg(keg, *spec, **options)
|
||||
else
|
||||
factory(rack.basename.to_s, spec || :stable, alias_path: alias_path, from: :rack, warn: false,
|
||||
force_bottle: force_bottle, flags: flags)
|
||||
factory(rack.basename.to_s, *spec, from: :rack, warn: false, **options)
|
||||
end
|
||||
end
|
||||
|
||||
@ -696,24 +761,45 @@ module Formulary
|
||||
end
|
||||
|
||||
# Return a {Formula} instance for the given keg.
|
||||
#
|
||||
# @param spec when nil, will auto resolve the formula's spec.
|
||||
def self.from_keg(keg, spec = nil, alias_path: nil, force_bottle: false, flags: [])
|
||||
sig {
|
||||
params(
|
||||
keg: Keg,
|
||||
# Automatically resolves the formula's spec if not specified.
|
||||
spec: Symbol,
|
||||
alias_path: Pathname,
|
||||
force_bottle: T::Boolean,
|
||||
flags: T::Array[String],
|
||||
).returns(Formula)
|
||||
}
|
||||
def self.from_keg(
|
||||
keg,
|
||||
spec = T.unsafe(nil),
|
||||
alias_path: T.unsafe(nil),
|
||||
force_bottle: T.unsafe(nil),
|
||||
flags: T.unsafe(nil)
|
||||
)
|
||||
tab = Tab.for_keg(keg)
|
||||
tap = tab.tap
|
||||
spec ||= tab.spec
|
||||
|
||||
formula_name = keg.rack.basename.to_s
|
||||
|
||||
options = {
|
||||
alias_path: alias_path,
|
||||
from: :keg,
|
||||
warn: false,
|
||||
force_bottle: force_bottle,
|
||||
flags: flags,
|
||||
}.compact
|
||||
|
||||
f = if tap.nil?
|
||||
factory(keg.rack.basename.to_s, spec, alias_path: alias_path, from: :keg, warn: false,
|
||||
force_bottle: force_bottle, flags: flags)
|
||||
factory(formula_name, spec, **options)
|
||||
else
|
||||
begin
|
||||
factory("#{tap}/#{keg.rack.basename}", spec, alias_path: alias_path, from: :keg, warn: false,
|
||||
force_bottle: force_bottle, flags: flags)
|
||||
factory("#{tap}/#{formula_name}", spec, **options)
|
||||
rescue FormulaUnavailableError
|
||||
# formula may be migrated to different tap. Try to search in core and all taps.
|
||||
factory(keg.rack.basename.to_s, spec, alias_path: alias_path, from: :keg, warn: false,
|
||||
force_bottle: force_bottle, flags: flags)
|
||||
factory(formula_name, spec, **options)
|
||||
end
|
||||
end
|
||||
f.build = tab
|
||||
@ -723,13 +809,35 @@ module Formulary
|
||||
end
|
||||
|
||||
# Return a {Formula} instance directly from contents.
|
||||
sig {
|
||||
params(
|
||||
name: String,
|
||||
path: Pathname,
|
||||
contents: String,
|
||||
spec: Symbol,
|
||||
alias_path: Pathname,
|
||||
force_bottle: T::Boolean,
|
||||
flags: T::Array[String],
|
||||
ignore_errors: T::Boolean,
|
||||
).returns(Formula)
|
||||
}
|
||||
def self.from_contents(
|
||||
name, path, contents, spec = :stable, alias_path: nil,
|
||||
force_bottle: false, flags: [], ignore_errors: false
|
||||
name,
|
||||
path,
|
||||
contents,
|
||||
spec = :stable,
|
||||
alias_path: T.unsafe(nil),
|
||||
force_bottle: T.unsafe(nil),
|
||||
flags: T.unsafe(nil),
|
||||
ignore_errors: T.unsafe(nil)
|
||||
)
|
||||
FormulaContentsLoader.new(name, path, contents)
|
||||
.get_formula(spec, alias_path: alias_path, force_bottle: force_bottle,
|
||||
flags: flags, ignore_errors: ignore_errors)
|
||||
options = {
|
||||
alias_path: alias_path,
|
||||
force_bottle: force_bottle,
|
||||
flags: flags,
|
||||
ignore_errors: ignore_errors,
|
||||
}.compact
|
||||
FormulaContentsLoader.new(name, path, contents).get_formula(spec, **options)
|
||||
end
|
||||
|
||||
def self.to_rack(ref)
|
||||
|
||||
@ -71,16 +71,37 @@ class Attr < Parlour::Plugin
|
||||
tree << element
|
||||
elsif node.type == :send && children.shift.nil?
|
||||
method_name = children.shift
|
||||
if [:attr_rw, :attr_predicate].include?(method_name)
|
||||
|
||||
case method_name
|
||||
when :attr_rw, :attr_predicate
|
||||
children.each do |name_node|
|
||||
tree << [method_name, name_node.children.first.to_s]
|
||||
end
|
||||
when :delegate
|
||||
children.each do |name_node|
|
||||
name_node.children.each do |pair|
|
||||
delegated_method = pair.children.first
|
||||
delegated_methods = if delegated_method.type == :array
|
||||
delegated_method.children
|
||||
else
|
||||
[delegated_method]
|
||||
end
|
||||
|
||||
delegated_methods.each do |delegated_method_sym|
|
||||
tree << [method_name, delegated_method_sym.children.first.to_s]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
tree
|
||||
end
|
||||
|
||||
ARRAY_METHODS = T.let(["to_a", "to_ary"].freeze, T::Array[String])
|
||||
HASH_METHODS = T.let(["to_h", "to_hash"].freeze, T::Array[String])
|
||||
STRING_METHODS = T.let(["to_s", "to_str", "to_json"].freeze, T::Array[String])
|
||||
|
||||
sig { params(tree: T::Array[T.untyped], namespace: Parlour::RbiGenerator::Namespace, sclass: T::Boolean).void }
|
||||
def process_custom_attr(tree, namespace, sclass: false)
|
||||
tree.each do |node|
|
||||
@ -107,6 +128,32 @@ class Attr < Parlour::Plugin
|
||||
name = node.shift
|
||||
name = "self.#{name}" if sclass
|
||||
namespace.create_method(name, return_type: "T::Boolean")
|
||||
when :delegate
|
||||
name = node.shift
|
||||
|
||||
return_type = if name.end_with?("?")
|
||||
"T::Boolean"
|
||||
elsif ARRAY_METHODS.include?(name)
|
||||
"Array"
|
||||
elsif HASH_METHODS.include?(name)
|
||||
"Hash"
|
||||
elsif STRING_METHODS.include?(name)
|
||||
"String"
|
||||
else
|
||||
"T.untyped"
|
||||
end
|
||||
|
||||
name = "self.#{name}" if sclass
|
||||
|
||||
namespace.create_method(
|
||||
name,
|
||||
parameters: [
|
||||
Parlour::RbiGenerator::Parameter.new("*args"),
|
||||
Parlour::RbiGenerator::Parameter.new("**options"),
|
||||
Parlour::RbiGenerator::Parameter.new("&block"),
|
||||
],
|
||||
return_type: return_type,
|
||||
)
|
||||
else
|
||||
raise "Malformed tree."
|
||||
end
|
||||
|
||||
@ -4,17 +4,17 @@ require "cli/named_args"
|
||||
|
||||
def setup_unredable_formula(name)
|
||||
error = FormulaUnreadableError.new(name, RuntimeError.new("testing"))
|
||||
allow(Formulary).to receive(:factory).with(name, force_bottle: false, flags: [], warn: true).and_raise(error)
|
||||
allow(Formulary).to receive(:factory).with(name, {}).and_raise(error)
|
||||
end
|
||||
|
||||
def setup_unredable_cask(name)
|
||||
error = Cask::CaskUnreadableError.new(name, "testing")
|
||||
allow(Cask::CaskLoader).to receive(:load).with(name).and_raise(error)
|
||||
allow(Cask::CaskLoader).to receive(:load).with(name, config: nil, warn: true).and_raise(error)
|
||||
allow(Cask::CaskLoader).to receive(:load).with(name, config: nil).and_raise(error)
|
||||
|
||||
config = instance_double(Cask::Config)
|
||||
allow(Cask::Config).to receive(:from_args).and_return(config)
|
||||
allow(Cask::CaskLoader).to receive(:load).with(name, config: config, warn: true).and_raise(error)
|
||||
allow(Cask::CaskLoader).to receive(:load).with(name, config: config).and_raise(error)
|
||||
end
|
||||
|
||||
describe Homebrew::CLI::NamedArgs do
|
||||
|
||||
@ -16,7 +16,7 @@ module Test
|
||||
|
||||
loader = double(get_formula: formula)
|
||||
allow(Formulary).to receive(:loader_for).with(ref, from: :keg, warn: false).and_return(loader)
|
||||
allow(Formulary).to receive(:loader_for).with(ref, from: nil, warn: true).and_return(loader)
|
||||
allow(Formulary).to receive(:loader_for).with(ref, {}).and_return(loader)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -10,11 +10,19 @@ module Utils
|
||||
module Bottles
|
||||
class << self
|
||||
# Gets the tag for the running OS.
|
||||
def tag(symbol = nil)
|
||||
return Tag.from_symbol(symbol) if symbol.present?
|
||||
|
||||
@tag ||= Tag.new(system: HOMEBREW_SYSTEM.downcase.to_sym,
|
||||
arch: HOMEBREW_PROCESSOR.downcase.to_sym)
|
||||
sig { params(tag: T.nilable(T.any(Symbol, Tag))).returns(Tag) }
|
||||
def tag(tag = nil)
|
||||
case tag
|
||||
when Symbol
|
||||
Tag.from_symbol(tag)
|
||||
when Tag
|
||||
tag
|
||||
else
|
||||
@tag ||= Tag.new(
|
||||
system: HOMEBREW_SYSTEM.downcase.to_sym,
|
||||
arch: HOMEBREW_PROCESSOR.downcase.to_sym,
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
def built_as?(formula)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user