Skip to content

Commit c774467

Browse files
committed
Install and uninstall formulae with the internal API
1 parent 18ba182 commit c774467

File tree

11 files changed

+94
-43
lines changed

11 files changed

+94
-43
lines changed

Library/Homebrew/cask_dependent.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ def full_name
3232

3333
sig { returns(T::Array[Dependency]) }
3434
def runtime_dependencies
35-
deps.flat_map { |dep| [dep, *dep.to_formula.runtime_dependencies] }.uniq
35+
deps.flat_map { |dep| [dep, *dep.to_installed_formula.runtime_dependencies] }.uniq
3636
end
3737

3838
sig { returns(T::Array[Dependency]) }

Library/Homebrew/cleanup.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -722,7 +722,7 @@ def self.autoremove(dry_run: false)
722722
# Remove formulae listed in HOMEBREW_NO_CLEANUP_FORMULAE and their dependencies.
723723
if Homebrew::EnvConfig.no_cleanup_formulae.present?
724724
formulae -= formulae.select { skip_clean_formula?(_1) }
725-
.flat_map { |f| [f, *f.runtime_formula_dependencies] }
725+
.flat_map { |f| [f, *f.installed_runtime_formula_dependencies] }
726726
end
727727
casks = Cask::Caskroom.casks
728728

Library/Homebrew/cmd/install.rb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,6 @@ def run
229229
dep_names = CaskDependent.new(cask)
230230
.runtime_dependencies
231231
.reject(&:installed?)
232-
.map(&:to_formula)
233232
.map(&:name)
234233
next if dep_names.blank?
235234

Library/Homebrew/cmd/leaves.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,9 @@ class Leaves < AbstractCommand
2424

2525
sig { override.void }
2626
def run
27-
leaves_list = Formula.installed - Formula.installed.flat_map(&:runtime_formula_dependencies)
27+
leaves_list = Formula.installed - Formula.installed.flat_map(&:installed_runtime_formula_dependencies)
2828
casks_runtime_dependencies = Cask::Caskroom.casks.flat_map do |cask|
29-
CaskDependent.new(cask).runtime_dependencies.map(&:to_formula)
29+
CaskDependent.new(cask).runtime_dependencies.map(&:to_installed_formula)
3030
end
3131
leaves_list -= casks_runtime_dependencies
3232
leaves_list.select! { installed_on_request?(_1) } if args.installed_on_request?

Library/Homebrew/cmd/outdated.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ def print_outdated(formulae_or_casks)
101101
# There is a newer HEAD but the version number has not changed.
102102
"latest HEAD"
103103
else
104-
f.pkg_version.to_s
104+
f.latest_formula.pkg_version.to_s
105105
end
106106

107107
outdated_versions = outdated_kegs.group_by { |keg| Formulary.from_keg(keg).full_name }

Library/Homebrew/dependency.rb

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,16 +36,20 @@ def hash
3636
[name, tags].hash
3737
end
3838

39-
def to_formula(prefer_stub: false)
40-
formula = Formulary.factory(name, warn: false, prefer_stub:)
39+
def to_installed_formula
40+
Formulary.resolve(name)
41+
end
42+
43+
def to_formula
44+
formula = Formulary.factory(name, warn: false)
4145
formula.build = BuildOptions.new(options, formula.options)
4246
formula
4347
end
4448

