uninstall: only <=1 Diagnostic.missing_deps call
This commit is contained in:
parent
452691528d
commit
ef13f8eaca
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
require "keg"
|
require "keg"
|
||||||
require "formula"
|
require "formula"
|
||||||
|
require "diagnostic"
|
||||||
require "migrator"
|
require "migrator"
|
||||||
|
|
||||||
module Homebrew
|
module Homebrew
|
||||||
@ -75,17 +76,45 @@ module Homebrew
|
|||||||
end
|
end
|
||||||
|
|
||||||
def check_for_dependents(kegs)
|
def check_for_dependents(kegs)
|
||||||
|
return false unless result = find_some_installed_dependents(kegs)
|
||||||
|
|
||||||
|
requireds, dependents = result
|
||||||
|
|
||||||
|
msg = "Refusing to uninstall #{requireds.join(", ")} because "
|
||||||
|
msg << (requireds.count == 1 ? "it is" : "they are")
|
||||||
|
msg << " required by #{dependents.join(", ")}, which "
|
||||||
|
msg << (dependents.count == 1 ? "is" : "are")
|
||||||
|
msg << " currently installed."
|
||||||
|
ofail msg
|
||||||
|
print "You can override this and force removal with "
|
||||||
|
puts "`brew uninstall --ignore-dependencies #{requireds.map(&:name).join(" ")}`."
|
||||||
|
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
|
# Will return some kegs, and some dependencies, if they're present.
|
||||||
|
# For efficiency, we don't bother trying to get complete data.
|
||||||
|
def find_some_installed_dependents(kegs)
|
||||||
kegs.each do |keg|
|
kegs.each do |keg|
|
||||||
dependents = keg.installed_dependents - kegs
|
dependents = keg.installed_dependents - kegs
|
||||||
next if dependents.empty?
|
dependents.map! { |d| "#{d.name} #{d.version}" }
|
||||||
|
return [keg], dependents if dependents.any?
|
||||||
dependents_output = dependents.map { |k| "#{k.name} #{k.version}" }.join(", ")
|
|
||||||
conjugation = dependents.count == 1 ? "is" : "are"
|
|
||||||
ofail "Refusing to uninstall #{keg} because it is required by #{dependents_output}, which #{conjugation} currently installed."
|
|
||||||
puts "You can override this and force removal with `brew uninstall --ignore-dependencies #{keg.name}`."
|
|
||||||
return true
|
|
||||||
end
|
end
|
||||||
false
|
|
||||||
|
# Find formulae that didn't have dependencies saved in all of their kegs,
|
||||||
|
# so need them to be calculated now.
|
||||||
|
#
|
||||||
|
# This happens after the initial dependency check because it's sloooow.
|
||||||
|
remaining_formulae = Formula.installed.select { |f|
|
||||||
|
f.installed_kegs.any? { |k| Tab.for_keg(k).runtime_dependencies.nil? }
|
||||||
|
}
|
||||||
|
Diagnostic.missing_deps(remaining_formulae, kegs.map(&:name)) do |dependent, required|
|
||||||
|
kegs_by_name = kegs.group_by(&:to_formula)
|
||||||
|
required_kegs = required.map { |f| kegs_by_name[f].sort_by(&:version).last }
|
||||||
|
return required_kegs, [dependent]
|
||||||
|
end
|
||||||
|
|
||||||
|
nil
|
||||||
end
|
end
|
||||||
|
|
||||||
def rm_pin(rack)
|
def rm_pin(rack)
|
||||||
|
|||||||
@ -298,7 +298,9 @@ class Keg
|
|||||||
|
|
||||||
def installed_dependents
|
def installed_dependents
|
||||||
Formula.installed.flat_map(&:installed_kegs).select do |keg|
|
Formula.installed.flat_map(&:installed_kegs).select do |keg|
|
||||||
Tab.for_keg(keg).runtime_dependencies.any? do |dep|
|
tab = Tab.for_keg(keg)
|
||||||
|
next if tab.runtime_dependencies.nil? # no dependency information saved.
|
||||||
|
tab.runtime_dependencies.any? do |dep|
|
||||||
# Resolve formula rather than directly comparing names
|
# Resolve formula rather than directly comparing names
|
||||||
# in case of conflicts between formulae from different taps.
|
# in case of conflicts between formulae from different taps.
|
||||||
dep_formula = Formulary.factory(dep["full_name"])
|
dep_formula = Formulary.factory(dep["full_name"])
|
||||||
|
|||||||
@ -43,6 +43,24 @@ class IntegrationCommandTestUninstall < IntegrationCommandTestCase
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_uninstall_leaving_dependents_no_runtime_dependencies_in_tab
|
||||||
|
cmd("install", "testball_f2")
|
||||||
|
|
||||||
|
f2_keg = f2.installed_kegs.first
|
||||||
|
f2_tab = Tab.for_keg(f2_keg)
|
||||||
|
f2_tab.runtime_dependencies = nil
|
||||||
|
f2_tab.write
|
||||||
|
|
||||||
|
run_as_not_developer do
|
||||||
|
assert_match "Refusing to uninstall",
|
||||||
|
cmd_fail("uninstall", "testball_f1")
|
||||||
|
refute_empty f1.installed_kegs
|
||||||
|
assert_match "Uninstalling #{f2.rack}",
|
||||||
|
cmd("uninstall", "testball_f2")
|
||||||
|
assert_empty f2.installed_kegs
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def test_uninstall_force_leaving_dependents
|
def test_uninstall_force_leaving_dependents
|
||||||
cmd("install", "testball_f2")
|
cmd("install", "testball_f2")
|
||||||
run_as_not_developer do
|
run_as_not_developer do
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user