From f54b458cdaec5091cf7abfa3e09e9050a94a4a26 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Fri, 25 Sep 2020 21:13:26 +0200 Subject: [PATCH 1/4] Allow installing casks with `brew install`. --- Library/Homebrew/cask/cmd/abstract_command.rb | 1 + Library/Homebrew/cask/cmd/install.rb | 29 ++- Library/Homebrew/cask/cmd/reinstall.rb | 6 +- Library/Homebrew/cli/named_args.rb | 69 ++++-- Library/Homebrew/cmd/install.rb | 227 ++++++++++++------ Library/Homebrew/exceptions.rb | 16 +- docs/Manpage.md | 20 +- manpages/brew.1 | 40 ++- 8 files changed, 288 insertions(+), 120 deletions(-) diff --git a/Library/Homebrew/cask/cmd/abstract_command.rb b/Library/Homebrew/cask/cmd/abstract_command.rb index c19cb18726..8247ee5323 100644 --- a/Library/Homebrew/cask/cmd/abstract_command.rb +++ b/Library/Homebrew/cask/cmd/abstract_command.rb @@ -1,5 +1,6 @@ # frozen_string_literal: true +require "cask/config" require "search" module Cask diff --git a/Library/Homebrew/cask/cmd/install.rb b/Library/Homebrew/cask/cmd/install.rb index 93d03d1fb2..b2f1be6a96 100644 --- a/Library/Homebrew/cask/cmd/install.rb +++ b/Library/Homebrew/cask/cmd/install.rb @@ -26,20 +26,41 @@ module Cask end def run - require "cask/installer" - - options = { + self.class.install_casks( + *casks, binaries: args.binaries?, verbose: args.verbose?, force: args.force?, skip_cask_deps: args.skip_cask_deps?, require_sha: args.require_sha?, quarantine: args.quarantine?, + ) + end + + def self.install_casks( + *casks, + verbose: nil, + force: nil, + binaries: nil, + skip_cask_deps: nil, + require_sha: nil, + quarantine: nil + ) + odie "Installing casks is supported only on macOS" unless OS.mac? + + options = { + verbose: verbose, + force: force, + binaries: binaries, + skip_cask_deps: skip_cask_deps, + require_sha: require_sha, + quarantine: quarantine, }.compact options[:quarantine] = true if options[:quarantine].nil? - odie "Installing casks is supported only on macOS" unless OS.mac? + require "cask/installer" + casks.each do |cask| Installer.new(cask, **options).install rescue CaskAlreadyInstalledError => e diff --git a/Library/Homebrew/cask/cmd/reinstall.rb b/Library/Homebrew/cask/cmd/reinstall.rb index 6303a10353..c1e066bb1a 100644 --- a/Library/Homebrew/cask/cmd/reinstall.rb +++ b/Library/Homebrew/cask/cmd/reinstall.rb @@ -24,9 +24,9 @@ module Cask def self.reinstall_casks( *casks, - verbose: false, - force: false, - skip_cask_deps: false, + verbose: nil, + force: nil, + skip_cask_deps: nil, binaries: nil, require_sha: nil, quarantine: nil diff --git a/Library/Homebrew/cli/named_args.rb b/Library/Homebrew/cli/named_args.rb index fa63db0dfe..d40719838c 100644 --- a/Library/Homebrew/cli/named_args.rb +++ b/Library/Homebrew/cli/named_args.rb @@ -21,34 +21,47 @@ module Homebrew end def to_formulae - @to_formulae ||= (downcased_unique_named - homebrew_tap_cask_names).map do |name| - Formulary.factory(name, spec, force_bottle: @force_bottle, flags: @flags) - end.uniq(&:name).freeze + @to_formulae ||= to_formulae_and_casks.select { |o| o.is_a?(Formula) }.freeze end - def to_formulae_and_casks - @to_formulae_and_casks ||= begin - formulae_and_casks = [] - - downcased_unique_named.each do |name| - formulae_and_casks << Formulary.factory(name, spec) - - warn_if_cask_conflicts(name, "formula") - rescue FormulaUnavailableError - begin - formulae_and_casks << Cask::CaskLoader.load(name) - rescue Cask::CaskUnavailableError - raise "No available formula or cask with the name \"#{name}\"" - end - end - - formulae_and_casks.freeze + def to_formulae_and_casks(only: nil) + @to_formulae_and_casks ||= {} + @to_formulae_and_casks[only] ||= begin + to_objects(only: only).reject { |o| o.is_a?(Tap) }.freeze end end + def load_formula_or_cask(name, only: nil) + if only != :cask + begin + formula = Formulary.factory(name, spec, force_bottle: @force_bottle, flags: @flags) + warn_if_cask_conflicts(name, "formula") unless only == :formula + return formula + rescue FormulaUnavailableError => e + raise e if only == :formula + end + end + + if only != :formula + begin + return Cask::CaskLoader.load(name) + rescue Cask::CaskUnavailableError + raise e if only == :cask + end + end + + raise FormulaOrCaskUnavailableError, name + end + private :load_formula_or_cask + + def resolve_formula(name) + Formulary.resolve(name, spec: spec(nil), force_bottle: @force_bottle, flags: @flags) + end + private :resolve_formula + def to_resolved_formulae @to_resolved_formulae ||= (downcased_unique_named - homebrew_tap_cask_names).map do |name| - Formulary.resolve(name, spec: spec(nil), force_bottle: @force_bottle, flags: @flags) + resolve_formula(name) end.uniq(&:name).freeze end @@ -58,7 +71,7 @@ module Homebrew casks = [] downcased_unique_named.each do |name| - resolved_formulae << Formulary.resolve(name, spec: spec(nil), force_bottle: @force_bottle, flags: @flags) + resolved_formulae << resolve_formula(name) warn_if_cask_conflicts(name, "formula") rescue FormulaUnavailableError @@ -73,6 +86,18 @@ module Homebrew end end + # Convert named arguments to `Tap`, `Formula` or `Cask` objects. + # If both a formula and cask exist with the same name, returns the + # formula and prints a warning unless `only` is specified. + def to_objects(only: nil) + @to_objects ||= {} + @to_objects[only] ||= downcased_unique_named.flat_map do |name| + next Tap.fetch(name) if only == :tap || (only.nil? && name.count("/") == 1 && !name.start_with?("./", "/")) + + load_formula_or_cask(name, only: only) + end.uniq.freeze + end + def to_formulae_paths to_paths(only: :formulae) end diff --git a/Library/Homebrew/cmd/install.rb b/Library/Homebrew/cmd/install.rb index f9464abbcc..9ae1ba145f 100644 --- a/Library/Homebrew/cmd/install.rb +++ b/Library/Homebrew/cmd/install.rb @@ -1,5 +1,6 @@ # frozen_string_literal: true +require "cask/config" require "missing_formula" require "formula_installer" require "development_tools" @@ -15,6 +16,111 @@ module Homebrew module_function def install_args + cask_only_options = { + ["--cask", "--casks"] => { + description: "Treat all named arguments as casks.", + }, + ["--[no-]binaries"] => { + description: "Disable/enable linking of helper executables to `#{Cask::Config.global.binarydir}`. " \ + "Default: enabled", + env: :cask_opts_binaries, + }, + ["--require-sha"] => { + description: "Require all casks to have a checksum.", + env: :cask_opts_require_sha, + }, + ["--[no-]quarantine"] => { + description: "Disable/enable quarantining of downloads. Default: enabled", + env: :cask_opts_quarantine, + }, + ["--skip-cask-deps"] => { + description: "Skip installing cask dependencies.", + }, + }.freeze + + formula_only_options = { + ["--formula", "--formulae"] => { + description: "Treat all named arguments as formulae.", + }, + ["--env="] => { + description: "If `std` is passed, use the standard build environment instead of superenv. "\ + "If `super` is passed, use superenv even if the formula specifies the "\ + "standard build environment.", + }, + ["--ignore-dependencies"] => { + description: "An unsupported Homebrew development flag 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 flag.", + + }, + ["--only-dependencies"] => { + description: "Install the dependencies with specified options but do not install the "\ + "formula itself.", + + }, + ["--cc="] => { + description: "Attempt to compile using the specified , which should be the "\ + "name of the compiler's executable, e.g. `gcc-7` for GCC 7. "\ + "In order to use LLVM's clang, specify `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.", + + }, + ["-s", "--build-from-source"] => { + description: "Compile from source even if a bottle is provided. "\ + "Dependencies will still be installed from bottles if they are available.", + + }, + ["--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.", + + }, + ["--include-test"] => { + description: "Install testing dependencies required to run `brew test` .", + + }, + ["--HEAD"] => { + description: "If defines it, install the HEAD version, aka. master, trunk, unstable.", + + }, + ["--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.", + + }, + ["--keep-tmp"] => { + description: "Retain the temporary files created during installation.", + + }, + ["--build-bottle"] => { + description: "Prepare the formula for eventual bottling during installation, skipping any "\ + "post-install steps.", + + }, + ["--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.", + + }, + ["--display-times"] => { + env: :display_install_times, + description: "Print install times for each formula at the end of the run.", + }, + ["-i", "--interactive"] => { + description: "Download and patch , 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.", + }, + ["-g", "--git"] => { + description: "Create a Git repository, useful for creating patches to the software.", + }, + }.freeze + Homebrew::CLI::Parser.new do usage_banner <<~EOS `install` [] @@ -27,65 +133,30 @@ module Homebrew switch "-d", "--debug", description: "If brewing fails, open an interactive debugging session with access to IRB "\ "or a shell inside the temporary build directory." - flag "--env=", - description: "If `std` is passed, use the standard build environment instead of superenv. "\ - "If `super` is passed, use superenv even if the formula specifies the "\ - "standard build environment." - switch "--ignore-dependencies", - description: "An unsupported Homebrew development flag 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 flag." - 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 , which should be the "\ - "name of the compiler's executable, e.g. `gcc-7` for GCC 7. "\ - "In order to use LLVM's clang, specify `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 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` ." - switch "--HEAD", - description: "If defines it, install the HEAD version, aka. master, trunk, unstable." - 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 "--build-bottle", - description: "Prepare the formula for eventual bottling during installation, skipping any "\ - "post-install steps." - 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 "-f", "--force", description: "Install without checking for previously installed keg-only or "\ "non-migrated versions." switch "-v", "--verbose", description: "Print the verification and postinstall steps." - switch "--display-times", - env: :display_install_times, - description: "Print install times for each formula at the end of the run." - switch "-i", "--interactive", - description: "Download and patch , 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." + conflicts "--ignore-dependencies", "--only-dependencies" - conflicts "--devel", "--HEAD" conflicts "--build-from-source", "--build-bottle", "--force-bottle" + + formula_only_options.each do |flags, **options| + if flags.last.end_with?("=") + flag(*flags, **options) + else + switch(*flags, **options) + end + + conflicts "--cask", flags.last + end + + cask_only_options.each do |flags, **options| + switch(*flags, **options) + conflicts "--formula", flags.last + end + formula_options min_named :formula end @@ -94,13 +165,15 @@ module Homebrew def install args = install_args.parse - args.named.each do |name| - next if File.exist?(name) - next if name !~ HOMEBREW_TAP_FORMULA_REGEX && name !~ HOMEBREW_CASK_TAP_CASK_REGEX + only = :formula if args.formula? + only = :cask if args.cask? - tap = Tap.fetch(Regexp.last_match(1), Regexp.last_match(2)) - tap.install unless tap.installed? - end + objects = args.named.to_objects(only: only) + + taps, formulae_or_casks = objects.partition { |o| o.is_a?(Tap) } + taps = (taps + formulae_or_casks.map(&:tap).compact).uniq.sort_by(&:name) + + taps.reject(&:installed?).each(&:install) if args.ignore_dependencies? opoo <<~EOS @@ -111,25 +184,29 @@ module Homebrew EOS end - formulae = [] + formulae, casks = formulae_or_casks.partition { |formula_or_cask| formula_or_cask.is_a?(Formula) } - unless args.named.homebrew_tap_cask_names.empty? - cask_args = [] - cask_args << "--force" if args.force? - cask_args << "--debug" if args.debug? - cask_args << "--verbose" if args.verbose? + if casks.any? + require "cask/cmd/install" - args.named.homebrew_tap_cask_names.each do |c| - ohai "brew cask install #{c} #{cask_args.join " "}" - system("#{HOMEBREW_PREFIX}/bin/brew", "cask", "install", c, *cask_args) - end + Cask::Cmd::Install.install_casks( + *casks, + binaries: args.binaries?, + verbose: args.verbose?, + force: args.force?, + skip_cask_deps: args.skip_cask_deps?, + require_sha: args.require_sha?, + quarantine: args.quarantine?, + ) end # if the user's flags will prevent bottle only-installations when no # developer tools are available, we need to stop them early on FormulaInstaller.prevent_build_flags(args) - args.named.to_formulae.each do |f| + installed_formulae = [] + + formulae.each do |f| # head-only without --HEAD is an error if !args.HEAD? && f.stable.nil? raise <<~EOS @@ -160,7 +237,7 @@ module Homebrew To upgrade to #{f.version}, run `brew upgrade #{f.full_name}` EOS elsif args.only_dependencies? - formulae << f + installed_formulae << f else opoo <<~EOS #{f.full_name} #{f.pkg_version} is already installed and up-to-date @@ -193,7 +270,7 @@ module Homebrew EOS elsif args.only_dependencies? msg = nil - formulae << f + installed_formulae << f else msg = <<~EOS #{msg} and up-to-date @@ -221,7 +298,7 @@ module Homebrew else # If none of the above is true and the formula is linked, then # FormulaInstaller will handle this case. - formulae << f + installed_formulae << f end # Even if we don't install this formula mark it as no longer just @@ -236,11 +313,11 @@ module Homebrew end end - return if formulae.empty? + return if installed_formulae.empty? Install.perform_preinstall_checks(cc: args.cc) - formulae.each do |f| + installed_formulae.each do |f| Migrator.migrate_if_needed(f, force: args.force?) install_formula(f, args: args) Cleanup.install_formula_clean!(f) @@ -256,7 +333,7 @@ module Homebrew # formula was found, but there's a problem with its implementation). $stderr.puts e.backtrace if Homebrew::EnvConfig.developer? ofail e.message - rescue FormulaUnavailableError => e + rescue FormulaOrCaskUnavailableError => e if e.name == "updog" ofail "What's updog?" return diff --git a/Library/Homebrew/exceptions.rb b/Library/Homebrew/exceptions.rb index 137f593c71..a18499f691 100644 --- a/Library/Homebrew/exceptions.rb +++ b/Library/Homebrew/exceptions.rb @@ -68,17 +68,25 @@ class MethodDeprecatedError < StandardError attr_accessor :issues_url end -# Raised when a formula is not available. -class FormulaUnavailableError < RuntimeError +# Raised when neither a formula nor a cask with the given name is available. +class FormulaOrCaskUnavailableError < RuntimeError attr_reader :name - attr_accessor :dependent def initialize(name) - super + super() @name = name end + def to_s + "No available formula or cask with the name \"#{name}\"." + end +end + +# Raised when a formula is not available. +class FormulaUnavailableError < FormulaOrCaskUnavailableError + attr_accessor :dependent + def dependent_s "(dependency of #{dependent})" if dependent && dependent != name end diff --git a/docs/Manpage.md b/docs/Manpage.md index 143cf6ca4a..c768b2ddfc 100644 --- a/docs/Manpage.md +++ b/docs/Manpage.md @@ -313,6 +313,12 @@ installed formulae or, every 30 days, for all formulae. * `-d`, `--debug`: If brewing fails, open an interactive debugging session with access to IRB or a shell inside the temporary build directory. +* `-f`, `--force`: + Install without checking for previously installed keg-only or non-migrated versions. +* `-v`, `--verbose`: + Print the verification and postinstall steps. +* `--formula`: + Treat all named arguments as formulae. * `--env`: If `std` is passed, use the standard build environment instead of superenv. If `super` is passed, use superenv even if the formula specifies the standard build environment. * `--ignore-dependencies`: @@ -337,16 +343,22 @@ installed formulae or, every 30 days, for all formulae. Prepare the formula for eventual bottling during installation, skipping any post-install steps. * `--bottle-arch`: Optimise bottles for the specified architecture rather than the oldest architecture supported by the version of macOS the bottles are built on. -* `-f`, `--force`: - Install without checking for previously installed keg-only or non-migrated versions. -* `-v`, `--verbose`: - Print the verification and postinstall steps. * `--display-times`: Print install times for each formula at the end of the run. * `-i`, `--interactive`: 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. * `-g`, `--git`: Create a Git repository, useful for creating patches to the software. +* `--cask`: + Treat all named arguments as casks. +* `--[no-]binaries`: + Disable/enable linking of helper executables to `/usr/local/bin`. Default: enabled +* `--require-sha`: + Require all casks to have a checksum. +* `--[no-]quarantine`: + Disable/enable quarantining of downloads. Default: enabled +* `--skip-cask-deps`: + Skip installing cask dependencies. ### `leaves` diff --git a/manpages/brew.1 b/manpages/brew.1 index a392f009ee..580fa1fbb2 100644 --- a/manpages/brew.1 +++ b/manpages/brew.1 @@ -456,6 +456,18 @@ Unless \fBHOMEBREW_NO_INSTALL_CLEANUP\fR is set, \fBbrew cleanup\fR will then be If brewing fails, open an interactive debugging session with access to IRB or a shell inside the temporary build directory\. . .TP +\fB\-f\fR, \fB\-\-force\fR +Install without checking for previously installed keg\-only or non\-migrated versions\. +. +.TP +\fB\-v\fR, \fB\-\-verbose\fR +Print the verification and postinstall steps\. +. +.TP +\fB\-\-formula\fR +Treat all named arguments as formulae\. +. +.TP \fB\-\-env\fR If \fBstd\fR is passed, use the standard build environment instead of superenv\. If \fBsuper\fR is passed, use superenv even if the formula specifies the standard build environment\. . @@ -504,14 +516,6 @@ Prepare the formula for eventual bottling during installation, skipping any post Optimise bottles for the specified architecture rather than the oldest architecture supported by the version of macOS the bottles are built on\. . .TP -\fB\-f\fR, \fB\-\-force\fR -Install without checking for previously installed keg\-only or non\-migrated versions\. -. -.TP -\fB\-v\fR, \fB\-\-verbose\fR -Print the verification and postinstall steps\. -. -.TP \fB\-\-display\-times\fR Print install times for each formula at the end of the run\. . @@ -523,6 +527,26 @@ Download and patch \fIformula\fR, then open a shell\. This allows the user to ru \fB\-g\fR, \fB\-\-git\fR Create a Git repository, useful for creating patches to the software\. . +.TP +\fB\-\-cask\fR +Treat all named arguments as casks\. +. +.TP +\fB\-\-[no\-]binaries\fR +Disable/enable linking of helper executables to \fB/usr/local/bin\fR\. Default: enabled +. +.TP +\fB\-\-require\-sha\fR +Require all casks to have a checksum\. +. +.TP +\fB\-\-[no\-]quarantine\fR +Disable/enable quarantining of downloads\. Default: enabled +. +.TP +\fB\-\-skip\-cask\-deps\fR +Skip installing cask dependencies\. +. .SS "\fBleaves\fR" List installed formulae that are not dependencies of another installed formula\. . From d443afc82d1bb945836ed9d021c08bb92fd0bd25 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Sat, 26 Sep 2020 02:24:16 +0200 Subject: [PATCH 2/4] Improve `brew man` output. --- Library/Homebrew/cli/named_args.rb | 2 +- Library/Homebrew/dev-cmd/man.rb | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/Library/Homebrew/cli/named_args.rb b/Library/Homebrew/cli/named_args.rb index d40719838c..8a47787b58 100644 --- a/Library/Homebrew/cli/named_args.rb +++ b/Library/Homebrew/cli/named_args.rb @@ -21,7 +21,7 @@ module Homebrew end def to_formulae - @to_formulae ||= to_formulae_and_casks.select { |o| o.is_a?(Formula) }.freeze + @to_formulae ||= to_formulae_and_casks(only: :formula).freeze end def to_formulae_and_casks(only: nil) diff --git a/Library/Homebrew/dev-cmd/man.rb b/Library/Homebrew/dev-cmd/man.rb index 4d7f961f92..e34fe3cfcb 100644 --- a/Library/Homebrew/dev-cmd/man.rb +++ b/Library/Homebrew/dev-cmd/man.rb @@ -38,9 +38,14 @@ module Homebrew Commands.rebuild_internal_commands_completion_list regenerate_man_pages(preserve_date: args.fail_if_changed?, quiet: args.quiet?) - if system "git", "-C", HOMEBREW_REPOSITORY, "diff", "--quiet", "docs/Manpage.md", "manpages", "completions" + diff = system_command "git", args: [ + "-C", HOMEBREW_REPOSITORY, "diff", "--exit-code", "docs/Manpage.md", "manpages", "completions" + ] + if diff.status.success? puts "No changes to manpage or completions output detected." elsif args.fail_if_changed? + puts "Changes to manpage or completions detected:" + puts diff.stdout Homebrew.failed = true end end From 08be729af04de693d7f44f3a3b216c3e15172dcb Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Sun, 27 Sep 2020 22:53:01 +0200 Subject: [PATCH 3/4] Support all cask options in `brew install`. --- Library/Homebrew/cask/cmd.rb | 113 ++++++++++------- Library/Homebrew/cask/cmd/abstract_command.rb | 31 +++-- Library/Homebrew/cask/cmd/install.rb | 12 +- Library/Homebrew/cmd/install.rb | 117 +++++++----------- docs/Manpage.md | 32 ++++- manpages/brew.1 | 62 +++++++++- 6 files changed, 236 insertions(+), 131 deletions(-) diff --git a/Library/Homebrew/cask/cmd.rb b/Library/Homebrew/cask/cmd.rb index 5ef9a9f634..fde3f0cf9a 100644 --- a/Library/Homebrew/cask/cmd.rb +++ b/Library/Homebrew/cask/cmd.rb @@ -79,6 +79,70 @@ module Cask EOS end + OPTIONS = [ + [:flag, "--appdir=", { + description: "Target location for Applications. " \ + "Default: `#{Config::DEFAULT_DIRS[:appdir]}`", + }], + [:flag, "--colorpickerdir=", { + description: "Target location for Color Pickers. " \ + "Default: `#{Config::DEFAULT_DIRS[:colorpickerdir]}`", + }], + [:flag, "--prefpanedir=", { + description: "Target location for Preference Panes. " \ + "Default: `#{Config::DEFAULT_DIRS[:prefpanedir]}`", + }], + [:flag, "--qlplugindir=", { + description: "Target location for QuickLook Plugins. " \ + "Default: `#{Config::DEFAULT_DIRS[:qlplugindir]}`", + }], + [:flag, "--mdimporterdir=", { + description: "Target location for Spotlight Plugins. " \ + "Default: `#{Config::DEFAULT_DIRS[:mdimporterdir]}`", + }], + [:flag, "--dictionarydir=", { + description: "Target location for Dictionaries. " \ + "Default: `#{Config::DEFAULT_DIRS[:dictionarydir]}`", + }], + [:flag, "--fontdir=", { + description: "Target location for Fonts. " \ + "Default: `#{Config::DEFAULT_DIRS[:fontdir]}`", + }], + [:flag, "--servicedir=", { + description: "Target location for Services. " \ + "Default: `#{Config::DEFAULT_DIRS[:servicedir]}`", + }], + [:flag, "--input_methoddir=", { + description: "Target location for Input Methods. " \ + "Default: `#{Config::DEFAULT_DIRS[:input_methoddir]}`", + }], + [:flag, "--internet_plugindir=", { + description: "Target location for Internet Plugins. " \ + "Default: `#{Config::DEFAULT_DIRS[:internet_plugindir]}`", + }], + [:flag, "--audio_unit_plugindir=", { + description: "Target location for Audio Unit Plugins. " \ + "Default: `#{Config::DEFAULT_DIRS[:audio_unit_plugindir]}`", + }], + [:flag, "--vst_plugindir=", { + description: "Target location for VST Plugins. " \ + "Default: `#{Config::DEFAULT_DIRS[:vst_plugindir]}`", + }], + [:flag, "--vst3_plugindir=", { + description: "Target location for VST3 Plugins. " \ + "Default: `#{Config::DEFAULT_DIRS[:vst3_plugindir]}`", + }], + [:flag, "--screen_saverdir=", { + description: "Target location for Screen Savers. " \ + "Default: `#{Config::DEFAULT_DIRS[:screen_saverdir]}`", + }], + [:comma_array, "--language", { + description: "Set language of the Cask to install. The first matching " \ + "language is used, otherwise the default language on the Cask. " \ + "The default value is the `language of your system`", + }], + ].freeze + def self.parser(&block) Homebrew::CLI::Parser.new do if block_given? @@ -91,52 +155,9 @@ module Cask EOS end - flag "--appdir=", - description: "Target location for Applications. " \ - "Default: `#{Config::DEFAULT_DIRS[:appdir]}`" - flag "--colorpickerdir=", - description: "Target location for Color Pickers. " \ - "Default: `#{Config::DEFAULT_DIRS[:colorpickerdir]}`" - flag "--prefpanedir=", - description: "Target location for Preference Panes. " \ - "Default: `#{Config::DEFAULT_DIRS[:prefpanedir]}`" - flag "--qlplugindir=", - description: "Target location for QuickLook Plugins. " \ - "Default: `#{Config::DEFAULT_DIRS[:qlplugindir]}`" - flag "--mdimporterdir=", - description: "Target location for Spotlight Plugins. " \ - "Default: `#{Config::DEFAULT_DIRS[:mdimporterdir]}`" - flag "--dictionarydir=", - description: "Target location for Dictionaries. " \ - "Default: `#{Config::DEFAULT_DIRS[:dictionarydir]}`" - flag "--fontdir=", - description: "Target location for Fonts. " \ - "Default: `#{Config::DEFAULT_DIRS[:fontdir]}`" - flag "--servicedir=", - description: "Target location for Services. " \ - "Default: `#{Config::DEFAULT_DIRS[:servicedir]}`" - flag "--input_methoddir=", - description: "Target location for Input Methods. " \ - "Default: `#{Config::DEFAULT_DIRS[:input_methoddir]}`" - flag "--internet_plugindir=", - description: "Target location for Internet Plugins. " \ - "Default: `#{Config::DEFAULT_DIRS[:internet_plugindir]}`" - flag "--audio_unit_plugindir=", - description: "Target location for Audio Unit Plugins. " \ - "Default: `#{Config::DEFAULT_DIRS[:audio_unit_plugindir]}`" - flag "--vst_plugindir=", - description: "Target location for VST Plugins. " \ - "Default: `#{Config::DEFAULT_DIRS[:vst_plugindir]}`" - flag "--vst3_plugindir=", - description: "Target location for VST3 Plugins. " \ - "Default: `#{Config::DEFAULT_DIRS[:vst3_plugindir]}`" - flag "--screen_saverdir=", - description: "Target location for Screen Savers. " \ - "Default: `#{Config::DEFAULT_DIRS[:screen_saverdir]}`" - comma_array "--language", - description: "Set language of the Cask to install. The first matching " \ - "language is used, otherwise the default language on the Cask. " \ - "The default value is the `language of your system`" + OPTIONS.each do |option| + send(*option) + end end end diff --git a/Library/Homebrew/cask/cmd/abstract_command.rb b/Library/Homebrew/cask/cmd/abstract_command.rb index 8247ee5323..5314cd931f 100644 --- a/Library/Homebrew/cask/cmd/abstract_command.rb +++ b/Library/Homebrew/cask/cmd/abstract_command.rb @@ -33,6 +33,22 @@ module Cask "`#{command_name}` []#{banner_args}" end + OPTIONS = [ + [:switch, "--[no-]binaries", { + description: "Disable/enable linking of helper executables to `#{Config.global.binarydir}`. " \ + "Default: enabled", + env: :cask_opts_binaries, + }], + [:switch, "--require-sha", { + 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, + }], + ].freeze + def self.parser(&block) banner = <<~EOS `cask` #{banner_headline} @@ -48,18 +64,9 @@ module Cask instance_eval(&block) if block_given? - switch "--[no-]binaries", - description: "Disable/enable linking of helper executables to `#{Config.global.binarydir}`. " \ - "Default: enabled", - env: :cask_opts_binaries - - switch "--require-sha", - 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 + OPTIONS.each do |option| + send(*option) + end min_named min_n unless min_n.nil? max_named max_n unless max_n.nil? diff --git a/Library/Homebrew/cask/cmd/install.rb b/Library/Homebrew/cask/cmd/install.rb index b2f1be6a96..a532bb521e 100644 --- a/Library/Homebrew/cask/cmd/install.rb +++ b/Library/Homebrew/cask/cmd/install.rb @@ -14,12 +14,20 @@ module Cask "Installs the given ." end + OPTIONS = [ + [:switch, "--skip-cask-deps", { + description: "Skip installing cask dependencies.", + }], + ].freeze + def self.parser(&block) super do switch "--force", description: "Force overwriting existing files." - switch "--skip-cask-deps", - description: "Skip installing cask dependencies." + + OPTIONS.each do |option| + send(*option) + end instance_eval(&block) if block_given? end diff --git a/Library/Homebrew/cmd/install.rb b/Library/Homebrew/cmd/install.rb index 9ae1ba145f..33f42ec12e 100644 --- a/Library/Homebrew/cmd/install.rb +++ b/Library/Homebrew/cmd/install.rb @@ -1,6 +1,8 @@ # frozen_string_literal: true require "cask/config" +require "cask/cmd" +require "cask/cmd/install" require "missing_formula" require "formula_installer" require "development_tools" @@ -16,50 +18,37 @@ module Homebrew module_function def install_args - cask_only_options = { - ["--cask", "--casks"] => { + cask_only_options = [ + [:switch, "--cask", "--casks", { description: "Treat all named arguments as casks.", - }, - ["--[no-]binaries"] => { - description: "Disable/enable linking of helper executables to `#{Cask::Config.global.binarydir}`. " \ - "Default: enabled", - env: :cask_opts_binaries, - }, - ["--require-sha"] => { - description: "Require all casks to have a checksum.", - env: :cask_opts_require_sha, - }, - ["--[no-]quarantine"] => { - description: "Disable/enable quarantining of downloads. Default: enabled", - env: :cask_opts_quarantine, - }, - ["--skip-cask-deps"] => { - description: "Skip installing cask dependencies.", - }, - }.freeze + }], + *Cask::Cmd::OPTIONS, + *Cask::Cmd::AbstractCommand::OPTIONS, + *Cask::Cmd::Install::OPTIONS, + ] - formula_only_options = { - ["--formula", "--formulae"] => { + formula_only_options = [ + [:switch, "--formula", "--formulae", { description: "Treat all named arguments as formulae.", - }, - ["--env="] => { + }], + [:flag, "--env=", { description: "If `std` is passed, use the standard build environment instead of superenv. "\ "If `super` is passed, use superenv even if the formula specifies the "\ "standard build environment.", - }, - ["--ignore-dependencies"] => { + }], + [:switch, "--ignore-dependencies", { description: "An unsupported Homebrew development flag 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 flag.", - }, - ["--only-dependencies"] => { + }], + [:switch, "--only-dependencies", { description: "Install the dependencies with specified options but do not install the "\ "formula itself.", - }, - ["--cc="] => { + }], + [:flag, "--cc=", { description: "Attempt to compile using the specified , which should be the "\ "name of the compiler's executable, e.g. `gcc-7` for GCC 7. "\ "In order to use LLVM's clang, specify `llvm_clang`. To use the "\ @@ -67,59 +56,56 @@ module Homebrew "compilers that are provided by Homebrew or bundled with macOS. "\ "Please do not file issues if you encounter errors while using this option.", - }, - ["-s", "--build-from-source"] => { + }], + [:switch, "-s", "--build-from-source", { description: "Compile from source even if a bottle is provided. "\ "Dependencies will still be installed from bottles if they are available.", - }, - ["--force-bottle"] => { + }], + [: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.", - }, - ["--include-test"] => { + }], + [:switch, "--include-test", { description: "Install testing dependencies required to run `brew test` .", - }, - ["--HEAD"] => { + }], + [:switch, "--HEAD", { description: "If defines it, install the HEAD version, aka. master, trunk, unstable.", - }, - ["--fetch-HEAD"] => { + }], [: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.", - }, - ["--keep-tmp"] => { + }], [:switch, "--keep-tmp", { description: "Retain the temporary files created during installation.", - }, - ["--build-bottle"] => { + }], [:switch, "--build-bottle", { description: "Prepare the formula for eventual bottling during installation, skipping any "\ "post-install steps.", - }, - ["--bottle-arch="] => { + }], + [: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.", - }, - ["--display-times"] => { + }], + [:switch, "--display-times", { env: :display_install_times, description: "Print install times for each formula at the end of the run.", - }, - ["-i", "--interactive"] => { + }], + [:switch, "-i", "--interactive", { description: "Download and patch , 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.", - }, - ["-g", "--git"] => { + }], + [:switch, "-g", "--git", { description: "Create a Git repository, useful for creating patches to the software.", - }, - }.freeze + }] + ] Homebrew::CLI::Parser.new do usage_banner <<~EOS @@ -134,27 +120,22 @@ module Homebrew description: "If brewing fails, open an interactive debugging session with access to IRB "\ "or a shell inside the temporary build directory." switch "-f", "--force", - description: "Install without checking for previously installed keg-only or "\ - "non-migrated versions." + description: "Install formulae without checking for previously installed keg-only or "\ + "non-migrated versions. Overwrite existing files when installing casks." switch "-v", "--verbose", description: "Print the verification and postinstall steps." conflicts "--ignore-dependencies", "--only-dependencies" conflicts "--build-from-source", "--build-bottle", "--force-bottle" - formula_only_options.each do |flags, **options| - if flags.last.end_with?("=") - flag(*flags, **options) - else - switch(*flags, **options) - end - - conflicts "--cask", flags.last + formula_only_options.each do |options| + send(*options) + conflicts "--cask", options[-2] end - cask_only_options.each do |flags, **options| - switch(*flags, **options) - conflicts "--formula", flags.last + cask_only_options.each do |options| + send(*options) + conflicts "--formula", options[-2] end formula_options @@ -187,8 +168,6 @@ module Homebrew formulae, casks = formulae_or_casks.partition { |formula_or_cask| formula_or_cask.is_a?(Formula) } if casks.any? - require "cask/cmd/install" - Cask::Cmd::Install.install_casks( *casks, binaries: args.binaries?, diff --git a/docs/Manpage.md b/docs/Manpage.md index c768b2ddfc..153c06c49e 100644 --- a/docs/Manpage.md +++ b/docs/Manpage.md @@ -314,7 +314,7 @@ installed formulae or, every 30 days, for all formulae. * `-d`, `--debug`: If brewing fails, open an interactive debugging session with access to IRB or a shell inside the temporary build directory. * `-f`, `--force`: - Install without checking for previously installed keg-only or non-migrated versions. + Install formulae without checking for previously installed keg-only or non-migrated versions. Overwrite existing files when installing casks. * `-v`, `--verbose`: Print the verification and postinstall steps. * `--formula`: @@ -351,6 +351,36 @@ installed formulae or, every 30 days, for all formulae. Create a Git repository, useful for creating patches to the software. * `--cask`: Treat all named arguments as casks. +* `--appdir`: + Target location for Applications. Default: `/Applications` +* `--colorpickerdir`: + Target location for Color Pickers. Default: `~/Library/ColorPickers` +* `--prefpanedir`: + Target location for Preference Panes. Default: `~/Library/PreferencePanes` +* `--qlplugindir`: + Target location for QuickLook Plugins. Default: `~/Library/QuickLook` +* `--mdimporterdir`: + Target location for Spotlight Plugins. Default: `~/Library/Spotlight` +* `--dictionarydir`: + Target location for Dictionaries. Default: `~/Library/Dictionaries` +* `--fontdir`: + Target location for Fonts. Default: `~/Library/Fonts` +* `--servicedir`: + Target location for Services. Default: `~/Library/Services` +* `--input_methoddir`: + Target location for Input Methods. Default: `~/Library/Input Methods` +* `--internet_plugindir`: + Target location for Internet Plugins. Default: `~/Library/Internet Plug-Ins` +* `--audio_unit_plugindir`: + Target location for Audio Unit Plugins. Default: `~/Library/Audio/Plug-Ins/Components` +* `--vst_plugindir`: + Target location for VST Plugins. Default: `~/Library/Audio/Plug-Ins/VST` +* `--vst3_plugindir`: + Target location for VST3 Plugins. Default: `~/Library/Audio/Plug-Ins/VST3` +* `--screen_saverdir`: + Target location for Screen Savers. Default: `~/Library/Screen Savers` +* `--language`: + Set language of the Cask to install. The first matching language is used, otherwise the default language on the Cask. The default value is the `language of your system` * `--[no-]binaries`: Disable/enable linking of helper executables to `/usr/local/bin`. Default: enabled * `--require-sha`: diff --git a/manpages/brew.1 b/manpages/brew.1 index 580fa1fbb2..d043615c77 100644 --- a/manpages/brew.1 +++ b/manpages/brew.1 @@ -457,7 +457,7 @@ If brewing fails, open an interactive debugging session with access to IRB or a . .TP \fB\-f\fR, \fB\-\-force\fR -Install without checking for previously installed keg\-only or non\-migrated versions\. +Install formulae without checking for previously installed keg\-only or non\-migrated versions\. Overwrite existing files when installing casks\. . .TP \fB\-v\fR, \fB\-\-verbose\fR @@ -532,6 +532,66 @@ Create a Git repository, useful for creating patches to the software\. Treat all named arguments as casks\. . .TP +\fB\-\-appdir\fR +Target location for Applications\. Default: \fB/Applications\fR +. +.TP +\fB\-\-colorpickerdir\fR +Target location for Color Pickers\. Default: \fB~/Library/ColorPickers\fR +. +.TP +\fB\-\-prefpanedir\fR +Target location for Preference Panes\. Default: \fB~/Library/PreferencePanes\fR +. +.TP +\fB\-\-qlplugindir\fR +Target location for QuickLook Plugins\. Default: \fB~/Library/QuickLook\fR +. +.TP +\fB\-\-mdimporterdir\fR +Target location for Spotlight Plugins\. Default: \fB~/Library/Spotlight\fR +. +.TP +\fB\-\-dictionarydir\fR +Target location for Dictionaries\. Default: \fB~/Library/Dictionaries\fR +. +.TP +\fB\-\-fontdir\fR +Target location for Fonts\. Default: \fB~/Library/Fonts\fR +. +.TP +\fB\-\-servicedir\fR +Target location for Services\. Default: \fB~/Library/Services\fR +. +.TP +\fB\-\-input_methoddir\fR +Target location for Input Methods\. Default: \fB~/Library/Input Methods\fR +. +.TP +\fB\-\-internet_plugindir\fR +Target location for Internet Plugins\. Default: \fB~/Library/Internet Plug\-Ins\fR +. +.TP +\fB\-\-audio_unit_plugindir\fR +Target location for Audio Unit Plugins\. Default: \fB~/Library/Audio/Plug\-Ins/Components\fR +. +.TP +\fB\-\-vst_plugindir\fR +Target location for VST Plugins\. Default: \fB~/Library/Audio/Plug\-Ins/VST\fR +. +.TP +\fB\-\-vst3_plugindir\fR +Target location for VST3 Plugins\. Default: \fB~/Library/Audio/Plug\-Ins/VST3\fR +. +.TP +\fB\-\-screen_saverdir\fR +Target location for Screen Savers\. Default: \fB~/Library/Screen Savers\fR +. +.TP +\fB\-\-language\fR +Set language of the Cask to install\. The first matching language is used, otherwise the default language on the Cask\. The default value is the \fBlanguage of your system\fR +. +.TP \fB\-\-[no\-]binaries\fR Disable/enable linking of helper executables to \fB/usr/local/bin\fR\. Default: enabled . From 0c74d93939e67e6929a6e581506cf33892f252c6 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Sun, 27 Sep 2020 23:02:19 +0200 Subject: [PATCH 4/4] Fix man page difference on Linux. --- Library/Homebrew/cask/cmd/abstract_command.rb | 4 +--- docs/Manpage.md | 2 +- manpages/brew.1 | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/Library/Homebrew/cask/cmd/abstract_command.rb b/Library/Homebrew/cask/cmd/abstract_command.rb index 5314cd931f..2408effac1 100644 --- a/Library/Homebrew/cask/cmd/abstract_command.rb +++ b/Library/Homebrew/cask/cmd/abstract_command.rb @@ -1,6 +1,5 @@ # frozen_string_literal: true -require "cask/config" require "search" module Cask @@ -35,8 +34,7 @@ module Cask OPTIONS = [ [:switch, "--[no-]binaries", { - description: "Disable/enable linking of helper executables to `#{Config.global.binarydir}`. " \ - "Default: enabled", + description: "Disable/enable linking of helper executables. Default: enabled", env: :cask_opts_binaries, }], [:switch, "--require-sha", { diff --git a/docs/Manpage.md b/docs/Manpage.md index 153c06c49e..e4d4b2c4dd 100644 --- a/docs/Manpage.md +++ b/docs/Manpage.md @@ -382,7 +382,7 @@ installed formulae or, every 30 days, for all formulae. * `--language`: Set language of the Cask to install. The first matching language is used, otherwise the default language on the Cask. The default value is the `language of your system` * `--[no-]binaries`: - Disable/enable linking of helper executables to `/usr/local/bin`. Default: enabled + Disable/enable linking of helper executables. Default: enabled * `--require-sha`: Require all casks to have a checksum. * `--[no-]quarantine`: diff --git a/manpages/brew.1 b/manpages/brew.1 index d043615c77..f5ce653ab3 100644 --- a/manpages/brew.1 +++ b/manpages/brew.1 @@ -593,7 +593,7 @@ Set language of the Cask to install\. The first matching language is used, other . .TP \fB\-\-[no\-]binaries\fR -Disable/enable linking of helper executables to \fB/usr/local/bin\fR\. Default: enabled +Disable/enable linking of helper executables\. Default: enabled . .TP \fB\-\-require\-sha\fR