diff --git a/Library/Homebrew/install.rb b/Library/Homebrew/install.rb index 49ace9b935..a67a8297d4 100644 --- a/Library/Homebrew/install.rb +++ b/Library/Homebrew/install.rb @@ -13,354 +13,354 @@ module Homebrew # @api private module Install class << self - def perform_preinstall_checks(all_fatal: false, cc: nil) - check_prefix - check_cpu - attempt_directory_creation - check_cc_argv(cc) - Diagnostic.checks(:supported_configuration_checks, fatal: all_fatal) - Diagnostic.checks(:fatal_preinstall_checks) - end - alias generic_perform_preinstall_checks 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) - end - - def global_post_install; end - alias generic_global_post_install global_post_install - - 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 + def perform_preinstall_checks(all_fatal: false, cc: nil) + check_prefix + check_cpu + attempt_directory_creation + check_cc_argv(cc) + Diagnostic.checks(:supported_configuration_checks, fatal: all_fatal) + Diagnostic.checks(:fatal_preinstall_checks) end - end + alias generic_perform_preinstall_checks perform_preinstall_checks - 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 - 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 - private_class_method :attempt_directory_creation - - 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 - private_class_method :check_cc_argv - - def install_formula?( - formula, - head: false, - fetch_head: false, - only_dependencies: false, - force: false, - quiet: false - ) - # head-only without --HEAD is an error - if !head && formula.stable.nil? - odie <<~EOS - #{formula.full_name} is a head-only formula. - To install it, run: - brew install --HEAD #{formula.full_name} - EOS + 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) end - # --HEAD, fail with no head defined - odie "No head is defined for #{formula.full_name}" if head && formula.head.nil? + def global_post_install; end + alias generic_global_post_install global_post_install - installed_head_version = formula.latest_head_version - if installed_head_version && - !formula.head_version_outdated?(installed_head_version, fetch_head: fetch_head) - new_head_installed = true - end - prefix_installed = formula.prefix.exist? && !formula.prefix.children.empty? - - if formula.keg_only? && formula.any_version_installed? && formula.optlinked? && !force - # 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 formula.outdated? - if !Homebrew::EnvConfig.no_install_upgrade? && !formula.pinned? - name = formula.name - version = formula.linked_version - puts "#{name} #{version} is already installed but outdated (so it will be upgraded)." - return true - end - - unpin_cmd_if_needed = ("brew unpin #{formula.full_name} && " if formula.pinned?) - optlinked_version = Keg.for(formula.opt_prefix).version - onoe <<~EOS - #{formula.full_name} #{optlinked_version} is already installed. - To upgrade to #{formula.version}, run: - #{unpin_cmd_if_needed}brew upgrade #{formula.full_name} - EOS - elsif only_dependencies - return true - elsif !quiet - opoo <<~EOS - #{formula.full_name} #{formula.pkg_version} is already installed and up-to-date. - To reinstall #{formula.pkg_version}, run: - brew reinstall #{formula.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 - formula.latest_head_version - else - formula.pkg_version - end - - msg = "#{formula.full_name} #{installed_version} is already installed" - linked_not_equals_installed = formula.linked_version != installed_version - if formula.linked? && linked_not_equals_installed - msg = if quiet - nil - else - <<~EOS - #{msg}. - The currently linked version is: #{formula.linked_version} + 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 - end - elsif only_dependencies - msg = nil - return true - elsif !formula.linked? || formula.keg_only? - msg = <<~EOS - #{msg}, it's just not linked. - To link this version, run: - brew link #{formula} - EOS - else - msg = if quiet - nil else - <<~EOS - #{msg} and up-to-date. + 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 + 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 + private_class_method :attempt_directory_creation + + 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 + private_class_method :check_cc_argv + + def install_formula?( + formula, + head: false, + fetch_head: false, + only_dependencies: false, + force: false, + quiet: false + ) + # head-only without --HEAD is an error + if !head && formula.stable.nil? + odie <<~EOS + #{formula.full_name} is a head-only formula. + To install it, run: + brew install --HEAD #{formula.full_name} + EOS + end + + # --HEAD, fail with no head defined + odie "No head is defined for #{formula.full_name}" if head && formula.head.nil? + + installed_head_version = formula.latest_head_version + if installed_head_version && + !formula.head_version_outdated?(installed_head_version, fetch_head: fetch_head) + new_head_installed = true + end + prefix_installed = formula.prefix.exist? && !formula.prefix.children.empty? + + if formula.keg_only? && formula.any_version_installed? && formula.optlinked? && !force + # 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 formula.outdated? + if !Homebrew::EnvConfig.no_install_upgrade? && !formula.pinned? + name = formula.name + version = formula.linked_version + puts "#{name} #{version} is already installed but outdated (so it will be upgraded)." + return true + end + + unpin_cmd_if_needed = ("brew unpin #{formula.full_name} && " if formula.pinned?) + optlinked_version = Keg.for(formula.opt_prefix).version + onoe <<~EOS + #{formula.full_name} #{optlinked_version} is already installed. + To upgrade to #{formula.version}, run: + #{unpin_cmd_if_needed}brew upgrade #{formula.full_name} + EOS + elsif only_dependencies + return true + elsif !quiet + opoo <<~EOS + #{formula.full_name} #{formula.pkg_version} is already installed and up-to-date. To reinstall #{formula.pkg_version}, run: brew reinstall #{formula.name} EOS end - end - opoo msg if msg - elsif !formula.any_version_installed? && (old_formula = formula.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 - elsif formula.migration_needed? && !force - # 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 - #{formula.oldname} is already installed, it's just not migrated. - To migrate this formula, run: - brew migrate #{formula} - Or to force-install it, run: - brew install #{formula} --force - EOS - elsif formula.linked? - message = "#{formula.name} #{formula.linked_version} is already installed" - if formula.outdated? && !head - if !Homebrew::EnvConfig.no_install_upgrade? && !formula.pinned? - puts "#{message} but outdated (so it will be upgraded)." + 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 + formula.latest_head_version + else + formula.pkg_version + end + + msg = "#{formula.full_name} #{installed_version} is already installed" + linked_not_equals_installed = formula.linked_version != installed_version + if formula.linked? && linked_not_equals_installed + msg = if quiet + nil + else + <<~EOS + #{msg}. + The currently linked version is: #{formula.linked_version} + EOS + end + elsif only_dependencies + msg = nil return true + elsif !formula.linked? || formula.keg_only? + msg = <<~EOS + #{msg}, it's just not linked. + To link this version, run: + brew link #{formula} + EOS + else + msg = if quiet + nil + else + <<~EOS + #{msg} and up-to-date. + To reinstall #{formula.pkg_version}, run: + brew reinstall #{formula.name} + EOS + end end - - unpin_cmd_if_needed = ("brew unpin #{formula.full_name} && " if formula.pinned?) - onoe <<~EOS - #{message} - To upgrade to #{formula.pkg_version}, run: - #{unpin_cmd_if_needed}brew upgrade #{formula.full_name} + opoo msg if msg + elsif !formula.any_version_installed? && (old_formula = formula.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 + elsif formula.migration_needed? && !force + # 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 + #{formula.oldname} is already installed, it's just not migrated. + To migrate this formula, run: + brew migrate #{formula} + Or to force-install it, run: + brew install #{formula} --force EOS - elsif only_dependencies - return true + elsif formula.linked? + message = "#{formula.name} #{formula.linked_version} is already installed" + if formula.outdated? && !head + if !Homebrew::EnvConfig.no_install_upgrade? && !formula.pinned? + puts "#{message} but outdated (so it will be upgraded)." + return true + end + + unpin_cmd_if_needed = ("brew unpin #{formula.full_name} && " if formula.pinned?) + onoe <<~EOS + #{message} + To upgrade to #{formula.pkg_version}, run: + #{unpin_cmd_if_needed}brew upgrade #{formula.full_name} + EOS + elsif only_dependencies + return true + else + onoe <<~EOS + #{message} + To install #{formula.pkg_version}, first run: + brew unlink #{formula.name} + EOS + end else - onoe <<~EOS - #{message} - To install #{formula.pkg_version}, first run: - brew unlink #{formula.name} - EOS + # If none of the above is true and the formula is linked, then + # FormulaInstaller will handle this case. + return true end - else - # If none of the above is true and the formula is linked, then - # FormulaInstaller will handle this case. - return true + + # Even if we don't install this formula mark it as no longer just + # installed as a dependency. + return false unless formula.opt_prefix.directory? + + keg = Keg.new(formula.opt_prefix.resolved_path) + tab = Tab.for_keg(keg) + unless tab.installed_on_request + tab.installed_on_request = true + tab.write + end + + false end - # Even if we don't install this formula mark it as no longer just - # installed as a dependency. - return false unless formula.opt_prefix.directory? + def install_formulae( + formulae_to_install, + 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, + debug_symbols: false, + force: false, + overwrite: false, + debug: false, + quiet: false, + verbose: false, + dry_run: false, + skip_post_install: false + ) + formula_installers = formulae_to_install.map do |formula| + Migrator.migrate_if_needed(formula, force: force, dry_run: dry_run) + build_options = formula.build - keg = Keg.new(formula.opt_prefix.resolved_path) - tab = Tab.for_keg(keg) - unless tab.installed_on_request - tab.installed_on_request = true - tab.write - end + formula_installer = FormulaInstaller.new( + formula, + 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, + debug_symbols: debug_symbols, + force: force, + overwrite: overwrite, + debug: debug, + quiet: quiet, + verbose: verbose, + skip_post_install: skip_post_install, + ) - false - end - - def install_formulae( - formulae_to_install, - 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, - debug_symbols: false, - force: false, - overwrite: false, - debug: false, - quiet: false, - verbose: false, - dry_run: false, - skip_post_install: false - ) - formula_installers = formulae_to_install.map do |formula| - Migrator.migrate_if_needed(formula, force: force, dry_run: dry_run) - build_options = formula.build - - formula_installer = FormulaInstaller.new( - formula, - 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, - debug_symbols: debug_symbols, - force: force, - overwrite: overwrite, - debug: debug, - quiet: quiet, - verbose: verbose, - skip_post_install: skip_post_install, - ) - - begin - unless dry_run - formula_installer.prelude - formula_installer.fetch + begin + unless dry_run + formula_installer.prelude + formula_installer.fetch + end + formula_installer + rescue CannotInstallFormulaError => e + ofail e.message + nil + rescue UnsatisfiedRequirements, DownloadError, ChecksumMismatchError => e + ofail "#{formula}: #{e}" + nil end - formula_installer - rescue CannotInstallFormulaError => e - ofail e.message - nil - rescue UnsatisfiedRequirements, DownloadError, ChecksumMismatchError => e - ofail "#{formula}: #{e}" - nil - end - end.compact + end.compact - if dry_run - if (formulae_name_to_install = formulae_to_install.map(&:name)) - ohai "Would install #{Utils.pluralize("formula", formulae_name_to_install.count, - plural: "e", include_count: true)}:" - puts formulae_name_to_install.join(" ") + if dry_run + if (formulae_name_to_install = formulae_to_install.map(&:name)) + ohai "Would install #{Utils.pluralize("formula", formulae_name_to_install.count, + plural: "e", include_count: true)}:" + puts formulae_name_to_install.join(" ") - formula_installers.each do |fi| - print_dry_run_dependencies(fi.formula, fi.compute_dependencies, &:name) + formula_installers.each do |fi| + print_dry_run_dependencies(fi.formula, fi.compute_dependencies, &:name) + end end + return + end + + formula_installers.each do |fi| + install_formula(fi) + Cleanup.install_formula_clean!(fi.formula) end - return end - formula_installers.each do |fi| - install_formula(fi) - Cleanup.install_formula_clean!(fi.formula) + def install_formula(formula_installer) + formula = formula_installer.formula + + upgrade = formula.linked? && formula.outdated? && !formula.head? && !Homebrew::EnvConfig.no_install_upgrade? + + Upgrade.install_formula(formula_installer, upgrade: upgrade) end - end + private_class_method :install_formula - def install_formula(formula_installer) - formula = formula_installer.formula + def print_dry_run_dependencies(formula, dependencies, &block) + return if dependencies.empty? - upgrade = formula.linked? && formula.outdated? && !formula.head? && !Homebrew::EnvConfig.no_install_upgrade? - - Upgrade.install_formula(formula_installer, upgrade: upgrade) - end - private_class_method :install_formula - - def print_dry_run_dependencies(formula, dependencies, &block) - return if dependencies.empty? - - ohai "Would install #{Utils.pluralize("dependenc", dependencies.count, plural: "ies", singular: "y", + ohai "Would install #{Utils.pluralize("dependenc", dependencies.count, plural: "ies", singular: "y", include_count: true)} for #{formula.name}:" - formula_names = dependencies.map(&:first).map(&:to_formula).map(&block) - puts formula_names.join(" ") + formula_names = dependencies.map(&:first).map(&:to_formula).map(&block) + puts formula_names.join(" ") + end end end end -end require "extend/os/install" diff --git a/Library/Homebrew/os/linux.rb b/Library/Homebrew/os/linux.rb index cf03b80ada..0d7a7ca916 100644 --- a/Library/Homebrew/os/linux.rb +++ b/Library/Homebrew/os/linux.rb @@ -50,8 +50,6 @@ module OS # rubocop:disable Style/Documentation module Mac - module_function - ::MacOS = OS::Mac raise "Loaded OS::Linux on generic OS!" if ENV["HOMEBREW_TEST_GENERIC_OS"] @@ -85,8 +83,6 @@ module OS end module Xcode - module_function - def self.version ::Version::NULL end @@ -97,8 +93,6 @@ module OS end module CLT - module_function - def self.version ::Version::NULL end diff --git a/Library/Homebrew/os/mac/xcode.rb b/Library/Homebrew/os/mac/xcode.rb index 70f610e63e..97088b1f91 100755 --- a/Library/Homebrew/os/mac/xcode.rb +++ b/Library/Homebrew/os/mac/xcode.rb @@ -261,8 +261,6 @@ module OS module CLT extend T::Sig - module_function - # The original Mavericks CLT package ID EXECUTABLE_PKG_ID = "com.apple.pkg.CLTools_Executables" MAVERICKS_NEW_PKG_ID = "com.apple.pkg.CLTools_Base" # obsolete diff --git a/Library/Homebrew/utils/github/api.rb b/Library/Homebrew/utils/github/api.rb index 9155b86797..2e3e21d6e4 100644 --- a/Library/Homebrew/utils/github/api.rb +++ b/Library/Homebrew/utils/github/api.rb @@ -182,7 +182,9 @@ module GitHub EOS end - def self.open_rest(url, data: nil, data_binary_path: nil, request_method: nil, scopes: [].freeze, parse_json: true) + def self.open_rest( + url, data: nil, data_binary_path: nil, request_method: nil, scopes: [].freeze, parse_json: true + ) # This is a no-op if the user is opting out of using the GitHub API. return block_given? ? yield({}) : {} if Homebrew::EnvConfig.no_github_api? diff --git a/Library/Homebrew/utils/gzip.rb b/Library/Homebrew/utils/gzip.rb index 18a649751c..f31951fbf1 100644 --- a/Library/Homebrew/utils/gzip.rb +++ b/Library/Homebrew/utils/gzip.rb @@ -19,7 +19,7 @@ module Utils ).returns(Pathname) } def self.compress_with_options(path, mtime: ENV["SOURCE_DATE_EPOCH"].to_i, orig_name: File.basename(path), - output: "#{path}.gz") + output: "#{path}.gz") # Ideally, we would just set mtime = 0 if SOURCE_DATE_EPOCH is absent, but Ruby's # Zlib::GzipWriter does not properly handle the case of setting mtime = 0: # https://bugs.ruby-lang.org/issues/16285