Separate formula conflicts from requirements
Closes Homebrew/homebrew#20357.
This commit is contained in:
parent
33cae6ac42
commit
8b9a3a560f
@ -174,11 +174,11 @@ class FormulaAuditor
|
||||
end
|
||||
|
||||
def audit_conflicts
|
||||
f.conflicts.each do |req|
|
||||
f.conflicts.each do |c|
|
||||
begin
|
||||
Formula.factory req.formula
|
||||
Formula.factory(c.name)
|
||||
rescue FormulaUnavailableError
|
||||
problem "Can't find conflicting formula \"#{req.formula}\"."
|
||||
problem "Can't find conflicting formula #{c.name.inspect}."
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -102,7 +102,7 @@ module Homebrew extend self
|
||||
puts
|
||||
end
|
||||
|
||||
conflicts = f.conflicts.map(&:formula).sort!
|
||||
conflicts = f.conflicts.map(&:name).sort!
|
||||
puts "Conflicts with: #{conflicts*', '}" unless conflicts.empty?
|
||||
|
||||
if f.rack.directory?
|
||||
|
||||
@ -115,6 +115,38 @@ class UnsatisfiedRequirements < Homebrew::InstallationError
|
||||
end
|
||||
end
|
||||
|
||||
class FormulaConflictError < Homebrew::InstallationError
|
||||
attr_reader :f, :conflicts
|
||||
|
||||
def initialize(f, conflicts)
|
||||
@f = f
|
||||
@conflicts = conflicts
|
||||
super f, message
|
||||
end
|
||||
|
||||
def conflict_message(conflict)
|
||||
message = []
|
||||
message << " #{conflict.name}"
|
||||
message << ": because #{conflict.reason}" if conflict.reason
|
||||
message.join
|
||||
end
|
||||
|
||||
def message
|
||||
message = []
|
||||
message << "Cannot install #{f.name} because conflicting formulae are installed.\n"
|
||||
message.concat conflicts.map { |c| conflict_message(c) } << ""
|
||||
message << <<-EOS.undent
|
||||
Please `brew unlink #{conflicts.map(&:name)*' '}` before continuing.
|
||||
|
||||
Unlinking removes a formula's symlinks from #{HOMEBREW_PREFIX}. You can
|
||||
link the formula again after the install finishes. You can --force this
|
||||
install, but the build may fail or cause obscure side-effects in the
|
||||
resulting software.
|
||||
EOS
|
||||
message.join("\n")
|
||||
end
|
||||
end
|
||||
|
||||
class BuildError < Homebrew::InstallationError
|
||||
attr_reader :exit_status, :command, :env
|
||||
|
||||
|
||||
@ -491,7 +491,7 @@ class Formula
|
||||
end
|
||||
|
||||
def conflicts
|
||||
requirements.grep(ConflictRequirement)
|
||||
self.class.conflicts
|
||||
end
|
||||
|
||||
# Returns a list of Dependency objects in an installable order, which
|
||||
@ -764,8 +764,12 @@ class Formula
|
||||
@plist_manual = options[:manual]
|
||||
end
|
||||
|
||||
def conflicts_with formula, opts={}
|
||||
dependencies.add ConflictRequirement.new(formula, name, opts)
|
||||
def conflicts
|
||||
@conflicts ||= []
|
||||
end
|
||||
|
||||
def conflicts_with name, opts={}
|
||||
conflicts << FormulaConflict.new(name, opts[:because])
|
||||
end
|
||||
|
||||
def skip_clean *paths
|
||||
|
||||
@ -78,6 +78,8 @@ class FormulaInstaller
|
||||
EOS
|
||||
end
|
||||
|
||||
check_conflicts
|
||||
|
||||
unless ignore_deps
|
||||
perform_readline_hack
|
||||
check_requirements
|
||||
@ -121,6 +123,17 @@ class FormulaInstaller
|
||||
end
|
||||
end
|
||||
|
||||
def check_conflicts
|
||||
return if ARGV.force?
|
||||
|
||||
conflicts = f.conflicts.reject do |c|
|
||||
keg = Formula.factory(c.name).prefix
|
||||
not keg.directory? && Keg.new(keg).linked?
|
||||
end
|
||||
|
||||
raise FormulaConflictError.new(f, conflicts) unless conflicts.empty?
|
||||
end
|
||||
|
||||
def check_requirements
|
||||
unsatisfied = ARGV.filter_for_dependencies do
|
||||
f.recursive_requirements do |dependent, req|
|
||||
|
||||
@ -2,6 +2,8 @@ require 'download_strategy'
|
||||
require 'checksum'
|
||||
require 'version'
|
||||
|
||||
FormulaConflict = Struct.new(:name, :reason)
|
||||
|
||||
class SoftwareSpec
|
||||
attr_reader :checksum, :mirrors, :specs
|
||||
attr_reader :using # for auditing
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
require 'requirement'
|
||||
require 'requirements/conflict_requirement'
|
||||
require 'requirements/language_module_dependency'
|
||||
require 'requirements/x11_dependency'
|
||||
require 'requirements/mpi_dependency'
|
||||
|
||||
@ -1,33 +0,0 @@
|
||||
require 'requirement'
|
||||
|
||||
# This requirement added by the `conflicts_with` DSL method.
|
||||
class ConflictRequirement < Requirement
|
||||
attr_reader :formula
|
||||
|
||||
# The user can chose to force installation even in the face of conflicts.
|
||||
fatal !ARGV.force?
|
||||
|
||||
def initialize formula, name, opts={}
|
||||
@formula = formula
|
||||
@name = name
|
||||
@opts = opts
|
||||
super([formula])
|
||||
end
|
||||
|
||||
def message
|
||||
message = "#{@name.downcase} cannot be installed alongside #{@formula}.\n"
|
||||
message << "This is because #{@opts[:because]}\n" if @opts[:because]
|
||||
message << <<-EOS.undent unless ARGV.force?
|
||||
Please `brew unlink #{@formula}` before continuing. Unlinking removes
|
||||
the formula's symlinks from #{HOMEBREW_PREFIX}. You can link the
|
||||
formula again after the install finishes. You can --force this install
|
||||
but the build may fail or cause obscure side-effects in the end-binary.
|
||||
EOS
|
||||
message
|
||||
end
|
||||
|
||||
satisfy :build_env => false do
|
||||
keg = Formula.factory(@formula).prefix
|
||||
not keg.exist? && Keg.new(keg).linked?
|
||||
end
|
||||
end
|
||||
Loading…
x
Reference in New Issue
Block a user