brew/Library/Homebrew/install.rb

336 lines
11 KiB
Ruby
Raw Normal View History

2020-10-10 14:16:11 +02:00
# typed: true
# frozen_string_literal: true
require "diagnostic"
require "fileutils"
require "hardware"
require "development_tools"
require "upgrade"
module Homebrew
2020-08-17 18:39:55 +02:00
# Helper module for performing (pre-)install checks.
#
# @api private
module Install
2020-07-27 11:37:07 +02:00
module_function
2020-08-17 18:39:55 +02:00
def perform_preinstall_checks(all_fatal: false, cc: nil)
check_prefix
2020-08-17 18:39:55 +02:00
check_cpu
attempt_directory_creation
check_cc_argv(cc)
Diagnostic.checks(:supported_configuration_checks, fatal: all_fatal)
Diagnostic.checks(:fatal_preinstall_checks)
2020-08-17 18:39:55 +02:00
end
alias generic_perform_preinstall_checks perform_preinstall_checks
module_function :generic_perform_preinstall_checks
def perform_build_from_source_checks(all_fatal: false)
Diagnostic.checks(:fatal_build_from_source_checks)
Diagnostic.checks(:build_from_source_checks, fatal: all_fatal)
2020-08-17 18:39:55 +02:00
end
def check_prefix
if (Hardware::CPU.intel? || Hardware::CPU.in_rosetta2?) &&
HOMEBREW_PREFIX.to_s == HOMEBREW_MACOS_ARM_DEFAULT_PREFIX
if Hardware::CPU.in_rosetta2?
odie <<~EOS
Cannot install under Rosetta 2 in ARM default prefix (#{HOMEBREW_PREFIX})!
To rerun under ARM use:
arch -arm64 brew install ...
To install under x86_64, install Homebrew into #{HOMEBREW_DEFAULT_PREFIX}.
EOS
else
odie "Cannot install on Intel processor in ARM default prefix (#{HOMEBREW_PREFIX})!"
end
elsif Hardware::CPU.arm? && HOMEBREW_PREFIX.to_s == HOMEBREW_DEFAULT_PREFIX
odie <<~EOS
Cannot install in Homebrew on ARM processor in Intel default prefix (#{HOMEBREW_PREFIX})!
Please create a new installation in #{HOMEBREW_MACOS_ARM_DEFAULT_PREFIX} using one of the
"Alternative Installs" from:
#{Formatter.url("https://docs.brew.sh/Installation")}
You can migrate your previously installed formula list with:
brew bundle dump
EOS
end
end
def check_cpu
return unless Hardware::CPU.ppc?
odie <<~EOS
Sorry, Homebrew does not support your computer's CPU architecture!
For PowerPC Mac (PPC32/PPC64BE) support, see:
#{Formatter.url("https://github.com/mistydemeo/tigerbrew")}
EOS
end
2020-08-17 18:39:55 +02:00
private_class_method :check_cpu
def attempt_directory_creation
Keg::MUST_EXIST_DIRECTORIES.each do |dir|
FileUtils.mkdir_p(dir) unless dir.exist?
# Create these files to ensure that these directories aren't removed
# by the Catalina installer.
# (https://github.com/Homebrew/brew/issues/6263)
keep_file = dir/".keepme"
FileUtils.touch(keep_file) unless keep_file.exist?
rescue
nil
end
end
2020-08-17 18:39:55 +02:00
private_class_method :attempt_directory_creation
2020-07-27 11:37:07 +02:00
def check_cc_argv(cc)
return unless cc
@checks ||= Diagnostic::Checks.new
opoo <<~EOS
You passed `--cc=#{cc}`.
#{@checks.please_create_pull_requests}
EOS
end
2020-08-17 18:39:55 +02:00
private_class_method :check_cc_argv
2021-06-10 10:50:05 -04:00
def install_formula?(
f,
head: false,
fetch_head: false,
only_dependencies: false,
force: false,
quiet: false
)
# head-only without --HEAD is an error
if !head && f.stable.nil?
odie <<~EOS
#{f.full_name} is a head-only formula.
To install it, run:
brew install --HEAD #{f.full_name}
EOS
end
# --HEAD, fail with no head defined
odie "No head is defined for #{f.full_name}" if head && f.head.nil?
installed_head_version = f.latest_head_version
if installed_head_version &&
!f.head_version_outdated?(installed_head_version, fetch_head: fetch_head)
new_head_installed = true
end
prefix_installed = f.prefix.exist? && !f.prefix.children.empty?
2021-06-10 11:39:20 -04:00
if f.keg_only? && f.any_version_installed? && f.optlinked? && !force
2021-06-10 10:50:05 -04:00
# keg-only install is only possible when no other version is
# linked to opt, because installing without any warnings can break
# dependencies. Therefore before performing other checks we need to be
# sure --force flag is passed.
if f.outdated?
if !Homebrew::EnvConfig.no_install_upgrade? && !f.pinned?
puts "#{f.name} #{f.linked_version} is already installed but outdated (so it will be upgraded)."
return true
end
unpin_cmd_if_needed = if f.pinned?
"brew unpin #{f.full_name} && "
end
2021-06-10 10:50:05 -04:00
optlinked_version = Keg.for(f.opt_prefix).version
onoe <<~EOS
#{f.full_name} #{optlinked_version} is already installed.
To upgrade to #{f.version}, run:
#{unpin_cmd_if_needed}brew upgrade #{f.full_name}
2021-06-10 10:50:05 -04:00
EOS
elsif only_dependencies
return true
2021-06-10 11:39:20 -04:00
elsif !quiet
2021-06-10 10:50:05 -04:00
opoo <<~EOS
#{f.full_name} #{f.pkg_version} is already installed and up-to-date.
To reinstall #{f.pkg_version}, run:
brew reinstall #{f.name}
EOS
end
elsif (head && new_head_installed) || prefix_installed
# After we're sure that --force flag is passed for linked to opt
# keg-only we need to be sure that the version we're attempting to
# install is not already installed.
installed_version = if head
f.latest_head_version
else
f.pkg_version
end
msg = "#{f.full_name} #{installed_version} is already installed"
linked_not_equals_installed = f.linked_version != installed_version
if f.linked? && linked_not_equals_installed
msg = if quiet
nil
else
<<~EOS
#{msg}.
The currently linked version is: #{f.linked_version}
EOS
end
elsif !f.linked? || f.keg_only?
msg = <<~EOS
#{msg}, it's just not linked.
To link this version, run:
brew link #{f}
EOS
elsif only_dependencies
msg = nil
return true
else
msg = if quiet
nil
else
<<~EOS
#{msg} and up-to-date.
To reinstall #{f.pkg_version}, run:
brew reinstall #{f.name}
EOS
end
end
opoo msg if msg
elsif !f.any_version_installed? && (old_formula = f.old_installed_formulae.first)
msg = "#{old_formula.full_name} #{old_formula.any_installed_version} already installed"
msg = if !old_formula.linked? && !old_formula.keg_only?
<<~EOS
#{msg}, it's just not linked.
To link this version, run:
brew link #{old_formula.full_name}
EOS
elsif quiet
nil
else
"#{msg}."
end
opoo msg if msg
2021-06-10 11:39:20 -04:00
elsif f.migration_needed? && !force
2021-06-10 10:50:05 -04:00
# Check if the formula we try to install is the same as installed
# but not migrated one. If --force is passed then install anyway.
opoo <<~EOS
#{f.oldname} is already installed, it's just not migrated.
To migrate this formula, run:
brew migrate #{f}
Or to force-install it, run:
brew install #{f} --force
EOS
elsif f.linked?
message = "#{f.name} #{f.linked_version} is already installed"
if f.outdated? && !head
if !Homebrew::EnvConfig.no_install_upgrade? && !f.pinned?
puts "#{message} but outdated (so it will be upgraded)."
return true
end
unpin_cmd_if_needed = if f.pinned?
"brew unpin #{f.full_name} && "
end
onoe <<~EOS
#{message}
To upgrade to #{f.pkg_version}, run:
#{unpin_cmd_if_needed}brew upgrade #{f.full_name}
EOS
elsif only_dependencies
return true
else
onoe <<~EOS
#{message}
To install #{f.pkg_version}, first run:
brew unlink #{f.name}
EOS
end
2021-06-10 10:50:05 -04:00
else
# If none of the above is true and the formula is linked, then
# FormulaInstaller will handle this case.
return true
end
# Even if we don't install this formula mark it as no longer just
# installed as a dependency.
return false unless f.opt_prefix.directory?
keg = Keg.new(f.opt_prefix.resolved_path)
tab = Tab.for_keg(keg)
unless tab.installed_on_request
tab.installed_on_request = true
tab.write
end
false
end
def install_formulae(
formulae_to_install,
2021-06-10 10:50:05 -04:00
build_bottle: false,
force_bottle: false,
bottle_arch: nil,
ignore_deps: false,
only_deps: false,
include_test_formulae: [],
build_from_source_formulae: [],
cc: nil,
git: false,
interactive: false,
keep_tmp: false,
force: false,
debug: false,
quiet: false,
verbose: false
)
formula_installers = formulae_to_install.map do |f|
Migrator.migrate_if_needed(f, force: force)
build_options = f.build
fi = FormulaInstaller.new(
f,
options: build_options.used_options,
build_bottle: build_bottle,
force_bottle: force_bottle,
bottle_arch: bottle_arch,
ignore_deps: ignore_deps,
only_deps: only_deps,
include_test_formulae: include_test_formulae,
build_from_source_formulae: build_from_source_formulae,
cc: cc,
git: git,
interactive: interactive,
keep_tmp: keep_tmp,
force: force,
debug: debug,
quiet: quiet,
verbose: verbose,
)
begin
fi.prelude
fi.fetch
fi
rescue CannotInstallFormulaError => e
ofail e.message
nil
rescue UnsatisfiedRequirements, DownloadError, ChecksumMismatchError => e
ofail "#{f}: #{e}"
nil
end
end.compact
formula_installers.each do |fi|
install_formula(fi)
Cleanup.install_formula_clean!(fi.formula)
end
end
def install_formula(formula_installer)
f = formula_installer.formula
upgrade = f.linked? && f.outdated? && !f.head? && !Homebrew::EnvConfig.no_install_upgrade?
Upgrade.install_formula(formula_installer, upgrade: upgrade)
2021-06-10 10:50:05 -04:00
end
private_class_method :install_formula
end
end
2018-09-28 14:01:09 -07:00
require "extend/os/install"