| 
									
										
										
										
											2024-03-30 09:36:47 -07:00
										 |  |  | # typed: strict | 
					
						
							| 
									
										
										
										
											2019-04-19 15:38:03 +09:00
										 |  |  | # frozen_string_literal: true | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-30 09:36:47 -07:00
										 |  |  | require "abstract_command" | 
					
						
							| 
									
										
										
										
											2020-09-25 21:13:26 +02:00
										 |  |  | require "cask/config" | 
					
						
							| 
									
										
										
										
											2023-04-19 21:31:22 +09:00
										 |  |  | require "cask/installer" | 
					
						
							|  |  |  | require "cask_dependent" | 
					
						
							| 
									
										
										
										
											2017-03-18 17:02:08 +02:00
										 |  |  | require "missing_formula" | 
					
						
							| 
									
										
										
										
											2014-06-16 13:36:17 -05:00
										 |  |  | require "formula_installer" | 
					
						
							| 
									
										
										
										
											2016-07-29 20:31:32 -06:00
										 |  |  | require "development_tools" | 
					
						
							| 
									
										
										
										
											2018-06-05 23:19:18 -04:00
										 |  |  | require "install" | 
					
						
							| 
									
										
										
										
											2019-01-03 16:23:44 +00:00
										 |  |  | require "cleanup" | 
					
						
							| 
									
										
										
										
											2020-07-02 12:53:52 +01:00
										 |  |  | require "upgrade" | 
					
						
							| 
									
										
										
										
											2010-09-11 20:22:54 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-18 22:41:47 -05:00
										 |  |  | module Homebrew | 
					
						
							| 
									
										
										
										
											2024-03-30 09:36:47 -07:00
										 |  |  |   module Cmd | 
					
						
							|  |  |  |     class InstallCmd < AbstractCommand | 
					
						
							|  |  |  |       cmd_args do | 
					
						
							|  |  |  |         description <<~EOS | 
					
						
							|  |  |  |           Install a <formula> or <cask>. Additional options specific to a <formula> may be | 
					
						
							|  |  |  |           appended to the command. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-27 14:21:27 +00:00
										 |  |  |           Unless `$HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK` is set, `brew upgrade` or `brew reinstall` will be run for | 
					
						
							| 
									
										
										
										
											2024-03-30 09:36:47 -07:00
										 |  |  |           outdated dependents and dependents with broken linkage, respectively. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-27 14:21:27 +00:00
										 |  |  |           Unless `$HOMEBREW_NO_INSTALL_CLEANUP` is set, `brew cleanup` will then be run for | 
					
						
							| 
									
										
										
										
											2024-03-30 09:36:47 -07:00
										 |  |  |           the installed formulae or, every 30 days, for all formulae. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-27 14:21:27 +00:00
										 |  |  |           Unless `$HOMEBREW_NO_INSTALL_UPGRADE` is set, `brew install` <formula> will upgrade <formula> if it | 
					
						
							| 
									
										
										
										
											2024-03-30 09:36:47 -07:00
										 |  |  |           is already installed but outdated. | 
					
						
							|  |  |  |         EOS | 
					
						
							|  |  |  |         switch "-d", "--debug", | 
					
						
							|  |  |  |                description: "If brewing fails, open an interactive debugging session with access to IRB " \ | 
					
						
							|  |  |  |                             "or a shell inside the temporary build directory." | 
					
						
							| 
									
										
										
										
											2024-04-08 07:35:01 -04:00
										 |  |  |         switch "--display-times", | 
					
						
							| 
									
										
										
										
											2025-06-03 11:06:35 -04:00
										 |  |  |                description: "Print install times for each package at the end of the run.", | 
					
						
							|  |  |  |                env:         :display_install_times | 
					
						
							| 
									
										
										
										
											2024-03-30 09:36:47 -07:00
										 |  |  |         switch "-f", "--force", | 
					
						
							|  |  |  |                description: "Install formulae without checking for previously installed keg-only or " \ | 
					
						
							|  |  |  |                             "non-migrated versions. When installing casks, overwrite existing files " \ | 
					
						
							|  |  |  |                             "(binaries and symlinks are excluded, unless originally from the same cask)." | 
					
						
							|  |  |  |         switch "-v", "--verbose", | 
					
						
							|  |  |  |                description: "Print the verification and post-install steps." | 
					
						
							|  |  |  |         switch "-n", "--dry-run", | 
					
						
							|  |  |  |                description: "Show what would be installed, but do not actually install anything." | 
					
						
							| 
									
										
										
										
											2025-05-07 12:07:29 -04:00
										 |  |  |         switch "--ask", | 
					
						
							|  |  |  |                description: "Ask for confirmation before downloading and installing formulae. " \ | 
					
						
							| 
									
										
										
										
											2025-06-03 11:06:35 -04:00
										 |  |  |                             "Print download and install sizes of bottles and dependencies.", | 
					
						
							|  |  |  |                env:         :ask | 
					
						
							| 
									
										
										
										
											2024-03-30 09:36:47 -07:00
										 |  |  |         [ | 
					
						
							|  |  |  |           [:switch, "--formula", "--formulae", { | 
					
						
							|  |  |  |             description: "Treat all named arguments as formulae.", | 
					
						
							|  |  |  |           }], | 
					
						
							|  |  |  |           [:flag, "--env=", { | 
					
						
							|  |  |  |             description: "Disabled other than for internal Homebrew use.", | 
					
						
							|  |  |  |             hidden:      true, | 
					
						
							|  |  |  |           }], | 
					
						
							|  |  |  |           [:switch, "--ignore-dependencies", { | 
					
						
							|  |  |  |             description: "An unsupported Homebrew development option to skip installing any dependencies of any " \ | 
					
						
							|  |  |  |                          "kind. If the dependencies are not already present, the formula will have issues. If " \ | 
					
						
							|  |  |  |                          "you're not developing Homebrew, consider adjusting your PATH rather than using this " \ | 
					
						
							|  |  |  |                          "option.", | 
					
						
							|  |  |  |           }], | 
					
						
							|  |  |  |           [:switch, "--only-dependencies", { | 
					
						
							|  |  |  |             description: "Install the dependencies with specified options but do not install the " \ | 
					
						
							|  |  |  |                          "formula itself.", | 
					
						
							|  |  |  |           }], | 
					
						
							|  |  |  |           [:flag, "--cc=", { | 
					
						
							|  |  |  |             description: "Attempt to compile using the specified <compiler>, which should be the name of the " \ | 
					
						
							| 
									
										
										
										
											2024-08-22 17:42:46 -04:00
										 |  |  |                          "compiler's executable, e.g. `gcc-9` for GCC 9. In order to use LLVM's clang, specify " \ | 
					
						
							| 
									
										
										
										
											2024-03-30 09:36:47 -07:00
										 |  |  |                          "`llvm_clang`. To use the Apple-provided clang, specify `clang`. This option will only " \ | 
					
						
							|  |  |  |                          "accept compilers that are provided by Homebrew or bundled with macOS. Please do not " \ | 
					
						
							|  |  |  |                          "file issues if you encounter errors while using this option.", | 
					
						
							|  |  |  |           }], | 
					
						
							|  |  |  |           [:switch, "-s", "--build-from-source", { | 
					
						
							|  |  |  |             description: "Compile <formula> from source even if a bottle is provided. " \ | 
					
						
							|  |  |  |                          "Dependencies will still be installed from bottles if they are available.", | 
					
						
							|  |  |  |           }], | 
					
						
							|  |  |  |           [:switch, "--force-bottle", { | 
					
						
							|  |  |  |             description: "Install from a bottle if it exists for the current or newest version of " \ | 
					
						
							|  |  |  |                          "macOS, even if it would not normally be used for installation.", | 
					
						
							|  |  |  |           }], | 
					
						
							|  |  |  |           [:switch, "--include-test", { | 
					
						
							|  |  |  |             description: "Install testing dependencies required to run `brew test` <formula>.", | 
					
						
							|  |  |  |           }], | 
					
						
							|  |  |  |           [:switch, "--HEAD", { | 
					
						
							|  |  |  |             description: "If <formula> defines it, install the HEAD version, aka. main, trunk, unstable, master.", | 
					
						
							|  |  |  |           }], | 
					
						
							|  |  |  |           [:switch, "--fetch-HEAD", { | 
					
						
							|  |  |  |             description: "Fetch the upstream repository to detect if the HEAD installation of the " \ | 
					
						
							|  |  |  |                          "formula is outdated. Otherwise, the repository's HEAD will only be checked for " \ | 
					
						
							|  |  |  |                          "updates when a new stable or development version has been released.", | 
					
						
							|  |  |  |           }], | 
					
						
							|  |  |  |           [:switch, "--keep-tmp", { | 
					
						
							|  |  |  |             description: "Retain the temporary files created during installation.", | 
					
						
							|  |  |  |           }], | 
					
						
							|  |  |  |           [:switch, "--debug-symbols", { | 
					
						
							|  |  |  |             depends_on:  "--build-from-source", | 
					
						
							|  |  |  |             description: "Generate debug symbols on build. Source will be retained in a cache directory.", | 
					
						
							|  |  |  |           }], | 
					
						
							|  |  |  |           [:switch, "--build-bottle", { | 
					
						
							|  |  |  |             description: "Prepare the formula for eventual bottling during installation, skipping any " \ | 
					
						
							|  |  |  |                          "post-install steps.", | 
					
						
							|  |  |  |           }], | 
					
						
							|  |  |  |           [:switch, "--skip-post-install", { | 
					
						
							|  |  |  |             description: "Install but skip any post-install steps.", | 
					
						
							|  |  |  |           }], | 
					
						
							| 
									
										
										
										
											2025-01-23 14:42:03 +00:00
										 |  |  |           [:switch, "--skip-link", { | 
					
						
							|  |  |  |             description: "Install but skip linking the keg into the prefix.", | 
					
						
							|  |  |  |           }], | 
					
						
							| 
									
										
										
										
											2025-03-21 15:49:22 +00:00
										 |  |  |           [:switch, "--as-dependency", { | 
					
						
							|  |  |  |             description: "Install but mark as installed as a dependency and not installed on request.", | 
					
						
							|  |  |  |           }], | 
					
						
							| 
									
										
										
										
											2024-03-30 09:36:47 -07:00
										 |  |  |           [:flag, "--bottle-arch=", { | 
					
						
							|  |  |  |             depends_on:  "--build-bottle", | 
					
						
							|  |  |  |             description: "Optimise bottles for the specified architecture rather than the oldest " \ | 
					
						
							|  |  |  |                          "architecture supported by the version of macOS the bottles are built on.", | 
					
						
							|  |  |  |           }], | 
					
						
							|  |  |  |           [:switch, "-i", "--interactive", { | 
					
						
							|  |  |  |             description: "Download and patch <formula>, then open a shell. This allows the user to " \ | 
					
						
							|  |  |  |                          "run `./configure --help` and otherwise determine how to turn the software " \ | 
					
						
							|  |  |  |                          "package into a Homebrew package.", | 
					
						
							|  |  |  |           }], | 
					
						
							|  |  |  |           [:switch, "-g", "--git", { | 
					
						
							|  |  |  |             description: "Create a Git repository, useful for creating patches to the software.", | 
					
						
							|  |  |  |           }], | 
					
						
							|  |  |  |           [:switch, "--overwrite", { | 
					
						
							|  |  |  |             description: "Delete files that already exist in the prefix while linking.", | 
					
						
							|  |  |  |           }], | 
					
						
							|  |  |  |         ].each do |args| | 
					
						
							|  |  |  |           options = args.pop | 
					
						
							|  |  |  |           send(*args, **options) | 
					
						
							|  |  |  |           conflicts "--cask", args.last | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  |         formula_options | 
					
						
							|  |  |  |         [ | 
					
						
							| 
									
										
										
										
											2025-06-03 13:01:49 -04:00
										 |  |  |           [:switch, "--cask", "--casks", { | 
					
						
							|  |  |  |             description: "Treat all named arguments as casks.", | 
					
						
							|  |  |  |           }], | 
					
						
							| 
									
										
										
										
											2024-03-30 09:36:47 -07:00
										 |  |  |           [:switch, "--[no-]binaries", { | 
					
						
							|  |  |  |             description: "Disable/enable linking of helper executables (default: enabled).", | 
					
						
							|  |  |  |             env:         :cask_opts_binaries, | 
					
						
							|  |  |  |           }], | 
					
						
							| 
									
										
										
										
											2025-06-03 13:01:49 -04:00
										 |  |  |           [:switch, "--require-sha", { | 
					
						
							| 
									
										
										
										
											2024-03-30 09:36:47 -07:00
										 |  |  |             description: "Require all casks to have a checksum.", | 
					
						
							|  |  |  |             env:         :cask_opts_require_sha, | 
					
						
							|  |  |  |           }], | 
					
						
							|  |  |  |           [:switch, "--[no-]quarantine", { | 
					
						
							|  |  |  |             description: "Disable/enable quarantining of downloads (default: enabled).", | 
					
						
							|  |  |  |             env:         :cask_opts_quarantine, | 
					
						
							|  |  |  |           }], | 
					
						
							|  |  |  |           [:switch, "--adopt", { | 
					
						
							|  |  |  |             description: "Adopt existing artifacts in the destination that are identical to those being installed. " \ | 
					
						
							|  |  |  |                          "Cannot be combined with `--force`.", | 
					
						
							|  |  |  |           }], | 
					
						
							|  |  |  |           [:switch, "--skip-cask-deps", { | 
					
						
							|  |  |  |             description: "Skip installing cask dependencies.", | 
					
						
							|  |  |  |           }], | 
					
						
							|  |  |  |           [:switch, "--zap", { | 
					
						
							|  |  |  |             description: "For use with `brew reinstall --cask`. Remove all files associated with a cask. " \ | 
					
						
							|  |  |  |                          "*May remove files which are shared between applications.*", | 
					
						
							|  |  |  |           }], | 
					
						
							|  |  |  |         ].each do |args| | 
					
						
							|  |  |  |           options = args.pop | 
					
						
							|  |  |  |           send(*args, **options) | 
					
						
							|  |  |  |           conflicts "--formula", args.last | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  |         cask_options | 
					
						
							| 
									
										
										
										
											2019-01-26 16:44:03 +05:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-30 09:36:47 -07:00
										 |  |  |         conflicts "--ignore-dependencies", "--only-dependencies" | 
					
						
							|  |  |  |         conflicts "--build-from-source", "--build-bottle", "--force-bottle" | 
					
						
							|  |  |  |         conflicts "--adopt", "--force" | 
					
						
							| 
									
										
										
										
											2019-12-15 23:50:01 +05:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-30 09:36:47 -07:00
										 |  |  |         named_args [:formula, :cask], min: 1
 | 
					
						
							| 
									
										
										
										
											2024-03-01 03:13:56 +01:00
										 |  |  |       end | 
					
						
							| 
									
										
										
										
											2020-09-25 21:13:26 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-30 09:36:47 -07:00
										 |  |  |       sig { override.void } | 
					
						
							|  |  |  |       def run | 
					
						
							|  |  |  |         if args.env.present? | 
					
						
							|  |  |  |           # Can't use `replacement: false` because `install_args` are used by | 
					
						
							|  |  |  |           # `build.rb`. Instead, `hide_from_man_page` and don't do anything with | 
					
						
							|  |  |  |           # this argument here. | 
					
						
							|  |  |  |           # This odisabled should stick around indefinitely. | 
					
						
							|  |  |  |           odisabled "brew install --env", "`env :std` in specific formula files" | 
					
						
							|  |  |  |         end | 
					
						
							| 
									
										
										
										
											2019-04-02 08:18:30 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-30 09:36:47 -07:00
										 |  |  |         args.named.each do |name| | 
					
						
							|  |  |  |           if (tap_with_name = Tap.with_formula_name(name)) | 
					
						
							|  |  |  |             tap, = tap_with_name | 
					
						
							|  |  |  |           elsif (tap_with_token = Tap.with_cask_token(name)) | 
					
						
							|  |  |  |             tap, = tap_with_token | 
					
						
							|  |  |  |           end | 
					
						
							| 
									
										
										
										
											2019-04-02 08:18:30 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-30 09:36:47 -07:00
										 |  |  |           tap&.ensure_installed! | 
					
						
							|  |  |  |         end | 
					
						
							| 
									
										
										
										
											2021-01-20 12:13:22 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-30 09:36:47 -07:00
										 |  |  |         if args.ignore_dependencies? | 
					
						
							|  |  |  |           opoo <<~EOS | 
					
						
							|  |  |  |             #{Tty.bold}`--ignore-dependencies` is an unsupported Homebrew developer option!#{Tty.reset} | 
					
						
							|  |  |  |             Adjust your PATH to put any preferred versions of applications earlier in the | 
					
						
							|  |  |  |             PATH rather than using this unsupported option! | 
					
						
							| 
									
										
										
										
											2014-10-31 18:33:39 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-30 09:36:47 -07:00
										 |  |  |           EOS | 
					
						
							|  |  |  |         end | 
					
						
							| 
									
										
										
										
											2023-04-19 21:31:22 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-30 09:36:47 -07:00
										 |  |  |         begin | 
					
						
							|  |  |  |           formulae, casks = T.cast( | 
					
						
							|  |  |  |             args.named.to_formulae_and_casks(warn: false).partition { _1.is_a?(Formula) }, | 
					
						
							|  |  |  |             [T::Array[Formula], T::Array[Cask::Cask]], | 
					
						
							|  |  |  |           ) | 
					
						
							|  |  |  |         rescue FormulaOrCaskUnavailableError, Cask::CaskUnavailableError | 
					
						
							|  |  |  |           cask_tap = CoreCaskTap.instance | 
					
						
							|  |  |  |           if !cask_tap.installed? && (args.cask? || Tap.untapped_official_taps.exclude?(cask_tap.name)) | 
					
						
							|  |  |  |             cask_tap.ensure_installed! | 
					
						
							|  |  |  |             retry if cask_tap.installed? | 
					
						
							|  |  |  |           end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           raise | 
					
						
							| 
									
										
										
										
											2023-04-19 21:31:22 +09:00
										 |  |  |         end | 
					
						
							| 
									
										
										
										
											2024-03-30 09:36:47 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if casks.any? | 
					
						
							| 
									
										
										
										
											2025-05-07 12:07:29 -04:00
										 |  |  |           Install.ask_casks casks if args.ask? | 
					
						
							| 
									
										
										
										
											2024-03-30 09:36:47 -07:00
										 |  |  |           if args.dry_run? | 
					
						
							|  |  |  |             if (casks_to_install = casks.reject(&:installed?).presence) | 
					
						
							|  |  |  |               ohai "Would install #{::Utils.pluralize("cask", casks_to_install.count, include_count: true)}:" | 
					
						
							|  |  |  |               puts casks_to_install.map(&:full_name).join(" ") | 
					
						
							|  |  |  |             end | 
					
						
							|  |  |  |             casks.each do |cask| | 
					
						
							|  |  |  |               dep_names = CaskDependent.new(cask) | 
					
						
							|  |  |  |                                        .runtime_dependencies | 
					
						
							|  |  |  |                                        .reject(&:installed?) | 
					
						
							|  |  |  |                                        .map(&:to_formula) | 
					
						
							|  |  |  |                                        .map(&:name) | 
					
						
							|  |  |  |               next if dep_names.blank? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |               ohai "Would install #{::Utils.pluralize("dependenc", dep_names.count, plural: "ies", singular: "y", | 
					
						
							| 
									
										
										
										
											2023-04-19 21:31:22 +09:00
										 |  |  |                                                   include_count: true)} for #{cask.full_name}:" | 
					
						
							| 
									
										
										
										
											2024-03-30 09:36:47 -07:00
										 |  |  |               puts dep_names.join(" ") | 
					
						
							|  |  |  |             end | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  |           end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           require "cask/installer" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           installed_casks, new_casks = casks.partition(&:installed?) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-29 14:49:08 +01:00
										 |  |  |           download_queue = Homebrew::DownloadQueue.new(pour: true) if Homebrew::EnvConfig.download_concurrency > 1
 | 
					
						
							|  |  |  |           fetch_casks = Homebrew::EnvConfig.no_install_upgrade? ? new_casks : casks | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           if download_queue | 
					
						
							| 
									
										
										
										
											2025-08-05 14:38:24 +01:00
										 |  |  |             fetch_cask_installers = fetch_casks.map do |cask| | 
					
						
							| 
									
										
										
										
											2025-07-29 14:49:08 +01:00
										 |  |  |               Cask::Installer.new(cask, binaries: args.binaries?, verbose: args.verbose?, | 
					
						
							|  |  |  |                                                    force: args.force?, skip_cask_deps: args.skip_cask_deps?, | 
					
						
							|  |  |  |                                                    require_sha: args.require_sha?, reinstall: true, | 
					
						
							|  |  |  |                                                    quarantine: args.quarantine?, zap: args.zap?, download_queue:) | 
					
						
							|  |  |  |             end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-05 14:38:24 +01:00
										 |  |  |             # Run prelude checks for all casks before enqueueing downloads | 
					
						
							|  |  |  |             fetch_cask_installers.each(&:prelude) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             fetch_casks_sentence = fetch_casks.map { |cask| Formatter.identifier(cask.full_name) }.to_sentence | 
					
						
							|  |  |  |             oh1 "Fetching downloads for: #{fetch_casks_sentence}", truncate: false | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             fetch_cask_installers.each(&:enqueue_downloads) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-29 14:49:08 +01:00
										 |  |  |             download_queue.fetch | 
					
						
							|  |  |  |           end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-30 09:36:47 -07:00
										 |  |  |           new_casks.each do |cask| | 
					
						
							|  |  |  |             Cask::Installer.new( | 
					
						
							|  |  |  |               cask, | 
					
						
							| 
									
										
										
										
											2025-03-06 14:10:37 -05:00
										 |  |  |               adopt:          args.adopt?, | 
					
						
							| 
									
										
										
										
											2024-03-30 09:36:47 -07:00
										 |  |  |               binaries:       args.binaries?, | 
					
						
							|  |  |  |               force:          args.force?, | 
					
						
							|  |  |  |               quarantine:     args.quarantine?, | 
					
						
							|  |  |  |               quiet:          args.quiet?, | 
					
						
							| 
									
										
										
										
											2025-03-06 14:10:37 -05:00
										 |  |  |               require_sha:    args.require_sha?, | 
					
						
							|  |  |  |               skip_cask_deps: args.skip_cask_deps?, | 
					
						
							|  |  |  |               verbose:        args.verbose?, | 
					
						
							| 
									
										
										
										
											2024-03-30 09:36:47 -07:00
										 |  |  |             ).install | 
					
						
							|  |  |  |           end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           if !Homebrew::EnvConfig.no_install_upgrade? && installed_casks.any? | 
					
						
							|  |  |  |             require "cask/upgrade" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-14 14:48:08 +01:00
										 |  |  |             Cask::Upgrade.upgrade_casks!( | 
					
						
							| 
									
										
										
										
											2024-03-30 09:36:47 -07:00
										 |  |  |               *installed_casks, | 
					
						
							|  |  |  |               force:          args.force?, | 
					
						
							|  |  |  |               dry_run:        args.dry_run?, | 
					
						
							|  |  |  |               binaries:       args.binaries?, | 
					
						
							|  |  |  |               quarantine:     args.quarantine?, | 
					
						
							|  |  |  |               require_sha:    args.require_sha?, | 
					
						
							|  |  |  |               skip_cask_deps: args.skip_cask_deps?, | 
					
						
							|  |  |  |               verbose:        args.verbose?, | 
					
						
							| 
									
										
										
										
											2024-07-15 11:50:37 -05:00
										 |  |  |               quiet:          args.quiet?, | 
					
						
							| 
									
										
										
										
											2024-03-30 09:36:47 -07:00
										 |  |  |               args:, | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |           end | 
					
						
							| 
									
										
										
										
											2023-04-19 21:31:22 +09:00
										 |  |  |         end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-18 21:32:50 -07:00
										 |  |  |         formulae = Homebrew::Attestation.sort_formulae_for_install(formulae) if Homebrew::Attestation.enabled? | 
					
						
							| 
									
										
										
										
											2024-07-15 13:30:47 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-30 09:36:47 -07:00
										 |  |  |         # if the user's flags will prevent bottle only-installations when no | 
					
						
							|  |  |  |         # developer tools are available, we need to stop them early on | 
					
						
							|  |  |  |         build_flags = [] | 
					
						
							|  |  |  |         unless DevelopmentTools.installed? | 
					
						
							|  |  |  |           build_flags << "--HEAD" if args.HEAD? | 
					
						
							|  |  |  |           build_flags << "--build-bottle" if args.build_bottle? | 
					
						
							|  |  |  |           build_flags << "--build-from-source" if args.build_from_source? | 
					
						
							| 
									
										
										
										
											2023-07-23 18:21:15 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-30 09:36:47 -07:00
										 |  |  |           raise BuildFlagsError.new(build_flags, bottled: formulae.all?(&:bottled?)) if build_flags.present? | 
					
						
							|  |  |  |         end | 
					
						
							| 
									
										
										
										
											2014-11-28 15:02:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-30 09:36:47 -07:00
										 |  |  |         if build_flags.present? && !Homebrew::EnvConfig.developer? | 
					
						
							|  |  |  |           opoo "building from source is not supported!" | 
					
						
							|  |  |  |           puts "You're on your own. Failures are expected so don't create any issues, please!" | 
					
						
							|  |  |  |         end | 
					
						
							| 
									
										
										
										
											2021-03-22 16:11:27 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-30 09:36:47 -07:00
										 |  |  |         installed_formulae = formulae.select do |f| | 
					
						
							|  |  |  |           Install.install_formula?( | 
					
						
							|  |  |  |             f, | 
					
						
							|  |  |  |             head:              args.HEAD?, | 
					
						
							|  |  |  |             fetch_head:        args.fetch_HEAD?, | 
					
						
							|  |  |  |             only_dependencies: args.only_dependencies?, | 
					
						
							|  |  |  |             force:             args.force?, | 
					
						
							|  |  |  |             quiet:             args.quiet?, | 
					
						
							| 
									
										
										
										
											2025-01-23 14:42:03 +00:00
										 |  |  |             skip_link:         args.skip_link?, | 
					
						
							| 
									
										
										
										
											2024-10-08 11:19:58 -07:00
										 |  |  |             overwrite:         args.overwrite?, | 
					
						
							| 
									
										
										
										
											2024-03-30 09:36:47 -07:00
										 |  |  |           ) | 
					
						
							|  |  |  |         end | 
					
						
							| 
									
										
										
										
											2014-06-16 13:38:14 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-09 00:22:16 -04:00
										 |  |  |         return if formulae.any? && installed_formulae.empty? | 
					
						
							| 
									
										
										
										
											2024-03-30 09:36:47 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-10-11 16:49:01 +01:00
										 |  |  |         Install.perform_preinstall_checks_once | 
					
						
							|  |  |  |         Install.check_cc_argv(args.cc) | 
					
						
							| 
									
										
										
										
											2024-03-30 09:36:47 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-06-20 12:32:46 -04:00
										 |  |  |         formulae_installer = Install.formula_installers( | 
					
						
							| 
									
										
										
										
											2024-03-30 09:36:47 -07:00
										 |  |  |           installed_formulae, | 
					
						
							| 
									
										
										
										
											2025-03-21 15:49:22 +00:00
										 |  |  |           installed_on_request:       !args.as_dependency?, | 
					
						
							|  |  |  |           installed_as_dependency:    args.as_dependency?, | 
					
						
							| 
									
										
										
										
											2024-03-30 09:36:47 -07:00
										 |  |  |           build_bottle:               args.build_bottle?, | 
					
						
							|  |  |  |           force_bottle:               args.force_bottle?, | 
					
						
							|  |  |  |           bottle_arch:                args.bottle_arch, | 
					
						
							|  |  |  |           ignore_deps:                args.ignore_dependencies?, | 
					
						
							|  |  |  |           only_deps:                  args.only_dependencies?, | 
					
						
							|  |  |  |           include_test_formulae:      args.include_test_formulae, | 
					
						
							|  |  |  |           build_from_source_formulae: args.build_from_source_formulae, | 
					
						
							|  |  |  |           cc:                         args.cc, | 
					
						
							|  |  |  |           git:                        args.git?, | 
					
						
							|  |  |  |           interactive:                args.interactive?, | 
					
						
							|  |  |  |           keep_tmp:                   args.keep_tmp?, | 
					
						
							|  |  |  |           debug_symbols:              args.debug_symbols?, | 
					
						
							|  |  |  |           force:                      args.force?, | 
					
						
							|  |  |  |           overwrite:                  args.overwrite?, | 
					
						
							|  |  |  |           debug:                      args.debug?, | 
					
						
							|  |  |  |           quiet:                      args.quiet?, | 
					
						
							|  |  |  |           verbose:                    args.verbose?, | 
					
						
							|  |  |  |           dry_run:                    args.dry_run?, | 
					
						
							|  |  |  |           skip_post_install:          args.skip_post_install?, | 
					
						
							| 
									
										
										
										
											2025-01-23 14:42:03 +00:00
										 |  |  |           skip_link:                  args.skip_link?, | 
					
						
							| 
									
										
										
										
											2024-03-30 09:36:47 -07:00
										 |  |  |         ) | 
					
						
							| 
									
										
										
										
											2023-02-17 14:33:53 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-06-17 21:12:47 -04:00
										 |  |  |         dependants = Upgrade.dependants( | 
					
						
							|  |  |  |           installed_formulae, | 
					
						
							|  |  |  |           flags:                      args.flags_only, | 
					
						
							|  |  |  |           ask:                        args.ask?, | 
					
						
							|  |  |  |           installed_on_request:       !args.as_dependency?, | 
					
						
							|  |  |  |           force_bottle:               args.force_bottle?, | 
					
						
							|  |  |  |           build_from_source_formulae: args.build_from_source_formulae, | 
					
						
							|  |  |  |           interactive:                args.interactive?, | 
					
						
							|  |  |  |           keep_tmp:                   args.keep_tmp?, | 
					
						
							|  |  |  |           debug_symbols:              args.debug_symbols?, | 
					
						
							|  |  |  |           force:                      args.force?, | 
					
						
							|  |  |  |           debug:                      args.debug?, | 
					
						
							|  |  |  |           quiet:                      args.quiet?, | 
					
						
							|  |  |  |           verbose:                    args.verbose?, | 
					
						
							|  |  |  |           dry_run:                    args.dry_run?, | 
					
						
							|  |  |  |         ) | 
					
						
							| 
									
										
										
										
											2025-06-08 12:34:24 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-06-18 16:05:19 -04:00
										 |  |  |         # Main block: if asking the user is enabled, show dependency and size information. | 
					
						
							|  |  |  |         Install.ask_formulae(formulae_installer, dependants, args: args) if args.ask? | 
					
						
							| 
									
										
										
										
											2025-06-08 12:34:24 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-06-09 00:14:16 -04:00
										 |  |  |         Install.install_formulae(formulae_installer, | 
					
						
							| 
									
										
										
										
											2025-06-08 12:34:24 -04:00
										 |  |  |                                  dry_run: args.dry_run?, | 
					
						
							|  |  |  |                                  verbose: args.verbose?) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-06-18 16:05:19 -04:00
										 |  |  |         Upgrade.upgrade_dependents( | 
					
						
							|  |  |  |           dependants, installed_formulae, | 
					
						
							|  |  |  |           flags:                      args.flags_only, | 
					
						
							|  |  |  |           dry_run:                    args.dry_run?, | 
					
						
							|  |  |  |           force_bottle:               args.force_bottle?, | 
					
						
							|  |  |  |           build_from_source_formulae: args.build_from_source_formulae, | 
					
						
							|  |  |  |           interactive:                args.interactive?, | 
					
						
							|  |  |  |           keep_tmp:                   args.keep_tmp?, | 
					
						
							|  |  |  |           debug_symbols:              args.debug_symbols?, | 
					
						
							|  |  |  |           force:                      args.force?, | 
					
						
							|  |  |  |           debug:                      args.debug?, | 
					
						
							|  |  |  |           quiet:                      args.quiet?, | 
					
						
							|  |  |  |           verbose:                    args.verbose? | 
					
						
							|  |  |  |         ) | 
					
						
							| 
									
										
										
										
											2014-06-16 13:38:14 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-30 09:36:47 -07:00
										 |  |  |         Cleanup.periodic_clean!(dry_run: args.dry_run?) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Homebrew.messages.display_messages(display_times: args.display_times?) | 
					
						
							|  |  |  |       rescue FormulaUnreadableError, FormulaClassUnavailableError, | 
					
						
							|  |  |  |              TapFormulaUnreadableError, TapFormulaClassUnavailableError => e | 
					
						
							| 
									
										
										
										
											2024-07-14 14:37:30 -04:00
										 |  |  |         require "utils/backtrace" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-30 09:36:47 -07:00
										 |  |  |         # Need to rescue before `FormulaUnavailableError` (superclass of this) | 
					
						
							|  |  |  |         # is handled, as searching for a formula doesn't make sense here (the | 
					
						
							|  |  |  |         # formula was found, but there's a problem with its implementation). | 
					
						
							|  |  |  |         $stderr.puts Utils::Backtrace.clean(e) if Homebrew::EnvConfig.developer? | 
					
						
							|  |  |  |         ofail e.message | 
					
						
							|  |  |  |       rescue FormulaOrCaskUnavailableError, Cask::CaskUnavailableError => e | 
					
						
							|  |  |  |         Homebrew.failed = true | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # formula name or cask token | 
					
						
							|  |  |  |         name = case e | 
					
						
							|  |  |  |         when FormulaOrCaskUnavailableError then e.name | 
					
						
							|  |  |  |         when Cask::CaskUnavailableError then e.token | 
					
						
							|  |  |  |         else T.absurd(e) | 
					
						
							|  |  |  |         end | 
					
						
							| 
									
										
										
										
											2022-12-10 12:59:06 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-30 09:36:47 -07:00
										 |  |  |         if name == "updog" | 
					
						
							|  |  |  |           ofail "What's updog?" | 
					
						
							|  |  |  |           return | 
					
						
							|  |  |  |         end | 
					
						
							| 
									
										
										
										
											2016-12-25 18:54:08 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-30 09:36:47 -07:00
										 |  |  |         opoo e | 
					
						
							| 
									
										
										
										
											2022-12-12 19:51:18 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-30 09:36:47 -07:00
										 |  |  |         reason = MissingFormula.reason(name, silent: true) | 
					
						
							|  |  |  |         if !args.cask? && reason | 
					
						
							|  |  |  |           $stderr.puts reason | 
					
						
							|  |  |  |           return | 
					
						
							|  |  |  |         end | 
					
						
							| 
									
										
										
										
											2022-12-12 19:51:18 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-30 09:36:47 -07:00
										 |  |  |         # We don't seem to get good search results when the tap is specified | 
					
						
							|  |  |  |         # so we might as well return early. | 
					
						
							|  |  |  |         return if name.include?("/") | 
					
						
							| 
									
										
										
										
											2022-12-12 19:51:18 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-30 09:36:47 -07:00
										 |  |  |         require "search" | 
					
						
							| 
									
										
										
										
											2022-12-31 15:52:05 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-30 09:36:47 -07:00
										 |  |  |         package_types = [] | 
					
						
							|  |  |  |         package_types << "formulae" unless args.cask? | 
					
						
							|  |  |  |         package_types << "casks" unless args.formula? | 
					
						
							| 
									
										
										
										
											2022-12-31 15:52:05 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-30 09:36:47 -07:00
										 |  |  |         ohai "Searching for similarly named #{package_types.join(" and ")}..." | 
					
						
							| 
									
										
										
										
											2017-03-22 21:55:29 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-30 09:36:47 -07:00
										 |  |  |         # Don't treat formula/cask name as a regex | 
					
						
							|  |  |  |         string_or_regex = name | 
					
						
							|  |  |  |         all_formulae, all_casks = Search.search_names(string_or_regex, args) | 
					
						
							| 
									
										
										
										
											2022-12-12 19:51:18 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-30 09:36:47 -07:00
										 |  |  |         if all_formulae.any? | 
					
						
							|  |  |  |           ohai "Formulae", Formatter.columns(all_formulae) | 
					
						
							|  |  |  |           first_formula = all_formulae.first.to_s | 
					
						
							|  |  |  |           puts <<~EOS | 
					
						
							| 
									
										
										
										
											2022-12-12 19:51:18 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-30 09:36:47 -07:00
										 |  |  |             To install #{first_formula}, run: | 
					
						
							|  |  |  |               brew install #{first_formula} | 
					
						
							|  |  |  |           EOS | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  |         puts if all_formulae.any? && all_casks.any? | 
					
						
							|  |  |  |         if all_casks.any? | 
					
						
							|  |  |  |           ohai "Casks", Formatter.columns(all_casks) | 
					
						
							|  |  |  |           first_cask = all_casks.first.to_s | 
					
						
							|  |  |  |           puts <<~EOS | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             To install #{first_cask}, run: | 
					
						
							|  |  |  |               brew install --cask #{first_cask} | 
					
						
							|  |  |  |           EOS | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  |         return if all_formulae.any? || all_casks.any? | 
					
						
							| 
									
										
										
										
											2022-12-12 19:51:18 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-30 09:36:47 -07:00
										 |  |  |         odie "No #{package_types.join(" or ")} found for #{name}." | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2010-09-11 20:22:54 +01:00
										 |  |  |   end | 
					
						
							|  |  |  | end |