4549
sig { params(minimum_version: T.nilable(Version), minimum_revision: T.nilable(Integer)).returns(T::Boolean) }
4650
def installed?(minimum_version: nil, minimum_revision: nil)
4751
formula = begin
48-
to_formula(prefer_stub: true)
52+
to_installed_formula
4953
rescue FormulaUnavailableError
5054
nil
5155
end
@@ -86,7 +90,7 @@ def satisfied?(inherited_options = [], minimum_version: nil, minimum_revision: n
8690
end
8791

8892
def missing_options(inherited_options)
89-
formula = to_formula(prefer_stub: true)
93+
formula = to_installed_formula
9094
required = options
9195
required |= inherited_options
9296
required &= formula.options.to_a

Library/Homebrew/diagnostic.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ module Diagnostic
2121

2222
sig {
2323
params(formulae: T::Array[Formula], hide: T::Array[String], _block: T.nilable(
24-
T.proc.params(formula_name: String, missing_dependencies: T::Array[Formula]).void,
24+
T.proc.params(formula_name: String, missing_dependencies: T::Array[Dependency]).void,
2525
)).returns(T::Hash[String, T::Array[String]])
2626
}
2727
def self.missing_deps(formulae, hide = [], &_block)

Library/Homebrew/formula.rb

Lines changed: 43 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1702,14 +1702,15 @@ def outdated_kegs(fetch_head: false)
17021702
Formula.cache[:outdated_kegs][cache_key] ||= begin
17031703
all_kegs = []
17041704
current_version = T.let(false, T::Boolean)
1705+
latest = latest_formula
17051706

17061707
installed_kegs.each do |keg|
17071708
all_kegs << keg
17081709
version = keg.version
17091710
next if version.head?
17101711

1711-
next if version_scheme > keg.version_scheme && pkg_version != version
1712-
next if version_scheme == keg.version_scheme && pkg_version > version
1712+
next if latest.version_scheme > keg.version_scheme && latest.pkg_version != version
1713+
next if latest.version_scheme == keg.version_scheme && latest.pkg_version > version
17131714

17141715
# don't consider this keg current if there's a newer formula available
17151716
next if follow_installed_alias? && new_formula_available?
@@ -1767,7 +1768,7 @@ def alias_changed?
17671768
# Otherwise, return self.
17681769
sig { returns(Formula) }
17691770
def latest_formula
1770-
installed_alias_target_changed? ? T.must(current_installed_alias_target) : self
1771+
installed_alias_target_changed? ? T.must(current_installed_alias_target) : Formulary.factory(name)
17711772
end
17721773

17731774
sig { returns(T::Array[Formula]) }
@@ -2478,23 +2479,28 @@ def any_installed_version
24782479
# @api internal
24792480
sig { params(read_from_tab: T::Boolean, undeclared: T::Boolean).returns(T::Array[Dependency]) }
24802481
def runtime_dependencies(read_from_tab: true, undeclared: true)
2481-
deps = if read_from_tab && undeclared &&
2482-
(tab_deps = any_installed_keg&.runtime_dependencies)
2483-
tab_deps.filter_map do |d|
2484-
full_name = d["full_name"]
2485-
next unless full_name
2482+
cache_key = "#{full_name}-#{read_from_tab}-#{undeclared}"
2483+
2484+
Formula.cache[:runtime_dependencies] ||= {}
2485+
Formula.cache[:runtime_dependencies][cache_key] ||= begin
2486+
deps = if read_from_tab && undeclared &&
2487+
(tab_deps = any_installed_keg&.runtime_dependencies)
2488+
tab_deps.filter_map do |d|
2489+
full_name = d["full_name"]
2490+
next unless full_name
24862491

2487-
Dependency.new full_name
2492+
Dependency.new full_name
2493+
end
24882494
end
2495+
begin
2496+
deps ||= declared_runtime_dependencies unless undeclared
2497+
deps ||= (declared_runtime_dependencies | undeclared_runtime_dependencies)
2498+
rescue FormulaUnavailableError
2499+
onoe "Could not get runtime dependencies from #{path}!"
2500+
deps ||= []
2501+
end
2502+
deps
24892503
end
2490-
begin
2491-
deps ||= declared_runtime_dependencies unless undeclared
2492-
deps ||= (declared_runtime_dependencies | undeclared_runtime_dependencies)
2493-
rescue FormulaUnavailableError
2494-
onoe "Could not get runtime dependencies from #{path}!"
2495-
deps ||= []
2496-
end
2497-
deps
24982504
end
24992505

25002506
# Returns a list of {Formula} objects that are required at runtime.
@@ -2513,6 +2519,22 @@ def runtime_formula_dependencies(read_from_tab: true, undeclared: true)
25132519
end
25142520
end
25152521

2522+
# Returns a list of installed {Formula} objects that are required at runtime.
2523+
sig { params(read_from_tab: T::Boolean, undeclared: T::Boolean).returns(T::Array[Formula]) }
2524+
def installed_runtime_formula_dependencies(read_from_tab: true, undeclared: true)
2525+
cache_key = "#{full_name}-#{read_from_tab}-#{undeclared}"
2526+
2527+
Formula.cache[:installed_runtime_formula_dependencies] ||= {}
2528+
Formula.cache[:installed_runtime_formula_dependencies][cache_key] ||= runtime_dependencies(
2529+
read_from_tab:,
2530+
undeclared:,
2531+
).filter_map do |d|
2532+
d.to_installed_formula
2533+
rescue FormulaUnavailableError
2534+
nil
2535+
end
2536+
end
2537+
25162538
sig { returns(T::Array[Formula]) }
25172539
def runtime_installed_formula_dependents
25182540
# `any_installed_keg` and `runtime_dependencies` `select`s ensure
@@ -2523,7 +2545,7 @@ def runtime_installed_formula_dependents
25232545
.select(&:any_installed_keg)
25242546
.select(&:runtime_dependencies)
25252547
.select do |f|
2526-
f.runtime_formula_dependencies.any? do |dep|
2548+
f.installed_runtime_formula_dependencies.any? do |dep|
25272549
full_name == dep.full_name
25282550
rescue
25292551
name == dep.name
@@ -2533,10 +2555,10 @@ def runtime_installed_formula_dependents
25332555

25342556
# Returns a list of formulae depended on by this formula that aren't
25352557
# installed.
2536-
sig { params(hide: T::Array[String]).returns(T::Array[Formula]) }
2558+
sig { params(hide: T::Array[String]).returns(T::Array[Dependency]) }
25372559
def missing_dependencies(hide: [])
2538-
runtime_formula_dependencies.select do |f|
2539-
hide.include?(f.name) || f.installed_prefixes.empty?
2560+
runtime_dependencies(read_from_tab: true, undeclared: true).select do |f|
2561+
hide.include?(f.name) || !f.installed?
25402562
end
25412563
# If we're still getting unavailable formulae at this stage the best we can
25422564
# do is just return no results.

Library/Homebrew/formulary.rb

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -928,9 +928,15 @@ class FromKegLoader < FormulaLoader
928928
def self.try_new(ref, from: nil, warn: false)
929929
ref = ref.to_s
930930

931-
return unless (keg_formula = HOMEBREW_PREFIX/"opt/#{ref}/.brew/#{ref}.rb").file?
931+
keg_directory = HOMEBREW_PREFIX/"opt/#{ref}"
932+
return unless keg_directory.directory?
932933

933-
new(ref, keg_formula)
934+
# The formula file in `.brew` will use the canonical name, whereas `ref` can be an alias.
935+
# Use `Keg#name` to get the canonical name.
936+
keg = Keg.new(keg_directory)
937+
return unless (keg_formula = HOMEBREW_PREFIX/"opt/#{ref}/.brew/#{keg.name}.rb").file?
938+
939+
new(keg.name, keg_formula)
934940
end
935941
end
936942

@@ -1046,7 +1052,12 @@ def klass(flags:, ignore_errors:)
10461052

10471053
sig { overridable.params(flags: T::Array[String]).void }
10481054
def load_from_api(flags:)
1049-
json_formula = Homebrew::API::Formula.all_formulae[name]
1055+
json_formula = if Homebrew::EnvConfig.use_internal_api?
1056+
Homebrew::API::Formula.formula_json(name)
1057+
else
1058+
Homebrew::API::Formula.all_formulae[name]
1059+
end
1060+
10501061
raise FormulaUnavailableError, name if json_formula.nil?
10511062

10521063
Formulary.load_formula_from_json!(name, json_formula, flags:)
@@ -1215,7 +1226,16 @@ def self.from_keg(
12151226
flags:,
12161227
}.compact
12171228

1218-
f = if tap.nil?
1229+
loader = FromKegLoader.try_new(keg.name, warn: false)
1230+
f = if loader.present?
1231+
begin
1232+
loader.get_formula(spec, alias_path:, force_bottle:, flags:, ignore_errors: true)
1233+
rescue FormulaUnreadableError
1234+
nil
1235+
end
1236+
end
1237+
1238+
f ||= if tap.nil?
12191239
factory(formula_name, spec, **options)
12201240
else
12211241
begin

Library/Homebrew/installed_dependents.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ def find_some_installed_dependents(kegs, casks: [])
2626
kegs_by_source = kegs.group_by do |keg|
2727
# First, attempt to resolve the keg to a formula
2828
# to get up-to-date name and tap information.
29-
f = keg.to_formula
29+
f = keg.to_installed_formula
3030
keg_formulae << f
3131
[f.name, f.tap]
3232
rescue
@@ -47,7 +47,7 @@ def find_some_installed_dependents(kegs, casks: [])
4747
dependent.missing_dependencies(hide: keg_names)
4848
when Cask::Cask
4949
# When checking for cask dependents, we don't care about missing or non-runtime dependencies
50-
CaskDependent.new(dependent).runtime_dependencies.map(&:to_formula)
50+
CaskDependent.new(dependent).runtime_dependencies
5151
end
5252

5353
required_kegs = required.filter_map do |f|

0 commit comments

Comments
 (0)