Fix unbottled dependency handling

- Rename `BuildToolsError` to `UnbottledError` to better reflect what it
  does (particularly now)
- Improve the `UnbottledError` messaging
- Raise the `UnbottledError` for dependencies also when building bottles
  (so that we don't try and build bottles against things that have been
  built from source).
This commit is contained in:
Mike McQuaid 2020-12-11 16:57:47 +00:00
parent 2be340c6d6
commit eb74717a9e
No known key found for this signature in database
GPG Key ID: 48A898132FD8EE70
3 changed files with 24 additions and 21 deletions

View File

@ -488,17 +488,18 @@ class BuildError < RuntimeError
end end
end end
# Raised by {FormulaInstaller#check_dependencies_bottled} and # Raised if the formula or its dependencies are not bottled and are being
# {FormulaInstaller#install} if the formula or its dependencies are not bottled # installed in a situation where a bottle is required.
# and are being installed on a system without necessary build tools. class UnbottledError < RuntimeError
class BuildToolsError < RuntimeError
def initialize(formulae) def initialize(formulae)
super <<~EOS msg = +<<~EOS
The following #{"formula".pluralize(formulae.count)} The following #{"formula".pluralize(formulae.count)} cannot be installed from #{"bottle".pluralize(formulae.count)} and must be
built from source.
#{formulae.to_sentence} #{formulae.to_sentence}
cannot be installed as #{"binary package".pluralize(formulae.count)} and must be built from source.
#{DevelopmentTools.installation_instructions}
EOS EOS
msg += "#{DevelopmentTools.installation_instructions}\n" unless DevelopmentTools.installed?
msg.freeze
super(msg)
end end
end end

View File

@ -356,11 +356,17 @@ class FormulaInstaller
check_conflicts check_conflicts
raise BuildToolsError, [formula] if !pour_bottle? && !formula.bottle_unneeded? && !DevelopmentTools.installed? raise UnbottledError, [formula] if !pour_bottle? && !formula.bottle_unneeded? && !DevelopmentTools.installed?
unless ignore_deps? unless ignore_deps?
deps = compute_dependencies deps = compute_dependencies
check_dependencies_bottled(deps) if pour_bottle? && !DevelopmentTools.installed? if ((pour_bottle? && !DevelopmentTools.installed?) || build_bottle?) &&
(unbottled = unbottled_dependencies(deps)).presence
# Check that each dependency in deps has a bottle available, terminating
# abnormally with a UnbottledError if one or more don't.
raise UnbottledError, unbottled
end
install_dependencies(deps) install_dependencies(deps)
end end
@ -412,7 +418,7 @@ class FormulaInstaller
@pour_failed = true @pour_failed = true
onoe e.message onoe e.message
opoo "Bottle installation failed: building from source." opoo "Bottle installation failed: building from source."
raise BuildToolsError, [formula] unless DevelopmentTools.installed? raise UnbottledError, [formula] unless DevelopmentTools.installed?
compute_and_install_dependencies unless ignore_deps? compute_and_install_dependencies unless ignore_deps?
else else
@ -490,16 +496,12 @@ class FormulaInstaller
expand_dependencies(req_deps + formula.deps) expand_dependencies(req_deps + formula.deps)
end end
# Check that each dependency in deps has a bottle available, terminating def unbottled_dependencies(deps)
# abnormally with a BuildToolsError if one or more don't. deps.map(&:first).map(&:to_formula).reject do |dep_f|
# Only invoked when the user has no developer tools. next false unless dep_f.pour_bottle?
def check_dependencies_bottled(deps)
unbottled = deps.reject do |dep, _|
dep_f = dep.to_formula
dep_f.pour_bottle? || dep_f.bottle_unneeded?
end
raise BuildToolsError, unbottled unless unbottled.empty? dep_f.bottle_unneeded? || dep_f.bottled?
end
end end
def compute_and_install_dependencies def compute_and_install_dependencies

View File

@ -83,7 +83,7 @@ describe FormulaInstaller do
expect { expect {
described_class.new(formula).install described_class.new(formula).install
}.to raise_error(BuildToolsError) }.to raise_error(UnbottledError)
expect(formula).not_to be_latest_version_installed expect(formula).not_to be_latest_version_installed
end end