Check version conflicts using linkage.

Instead of refusing to install software preemptively by assuming
multiple linkage to differing versions of the same library we now make
`brew linkage --test` verify that we don't have two versions of the
same library linked at the same time.

This will be considerably more permissive whilst checking the actual
problem that we're worried about.
This commit is contained in:
Mike McQuaid 2018-08-27 10:12:02 +01:00
parent 31ab0bb391
commit ca6c75d229
No known key found for this signature in database
GPG Key ID: 48A898132FD8EE70
2 changed files with 22 additions and 27 deletions

View File

@ -155,8 +155,6 @@ class FormulaInstaller
recursive_deps = formula.recursive_dependencies
recursive_formulae = recursive_deps.map(&:to_formula)
recursive_runtime_formulae =
formula.runtime_formula_dependencies(undeclared: false)
recursive_dependencies = []
recursive_formulae.each do |dep|
@ -182,25 +180,6 @@ class FormulaInstaller
EOS
end
version_hash = {}
version_conflicts = Set.new
recursive_runtime_formulae.each do |f|
name = f.name
unversioned_name, = name.split("@")
next if unversioned_name == "python"
version_hash[unversioned_name] ||= Set.new
version_hash[unversioned_name] << name
next if version_hash[unversioned_name].length < 2
version_conflicts += version_hash[unversioned_name]
end
unless version_conflicts.empty?
raise CannotInstallFormulaError, <<~EOS
#{formula.full_name} contains conflicting version recursive dependencies:
#{version_conflicts.to_a.join ", "}
View these with `brew deps --tree #{formula.full_name}`.
EOS
end
pinned_unsatisfied_deps = recursive_deps.select do |dep|
dep.to_formula.pinned? && !dep.satisfied?(inherited_options_for(dep))
end

View File

@ -19,6 +19,7 @@ class LinkageChecker
@indirect_deps = []
@undeclared_deps = []
@unnecessary_deps = []
@version_conflict_deps = []
check_dylibs(rebuild_cache: rebuild_cache)
end
@ -50,11 +51,14 @@ class LinkageChecker
def display_test_output(puts_output: true)
display_items "Missing libraries", @broken_dylibs, puts_output: puts_output
display_items "Broken dependencies", @broken_deps, puts_output: puts_output
display_items "Conflicting libraries", @version_conflict_deps, puts_output: puts_output
puts "No broken library linkage" unless broken_library_linkage?
end
def broken_library_linkage?
!@broken_dylibs.empty? || !@broken_deps.empty?
!@broken_dylibs.empty? ||
!@broken_deps.empty? ||
!@version_conflict_deps.empty?
end
private
@ -127,8 +131,8 @@ class LinkageChecker
end
if formula
@indirect_deps, @undeclared_deps, @unnecessary_deps =
check_undeclared_deps
@indirect_deps, @undeclared_deps, @unnecessary_deps,
@version_conflict_deps = check_formula_deps
end
return unless keg_files_dylibs_was_empty
@ -136,7 +140,7 @@ class LinkageChecker
store&.update!(keg_files_dylibs: keg_files_dylibs)
end
def check_undeclared_deps
def check_formula_deps
filter_out = proc do |dep|
next true if dep.build?
next false unless dep.optional? || dep.recommended?
@ -170,13 +174,25 @@ class LinkageChecker
unnecessary_deps = declared_deps_full_names.reject do |full_name|
next true if Formula[full_name].bin.directory?
name = full_name.split("/").last
@brewed_dylibs.keys.map { |x| x.split("/").last }.include?(name)
@brewed_dylibs.keys.map { |l| l.split("/").last }.include?(name)
end
missing_deps = @broken_deps.values.flatten.map { |d| dylib_to_dep(d) }
unnecessary_deps -= missing_deps
[indirect_deps, undeclared_deps, unnecessary_deps]
version_hash = {}
version_conflict_deps = Set.new
@brewed_dylibs.keys.each do |l|
name = l.split("/").last
unversioned_name, = name.split("@")
version_hash[unversioned_name] ||= Set.new
version_hash[unversioned_name] << name
next if version_hash[unversioned_name].length < 2
version_conflict_deps += version_hash[unversioned_name]
end
[indirect_deps, undeclared_deps,
unnecessary_deps, version_conflict_deps.to_a]
end
def sort_by_formula_full_name!(arr)