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