Install and uninstall formulae with the internal API
This commit is contained in:
parent
51a98eb950
commit
7c71554e5d
@ -32,7 +32,7 @@ class CaskDependent
|
|||||||
|
|
||||||
sig { returns(T::Array[Dependency]) }
|
sig { returns(T::Array[Dependency]) }
|
||||||
def runtime_dependencies
|
def runtime_dependencies
|
||||||
deps.flat_map { |dep| [dep, *dep.to_formula.runtime_dependencies] }.uniq
|
deps.flat_map { |dep| [dep, *dep.to_installed_formula.runtime_dependencies] }.uniq
|
||||||
end
|
end
|
||||||
|
|
||||||
sig { returns(T::Array[Dependency]) }
|
sig { returns(T::Array[Dependency]) }
|
||||||
|
@ -722,7 +722,7 @@ module Homebrew
|
|||||||
# Remove formulae listed in HOMEBREW_NO_CLEANUP_FORMULAE and their dependencies.
|
# Remove formulae listed in HOMEBREW_NO_CLEANUP_FORMULAE and their dependencies.
|
||||||
if Homebrew::EnvConfig.no_cleanup_formulae.present?
|
if Homebrew::EnvConfig.no_cleanup_formulae.present?
|
||||||
formulae -= formulae.select { skip_clean_formula?(_1) }
|
formulae -= formulae.select { skip_clean_formula?(_1) }
|
||||||
.flat_map { |f| [f, *f.runtime_formula_dependencies] }
|
.flat_map { |f| [f, *f.installed_runtime_formula_dependencies] }
|
||||||
end
|
end
|
||||||
casks = Cask::Caskroom.casks
|
casks = Cask::Caskroom.casks
|
||||||
|
|
||||||
|
@ -229,7 +229,6 @@ module Homebrew
|
|||||||
dep_names = CaskDependent.new(cask)
|
dep_names = CaskDependent.new(cask)
|
||||||
.runtime_dependencies
|
.runtime_dependencies
|
||||||
.reject(&:installed?)
|
.reject(&:installed?)
|
||||||
.map(&:to_formula)
|
|
||||||
.map(&:name)
|
.map(&:name)
|
||||||
next if dep_names.blank?
|
next if dep_names.blank?
|
||||||
|
|
||||||
|
@ -24,9 +24,9 @@ module Homebrew
|
|||||||
|
|
||||||
sig { override.void }
|
sig { override.void }
|
||||||
def run
|
def run
|
||||||
leaves_list = Formula.installed - Formula.installed.flat_map(&:runtime_formula_dependencies)
|
leaves_list = Formula.installed - Formula.installed.flat_map(&:installed_runtime_formula_dependencies)
|
||||||
casks_runtime_dependencies = Cask::Caskroom.casks.flat_map do |cask|
|
casks_runtime_dependencies = Cask::Caskroom.casks.flat_map do |cask|
|
||||||
CaskDependent.new(cask).runtime_dependencies.map(&:to_formula)
|
CaskDependent.new(cask).runtime_dependencies.map(&:to_installed_formula)
|
||||||
end
|
end
|
||||||
leaves_list -= casks_runtime_dependencies
|
leaves_list -= casks_runtime_dependencies
|
||||||
leaves_list.select! { installed_on_request?(_1) } if args.installed_on_request?
|
leaves_list.select! { installed_on_request?(_1) } if args.installed_on_request?
|
||||||
|
@ -36,8 +36,12 @@ class Dependency
|
|||||||
[name, tags].hash
|
[name, tags].hash
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_formula(prefer_stub: false)
|
def to_installed_formula
|
||||||
formula = Formulary.factory(name, warn: false, prefer_stub:)
|
Formulary.from_rack(HOMEBREW_CELLAR/name)
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_formula
|
||||||
|
formula = Formulary.factory(name, warn: false)
|
||||||
formula.build = BuildOptions.new(options, formula.options)
|
formula.build = BuildOptions.new(options, formula.options)
|
||||||
formula
|
formula
|
||||||
end
|
end
|
||||||
@ -45,7 +49,7 @@ class Dependency
|
|||||||
sig { params(minimum_version: T.nilable(Version), minimum_revision: T.nilable(Integer)).returns(T::Boolean) }
|
sig { params(minimum_version: T.nilable(Version), minimum_revision: T.nilable(Integer)).returns(T::Boolean) }
|
||||||
def installed?(minimum_version: nil, minimum_revision: nil)
|
def installed?(minimum_version: nil, minimum_revision: nil)
|
||||||
formula = begin
|
formula = begin
|
||||||
to_formula(prefer_stub: true)
|
to_installed_formula
|
||||||
rescue FormulaUnavailableError
|
rescue FormulaUnavailableError
|
||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
@ -86,7 +90,7 @@ class Dependency
|
|||||||
end
|
end
|
||||||
|
|
||||||
def missing_options(inherited_options)
|
def missing_options(inherited_options)
|
||||||
formula = to_formula(prefer_stub: true)
|
formula = to_installed_formula
|
||||||
required = options
|
required = options
|
||||||
required |= inherited_options
|
required |= inherited_options
|
||||||
required &= formula.options.to_a
|
required &= formula.options.to_a
|
||||||
|
@ -21,7 +21,7 @@ module Homebrew
|
|||||||
|
|
||||||
sig {
|
sig {
|
||||||
params(formulae: T::Array[Formula], hide: T::Array[String], _block: T.nilable(
|
params(formulae: T::Array[Formula], hide: T::Array[String], _block: T.nilable(
|
||||||
T.proc.params(formula_name: String, missing_dependencies: T::Array[Formula]).void,
|
T.proc.params(formula_name: String, missing_dependencies: T::Array[Dependency]).void,
|
||||||
)).returns(T::Hash[String, T::Array[String]])
|
)).returns(T::Hash[String, T::Array[String]])
|
||||||
}
|
}
|
||||||
def self.missing_deps(formulae, hide = [], &_block)
|
def self.missing_deps(formulae, hide = [], &_block)
|
||||||
|
@ -2478,6 +2478,10 @@ class Formula
|
|||||||
# @api internal
|
# @api internal
|
||||||
sig { params(read_from_tab: T::Boolean, undeclared: T::Boolean).returns(T::Array[Dependency]) }
|
sig { params(read_from_tab: T::Boolean, undeclared: T::Boolean).returns(T::Array[Dependency]) }
|
||||||
def runtime_dependencies(read_from_tab: true, undeclared: true)
|
def runtime_dependencies(read_from_tab: true, undeclared: true)
|
||||||
|
cache_key = "#{full_name}-#{read_from_tab}-#{undeclared}"
|
||||||
|
|
||||||
|
Formula.cache[:runtime_dependencies] ||= {}
|
||||||
|
Formula.cache[:runtime_dependencies][cache_key] ||= begin
|
||||||
deps = if read_from_tab && undeclared &&
|
deps = if read_from_tab && undeclared &&
|
||||||
(tab_deps = any_installed_keg&.runtime_dependencies)
|
(tab_deps = any_installed_keg&.runtime_dependencies)
|
||||||
tab_deps.filter_map do |d|
|
tab_deps.filter_map do |d|
|
||||||
@ -2496,6 +2500,7 @@ class Formula
|
|||||||
end
|
end
|
||||||
deps
|
deps
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# Returns a list of {Formula} objects that are required at runtime.
|
# Returns a list of {Formula} objects that are required at runtime.
|
||||||
sig { params(read_from_tab: T::Boolean, undeclared: T::Boolean).returns(T::Array[Formula]) }
|
sig { params(read_from_tab: T::Boolean, undeclared: T::Boolean).returns(T::Array[Formula]) }
|
||||||
@ -2513,6 +2518,22 @@ class Formula
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Returns a list of installed {Formula} objects that are required at runtime.
|
||||||
|
sig { params(read_from_tab: T::Boolean, undeclared: T::Boolean).returns(T::Array[Formula]) }
|
||||||
|
def installed_runtime_formula_dependencies(read_from_tab: true, undeclared: true)
|
||||||
|
cache_key = "#{full_name}-#{read_from_tab}-#{undeclared}"
|
||||||
|
|
||||||
|
Formula.cache[:installed_runtime_formula_dependencies] ||= {}
|
||||||
|
Formula.cache[:installed_runtime_formula_dependencies][cache_key] ||= runtime_dependencies(
|
||||||
|
read_from_tab:,
|
||||||
|
undeclared:,
|
||||||
|
).filter_map do |d|
|
||||||
|
d.to_installed_formula
|
||||||
|
rescue FormulaUnavailableError
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
sig { returns(T::Array[Formula]) }
|
sig { returns(T::Array[Formula]) }
|
||||||
def runtime_installed_formula_dependents
|
def runtime_installed_formula_dependents
|
||||||
# `any_installed_keg` and `runtime_dependencies` `select`s ensure
|
# `any_installed_keg` and `runtime_dependencies` `select`s ensure
|
||||||
@ -2523,7 +2544,7 @@ class Formula
|
|||||||
.select(&:any_installed_keg)
|
.select(&:any_installed_keg)
|
||||||
.select(&:runtime_dependencies)
|
.select(&:runtime_dependencies)
|
||||||
.select do |f|
|
.select do |f|
|
||||||
f.runtime_formula_dependencies.any? do |dep|
|
f.installed_runtime_formula_dependencies.any? do |dep|
|
||||||
full_name == dep.full_name
|
full_name == dep.full_name
|
||||||
rescue
|
rescue
|
||||||
name == dep.name
|
name == dep.name
|
||||||
@ -2533,10 +2554,10 @@ class Formula
|
|||||||
|
|
||||||
# Returns a list of formulae depended on by this formula that aren't
|
# Returns a list of formulae depended on by this formula that aren't
|
||||||
# installed.
|
# installed.
|
||||||
sig { params(hide: T::Array[String]).returns(T::Array[Formula]) }
|
sig { params(hide: T::Array[String]).returns(T::Array[Dependency]) }
|
||||||
def missing_dependencies(hide: [])
|
def missing_dependencies(hide: [])
|
||||||
runtime_formula_dependencies.select do |f|
|
runtime_dependencies(read_from_tab: true, undeclared: true).select do |f|
|
||||||
hide.include?(f.name) || f.installed_prefixes.empty?
|
hide.include?(f.name) || !f.installed?
|
||||||
end
|
end
|
||||||
# If we're still getting unavailable formulae at this stage the best we can
|
# If we're still getting unavailable formulae at this stage the best we can
|
||||||
# do is just return no results.
|
# do is just return no results.
|
||||||
|
@ -949,9 +949,15 @@ module Formulary
|
|||||||
def self.try_new(ref, from: nil, warn: false)
|
def self.try_new(ref, from: nil, warn: false)
|
||||||
ref = ref.to_s
|
ref = ref.to_s
|
||||||
|
|
||||||
return unless (keg_formula = HOMEBREW_PREFIX/"opt/#{ref}/.brew/#{ref}.rb").file?
|
keg_directory = HOMEBREW_PREFIX/"opt/#{ref}"
|
||||||
|
return unless keg_directory.directory?
|
||||||
|
|
||||||
new(ref, keg_formula)
|
# The formula file in `.brew` will use the canonical name, whereas `ref` can be an alias.
|
||||||
|
# Use `Keg#name` to get the canonical name.
|
||||||
|
keg = Keg.new(keg_directory)
|
||||||
|
return unless (keg_formula = HOMEBREW_PREFIX/"opt/#{ref}/.brew/#{keg.name}.rb").file?
|
||||||
|
|
||||||
|
new(keg.name, keg_formula)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -1067,7 +1073,12 @@ module Formulary
|
|||||||
|
|
||||||
sig { overridable.params(flags: T::Array[String]).void }
|
sig { overridable.params(flags: T::Array[String]).void }
|
||||||
def load_from_api(flags:)
|
def load_from_api(flags:)
|
||||||
json_formula = Homebrew::API::Formula.all_formulae[name]
|
json_formula = if Homebrew::EnvConfig.use_internal_api?
|
||||||
|
Homebrew::API::Formula.formula_json(name)
|
||||||
|
else
|
||||||
|
Homebrew::API::Formula.all_formulae[name]
|
||||||
|
end
|
||||||
|
|
||||||
raise FormulaUnavailableError, name if json_formula.nil?
|
raise FormulaUnavailableError, name if json_formula.nil?
|
||||||
|
|
||||||
Formulary.load_formula_from_json!(name, json_formula, flags:)
|
Formulary.load_formula_from_json!(name, json_formula, flags:)
|
||||||
@ -1236,7 +1247,16 @@ module Formulary
|
|||||||
flags:,
|
flags:,
|
||||||
}.compact
|
}.compact
|
||||||
|
|
||||||
f = if tap.nil?
|
loader = FromKegLoader.try_new(keg.name, warn: false)
|
||||||
|
f = if loader.present?
|
||||||
|
begin
|
||||||
|
loader.get_formula(spec, alias_path:, force_bottle:, flags:, ignore_errors: true)
|
||||||
|
rescue FormulaUnreadableError
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
f ||= if tap.nil?
|
||||||
factory(formula_name, spec, **options)
|
factory(formula_name, spec, **options)
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
|
@ -26,7 +26,7 @@ module InstalledDependents
|
|||||||
kegs_by_source = kegs.group_by do |keg|
|
kegs_by_source = kegs.group_by do |keg|
|
||||||
# First, attempt to resolve the keg to a formula
|
# First, attempt to resolve the keg to a formula
|
||||||
# to get up-to-date name and tap information.
|
# to get up-to-date name and tap information.
|
||||||
f = keg.to_formula
|
f = keg.to_installed_formula
|
||||||
keg_formulae << f
|
keg_formulae << f
|
||||||
[f.name, f.tap]
|
[f.name, f.tap]
|
||||||
rescue
|
rescue
|
||||||
@ -47,7 +47,7 @@ module InstalledDependents
|
|||||||
dependent.missing_dependencies(hide: keg_names)
|
dependent.missing_dependencies(hide: keg_names)
|
||||||
when Cask::Cask
|
when Cask::Cask
|
||||||
# When checking for cask dependents, we don't care about missing or non-runtime dependencies
|
# When checking for cask dependents, we don't care about missing or non-runtime dependencies
|
||||||
CaskDependent.new(dependent).runtime_dependencies.map(&:to_formula)
|
CaskDependent.new(dependent).runtime_dependencies
|
||||||
end
|
end
|
||||||
|
|
||||||
required_kegs = required.filter_map do |f|
|
required_kegs = required.filter_map do |f|
|
||||||
|
@ -23,10 +23,16 @@ module Utils
|
|||||||
# @private
|
# @private
|
||||||
sig { params(casks: T::Array[Cask::Cask]).returns(T::Array[Formula]) }
|
sig { params(casks: T::Array[Cask::Cask]).returns(T::Array[Formula]) }
|
||||||
def formulae_with_cask_dependents(casks)
|
def formulae_with_cask_dependents(casks)
|
||||||
casks.flat_map { |cask| cask.depends_on[:formula] }
|
casks.flat_map { |cask| cask.depends_on[:formula] }.compact.flat_map do |name|
|
||||||
.compact
|
f = begin
|
||||||
.map { |f| Formula[f] }
|
Formulary.from_rack(HOMEBREW_CELLAR/name)
|
||||||
.flat_map { |f| [f, *f.runtime_formula_dependencies].compact }
|
rescue FormulaUnavailableError
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
next [] unless f
|
||||||
|
|
||||||
|
[f, *f.installed_runtime_formula_dependencies].compact
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# An array of all installed bottled {Formula} without runtime {Formula}
|
# An array of all installed bottled {Formula} without runtime {Formula}
|
||||||
@ -37,7 +43,7 @@ module Utils
|
|||||||
def bottled_formulae_with_no_formula_dependents(formulae)
|
def bottled_formulae_with_no_formula_dependents(formulae)
|
||||||
formulae_to_keep = T.let([], T::Array[Formula])
|
formulae_to_keep = T.let([], T::Array[Formula])
|
||||||
formulae.each do |formula|
|
formulae.each do |formula|
|
||||||
formulae_to_keep += formula.runtime_formula_dependencies
|
formulae_to_keep += formula.installed_runtime_formula_dependencies
|
||||||
|
|
||||||
if (tab = formula.any_installed_keg&.tab)
|
if (tab = formula.any_installed_keg&.tab)
|
||||||
# Ignore build dependencies when the formula is a bottle
|
# Ignore build dependencies when the formula is a bottle
|
||||||
|
Loading…
x
Reference in New Issue
Block a user