diff --git a/Library/Homebrew/.rubocop.yml b/Library/Homebrew/.rubocop.yml index 938bf21b7c..4158f9f644 100644 --- a/Library/Homebrew/.rubocop.yml +++ b/Library/Homebrew/.rubocop.yml @@ -34,6 +34,9 @@ Metrics/ModuleLength: - 'cask/lib/hbc/macos.rb' - 'cask/lib/hbc/utils.rb' +Metrics/ParameterLists: + CountKeywordArgs: false + # so many of these in formulae but none in here Style/GuardClause: Enabled: true diff --git a/Library/Homebrew/cask/lib/hbc/artifact.rb b/Library/Homebrew/cask/lib/hbc/artifact.rb index b155a125a8..e5eb54c36f 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact.rb @@ -54,12 +54,12 @@ module Hbc Zap, ].freeze - def self.for_cask(cask, command: SystemCommand, force: false) + def self.for_cask(cask, options = {}) odebug "Determining which artifacts are present in Cask #{cask}" TYPES .select { |klass| klass.me?(cask) } - .map { |klass| klass.new(cask, command: command, force: force) } + .map { |klass| klass.new(cask, options) } end end end diff --git a/Library/Homebrew/cask/lib/hbc/artifact/base.rb b/Library/Homebrew/cask/lib/hbc/artifact/base.rb index 924493fc0f..96349f0816 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact/base.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact/base.rb @@ -65,10 +65,19 @@ module Hbc {} end - def initialize(cask, command: SystemCommand, force: false) + def verbose? + @verbose + end + + def force? + @force + end + + def initialize(cask, command: SystemCommand, force: false, verbose: false) @cask = cask @command = command @force = force + @verbose = verbose end end end diff --git a/Library/Homebrew/cask/lib/hbc/artifact/moved.rb b/Library/Homebrew/cask/lib/hbc/artifact/moved.rb index eaaa49e207..3fe969c0c2 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact/moved.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact/moved.rb @@ -20,7 +20,7 @@ module Hbc def move if Utils.path_occupied?(target) message = "It seems there is already #{self.class.artifact_english_article} #{self.class.artifact_english_name} at '#{target}'" - raise CaskError, "#{message}." unless force + raise CaskError, "#{message}." unless force? opoo "#{message}; overwriting." delete end diff --git a/Library/Homebrew/cask/lib/hbc/artifact/pkg.rb b/Library/Homebrew/cask/lib/hbc/artifact/pkg.rb index c43481c82b..be0a6be717 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact/pkg.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact/pkg.rb @@ -48,7 +48,7 @@ module Hbc "-pkg", source, "-target", "/" ] - args << "-verboseR" if CLI.verbose? + args << "-verboseR" if verbose? args << "-allowUntrusted" if pkg_install_opts :allow_untrusted with_choices_file do |choices_path| args << "-applyChoiceChangesXML" << choices_path if choices_path diff --git a/Library/Homebrew/cask/lib/hbc/artifact/uninstall_base.rb b/Library/Homebrew/cask/lib/hbc/artifact/uninstall_base.rb index 478f313b5a..2ddd0cfb36 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact/uninstall_base.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact/uninstall_base.rb @@ -173,7 +173,7 @@ module Hbc unless executable_path.exist? message = "uninstall script #{executable} does not exist" - raise CaskError, "#{message}." unless force + raise CaskError, "#{message}." unless force? opoo "#{message}, skipping." return end diff --git a/Library/Homebrew/cask/lib/hbc/cli.rb b/Library/Homebrew/cask/lib/hbc/cli.rb index 3f6af2c340..1c20a2a331 100644 --- a/Library/Homebrew/cask/lib/hbc/cli.rb +++ b/Library/Homebrew/cask/lib/hbc/cli.rb @@ -2,6 +2,7 @@ require "optparse" require "shellwords" require "extend/optparse" +require "hbc/cli/options" require "hbc/cli/abstract_command" require "hbc/cli/audit" @@ -44,49 +45,36 @@ module Hbc "remove" => "uninstall", "abv" => "info", "dr" => "doctor", - # aliases from Homebrew that we don't (yet) support - # 'ln' => 'link', - # 'configure' => 'diy', - # '--repo' => '--repository', - # 'environment' => '--env', - # '-c1' => '--config', }.freeze - OPTIONS = { - "--caskroom=" => :caskroom=, - "--appdir=" => :appdir=, - "--colorpickerdir=" => :colorpickerdir=, - "--prefpanedir=" => :prefpanedir=, - "--qlplugindir=" => :qlplugindir=, - "--dictionarydir=" => :dictionarydir=, - "--fontdir=" => :fontdir=, - "--servicedir=" => :servicedir=, - "--input_methoddir=" => :input_methoddir=, - "--internet_plugindir=" => :internet_plugindir=, - "--audio_unit_plugindir=" => :audio_unit_plugindir=, - "--vst_plugindir=" => :vst_plugindir=, - "--vst3_plugindir=" => :vst3_plugindir=, - "--screen_saverdir=" => :screen_saverdir=, - }.freeze + include Options - FLAGS = { - ["--[no-]binaries", :binaries] => true, - ["--verbose", :verbose] => false, - ["--outdated", :outdated] => false, - ["--help", :help] => false, - }.freeze + option "--caskroom=PATH", ->(value) { Hbc.caskroom = value } + option "--appdir=PATH", ->(value) { Hbc.appdir = value } + option "--colorpickerdir=PATH", ->(value) { Hbc.colorpickerdir = value } + option "--prefpanedir=PATH", ->(value) { Hbc.prefpanedir = value } + option "--qlplugindir=PATH", ->(value) { Hbc.qlplugindir = value } + option "--dictionarydir=PATH", ->(value) { Hbc.dictionarydir = value } + option "--fontdir=PATH", ->(value) { Hbc.fontdir = value } + option "--servicedir=PATH", ->(value) { Hbc.servicedir = value } + option "--input_methoddir=PATH", ->(value) { Hbc.input_methoddir = value } + option "--internet_plugindir=PATH", ->(value) { Hbc.internet_plugindir = value } + option "--audio_unit_plugindir=PATH", ->(value) { Hbc.audio_unit_plugindir = value } + option "--vst_plugindir=PATH", ->(value) { Hbc.vst_plugindir = value } + option "--vst3_plugindir=PATH", ->(value) { Hbc.vst3_plugindir = value } + option "--screen_saverdir=PATH", ->(value) { Hbc.screen_saverdir = value } + option "--binarydir=PATH", ->(*) { opoo(<<-EOS.undent) } + Option --binarydir is obsolete! + Homebrew-Cask now uses the same location as your Homebrew installation for executable links. + EOS - FLAGS.each do |(_, method), default_value| - instance_variable_set(:"@#{method}", default_value) + option "--help", :help, false - define_singleton_method(:"#{method}=") do |arg| - instance_variable_set(:"@#{method}", arg) - end + # handled in OS::Mac + option "--language a,b,c", ->(*) { raise OptionParser::InvalidOption } - define_singleton_method(:"#{method}?") do - instance_variable_get(:"@#{method}") - end - end + # override default handling of --version + option "--version", ->(*) { raise OptionParser::InvalidOption } def self.command_classes @command_classes ||= constants.map(&method(:const_get)) @@ -99,10 +87,10 @@ module Hbc @commands ||= command_classes.map(&:command_name) end - def self.lookup_command(command_string) + def self.lookup_command(command_name) @lookup ||= Hash[commands.zip(command_classes)] - command_string = ALIASES.fetch(command_string, command_string) - @lookup.fetch(command_string, command_string) + command_name = ALIASES.fetch(command_name, command_name) + @lookup.fetch(command_name, command_name) end def self.should_init?(command) @@ -145,18 +133,26 @@ module Hbc end end - def self.process(arguments) + def self.run(*args) + new(*args).run + end + + def initialize(*args) + @args = process_options(*args) + end + + def run + command_name, *args = *@args + command = help? ? "help" : self.class.lookup_command(command_name) + unless ENV["MACOS_VERSION"].nil? MacOS.full_version = ENV["MACOS_VERSION"] end - command_string, *rest = *arguments - rest = process_options(rest) - command = help? ? "help" : lookup_command(command_string) Hbc.default_tap.install unless Hbc.default_tap.installed? - Hbc.init if should_init?(command) - run_command(command, *rest) - rescue CaskError, CaskSha256MismatchError, ArgumentError => e + Hbc.init if self.class.should_init?(command) + self.class.run_command(command, *args) + rescue CaskError, CaskSha256MismatchError, ArgumentError, OptionParser::InvalidOption => e msg = e.message msg << e.backtrace.join("\n") if ARGV.debug? onoe msg @@ -188,59 +184,25 @@ module Hbc list.sort end - def self.parser - # If you modify these arguments, please update USAGE.md - @parser ||= OptionParser.new do |opts| - opts.on("--language STRING") do - # handled in OS::Mac - end - - OPTIONS.each do |option, method| - opts.on("#{option}" "PATH", Pathname) do |path| - Hbc.public_send(method, path) - end - end - - opts.on("--binarydir=PATH") do - opoo <<-EOS.undent - Option --binarydir is obsolete! - Homebrew-Cask now uses the same location as your Homebrew installation for executable links. - EOS - end - - FLAGS.keys.each do |flag, method| - opts.on(flag) do |bool| - send(:"#{method}=", bool) - end - end - - opts.on("--version") do - raise OptionParser::InvalidOption # override default handling of --version - end - end - end - - def self.process_options(args) + def process_options(*args) all_args = Shellwords.shellsplit(ENV["HOMEBREW_CASK_OPTS"] || "") + args - remaining = [] - until all_args.empty? + + non_options = [] + + if idx = all_args.index("--") + non_options += all_args.drop(idx) + all_args = all_args.first(idx) + end + + remaining = all_args.select do |arg| begin - head = all_args.shift - remaining.concat(parser.parse([head])) - rescue OptionParser::InvalidOption - remaining << head - retry - rescue OptionParser::MissingArgument - raise ArgumentError, "The option '#{head}' requires an argument." - rescue OptionParser::AmbiguousOption - raise ArgumentError, "There is more than one possible option that starts with '#{head}'." + !process_arguments([arg]).empty? + rescue OptionParser::InvalidOption, OptionParser::MissingArgument, OptionParser::AmbiguousOption + true end end - # for compat with Homebrew, not certain if this is desirable - self.verbose = true if ARGV.verbose? - - remaining + remaining + non_options end class NullCommand diff --git a/Library/Homebrew/cask/lib/hbc/cli/--version.rb b/Library/Homebrew/cask/lib/hbc/cli/--version.rb index 7f9609c881..1833c51c67 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/--version.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/--version.rb @@ -5,8 +5,13 @@ module Hbc "--#{super}" end + def initialize(*) + super + return if args.empty? + raise ArgumentError, "#{self.class.command_name} does not take arguments." + end + def run - raise ArgumentError, "#{self.class.command_name} does not take arguments." unless @args.empty? puts Hbc.full_version end diff --git a/Library/Homebrew/cask/lib/hbc/cli/abstract_command.rb b/Library/Homebrew/cask/lib/hbc/cli/abstract_command.rb index 0f9f05f94b..5264799eda 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/abstract_command.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/abstract_command.rb @@ -1,6 +1,15 @@ +require_relative "options" + module Hbc class CLI class AbstractCommand + include Options + + option "--[no-]binaries", :binaries, true + option "--debug", :debug, false + option "--verbose", :verbose, false + option "--outdated", :outdated_only, false + def self.command_name @command_name ||= name.sub(/^.*:/, "").gsub(/(.)([A-Z])/, '\1_\2').downcase end @@ -29,8 +38,11 @@ module Hbc new(*args).run end + attr_accessor :args + private :args= + def initialize(*args) - @args = args + @args = process_arguments(*args) end end end diff --git a/Library/Homebrew/cask/lib/hbc/cli/audit.rb b/Library/Homebrew/cask/lib/hbc/cli/audit.rb index 697b47ba6a..74d1ebfa77 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/audit.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/audit.rb @@ -1,21 +1,18 @@ module Hbc class CLI class Audit < AbstractCommand + option "--download", :download, false + option "--token-conflicts", :token_conflicts, false + def self.help "verifies installability of Casks" end - def initialize(*args, auditor: Auditor) - @args = args - @auditor = auditor - end - def run - failed_casks = [] + casks_to_audit = args.empty? ? Hbc.all : args.map(&CaskLoader.public_method(:load)) - casks_to_audit.each do |cask| - next if audit(cask) - failed_casks << cask + failed_casks = casks_to_audit.reject do |cask| + audit(cask) end return if failed_casks.empty? @@ -24,28 +21,7 @@ module Hbc def audit(cask) odebug "Auditing Cask #{cask}" - @auditor.audit(cask, audit_download: audit_download?, - check_token_conflicts: check_token_conflicts?) - end - - def audit_download? - @args.include?("--download") - end - - def check_token_conflicts? - @args.include?("--token-conflicts") - end - - def casks_to_audit - if cask_tokens.empty? - Hbc.all - else - cask_tokens.map { |token| CaskLoader.load(token) } - end - end - - def cask_tokens - @cask_tokens ||= self.class.cask_tokens_from(@args) + Auditor.audit(cask, audit_download: download?, check_token_conflicts: token_conflicts?) end def self.needs_init? diff --git a/Library/Homebrew/cask/lib/hbc/cli/cat.rb b/Library/Homebrew/cask/lib/hbc/cli/cat.rb index 9c678454cb..e68481b46b 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/cat.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/cat.rb @@ -1,14 +1,17 @@ module Hbc class CLI class Cat < AbstractCommand + def initialize(*) + super + raise CaskUnspecifiedError if args.empty? + end + def run - cask_tokens = self.class.cask_tokens_from(@args) - raise CaskUnspecifiedError if cask_tokens.empty? - # only respects the first argument - cask_token = cask_tokens.first.sub(/\.rb$/i, "") - cask_path = CaskLoader.path(cask_token) - raise CaskUnavailableError, cask_token.to_s unless cask_path.exist? - puts File.open(cask_path, &:read) + args.each do |cask_token| + cask_path = CaskLoader.path(cask_token) + raise CaskUnavailableError, cask_token.to_s unless cask_path.exist? + puts File.open(cask_path, &:read) + end end def self.help diff --git a/Library/Homebrew/cask/lib/hbc/cli/cleanup.rb b/Library/Homebrew/cask/lib/hbc/cli/cleanup.rb index 72ba9e65fc..e253932307 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/cleanup.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/cleanup.rb @@ -12,12 +12,11 @@ module Hbc true end - attr_reader :cache_location, :outdated_only + attr_reader :cache_location - def initialize(*args, cache_location: Hbc.cache, outdated_only: CLI.outdated?) - @args = args + def initialize(*args, cache_location: Hbc.cache) + super(*args) @cache_location = Pathname.new(cache_location) - @outdated_only = outdated_only end def run @@ -32,7 +31,7 @@ module Hbc end def outdated?(file) - outdated_only && file && file.stat.mtime > OUTDATED_TIMESTAMP + outdated_only? && file && file.stat.mtime > OUTDATED_TIMESTAMP end def incomplete?(file) @@ -54,7 +53,7 @@ module Hbc def remove_cache_files(*tokens) message = "Removing cached downloads" message.concat " for #{tokens.join(", ")}" unless tokens.empty? - message.concat " older than #{OUTDATED_DAYS} days old" if outdated_only + message.concat " older than #{OUTDATED_DAYS} days old" if outdated_only? ohai message deletable_cache_files = if tokens.empty? diff --git a/Library/Homebrew/cask/lib/hbc/cli/create.rb b/Library/Homebrew/cask/lib/hbc/cli/create.rb index dc8666b374..8de101092b 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/create.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/create.rb @@ -1,15 +1,18 @@ module Hbc class CLI class Create < AbstractCommand - def run - cask_tokens = self.class.cask_tokens_from(@args) - raise CaskUnspecifiedError if cask_tokens.empty? - cask_token = cask_tokens.first.sub(/\.rb$/i, "") - cask_path = CaskLoader.path(cask_token) - odebug "Creating Cask #{cask_token}" + def initialize(*) + super + raise CaskUnspecifiedError if args.empty? + raise ArgumentError, "Only one Cask can be created at a time." if args.count > 1 + end + def run + cask_token = args.first + cask_path = CaskLoader.path(cask_token) raise CaskAlreadyCreatedError, cask_token if cask_path.exist? + odebug "Creating Cask #{cask_token}" File.open(cask_path, "w") do |f| f.write self.class.template(cask_token) end diff --git a/Library/Homebrew/cask/lib/hbc/cli/doctor.rb b/Library/Homebrew/cask/lib/hbc/cli/doctor.rb index 9a3dfcad4a..64cd11f9e2 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/doctor.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/doctor.rb @@ -1,14 +1,20 @@ module Hbc class CLI class Doctor < AbstractCommand - def self.run + def initialize(*) + super + return if args.empty? + raise ArgumentError, "#{self.class.command_name} does not take arguments." + end + + def run ohai "Homebrew-Cask Version", Hbc.full_version - ohai "Homebrew-Cask Install Location", render_install_location - ohai "Homebrew-Cask Staging Location", render_staging_location(Hbc.caskroom) - ohai "Homebrew-Cask Cached Downloads", render_cached_downloads + ohai "Homebrew-Cask Install Location", self.class.render_install_location + ohai "Homebrew-Cask Staging Location", self.class.render_staging_location(Hbc.caskroom) + ohai "Homebrew-Cask Cached Downloads", self.class.render_cached_downloads ohai "Homebrew-Cask Taps:" - puts render_taps(Hbc.default_tap, *alt_taps) - ohai "Contents of $LOAD_PATH", render_load_path($LOAD_PATH) + puts self.class.render_taps(Hbc.default_tap, *self.class.alt_taps) + ohai "Contents of $LOAD_PATH", self.class.render_load_path($LOAD_PATH) ohai "Environment Variables" environment_variables = [ @@ -24,7 +30,7 @@ module Hbc "SHELL", ] - (locale_variables + environment_variables).sort.each(&method(:render_env_var)) + (self.class.locale_variables + environment_variables).sort.each(&self.class.method(:render_env_var)) end def self.locale_variables @@ -45,7 +51,7 @@ module Hbc end def self.alt_taps - Tap.select { |t| t.cask_dir && t != Hbc.default_tap } + Tap.select { |t| t.cask_dir.exist? && t != Hbc.default_tap } end def self.cask_count_for_tap(tap) diff --git a/Library/Homebrew/cask/lib/hbc/cli/edit.rb b/Library/Homebrew/cask/lib/hbc/cli/edit.rb index d8ab3d9e0a..dec0fe36ba 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/edit.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/edit.rb @@ -1,16 +1,21 @@ module Hbc class CLI class Edit < AbstractCommand + def initialize(*) + super + raise CaskUnspecifiedError if args.empty? + raise ArgumentError, "Only one Cask can be created at a time." if args.count > 1 + end + def run - cask_tokens = self.class.cask_tokens_from(@args) - raise CaskUnspecifiedError if cask_tokens.empty? - # only respects the first argument - cask_token = cask_tokens.first.sub(/\.rb$/i, "") + cask_token = args.first cask_path = CaskLoader.path(cask_token) - odebug "Opening editor for Cask #{cask_token}" + unless cask_path.exist? raise CaskUnavailableError, %Q(#{cask_token}, run "brew cask create #{cask_token}" to create a new Cask) end + + odebug "Opening editor for Cask #{cask_token}" exec_editor cask_path end diff --git a/Library/Homebrew/cask/lib/hbc/cli/fetch.rb b/Library/Homebrew/cask/lib/hbc/cli/fetch.rb index 2dc02aaf73..2c1cc5f66e 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/fetch.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/fetch.rb @@ -1,15 +1,18 @@ module Hbc class CLI class Fetch < AbstractCommand - def run - cask_tokens = self.class.cask_tokens_from(@args) - raise CaskUnspecifiedError if cask_tokens.empty? - force = @args.include? "--force" + option "--force", :force, false - cask_tokens.each do |cask_token| + def initialize(*) + super + raise CaskUnspecifiedError if args.empty? + end + + def run + args.each do |cask_token| ohai "Downloading external files for Cask #{cask_token}" cask = CaskLoader.load(cask_token) - downloaded_path = Download.new(cask, force: force).perform + downloaded_path = Download.new(cask, force: force?).perform Verify.all(cask, downloaded_path) ohai "Success! Downloaded to -> #{downloaded_path}" end diff --git a/Library/Homebrew/cask/lib/hbc/cli/home.rb b/Library/Homebrew/cask/lib/hbc/cli/home.rb index 15cbbfc8d5..009bc1e3e5 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/home.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/home.rb @@ -2,7 +2,7 @@ module Hbc class CLI class Home < AbstractCommand def run - casks = @args.map(&CaskLoader.public_method(:load)) + casks = args.map(&CaskLoader.public_method(:load)) if casks.empty? odebug "Opening project homepage" diff --git a/Library/Homebrew/cask/lib/hbc/cli/info.rb b/Library/Homebrew/cask/lib/hbc/cli/info.rb index 1a63b77471..dcfc8d9bb5 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/info.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/info.rb @@ -1,13 +1,13 @@ module Hbc class CLI class Info < AbstractCommand - def initialize(*args) - @cask_tokens = self.class.cask_tokens_from(args) - raise CaskUnspecifiedError if @cask_tokens.empty? + def initialize(*) + super + raise CaskUnspecifiedError if args.empty? end def run - @cask_tokens.each do |cask_token| + args.each do |cask_token| odebug "Getting info for Cask #{cask_token}" cask = CaskLoader.load(cask_token) diff --git a/Library/Homebrew/cask/lib/hbc/cli/install.rb b/Library/Homebrew/cask/lib/hbc/cli/install.rb index fc9ba97fa5..5acd837b1a 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/install.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/install.rb @@ -1,12 +1,13 @@ module Hbc class CLI class Install < AbstractCommand - def initialize(*args) - @cask_tokens = self.class.cask_tokens_from(args) - raise CaskUnspecifiedError if @cask_tokens.empty? - @force = args.include? "--force" - @skip_cask_deps = args.include? "--skip-cask-deps" - @require_sha = args.include? "--require-sha" + option "--force", :force, false + option "--skip-cask-deps", :skip_cask_deps, false + option "--require-sha", :require_sha, false + + def initialize(*) + super + raise CaskUnspecifiedError if args.empty? end def run @@ -19,13 +20,14 @@ module Hbc def install_casks count = 0 - @cask_tokens.each do |cask_token| + args.each do |cask_token| begin cask = CaskLoader.load(cask_token) - Installer.new(cask, binaries: CLI.binaries?, - force: @force, - skip_cask_deps: @skip_cask_deps, - require_sha: @require_sha).install + Installer.new(cask, binaries: binaries?, + verbose: verbose?, + force: force?, + skip_cask_deps: skip_cask_deps?, + require_sha: require_sha?).install count += 1 rescue CaskAlreadyInstalledError => e opoo e.message @@ -43,7 +45,7 @@ module Hbc end end - count.zero? ? nil : count == @cask_tokens.length + count.zero? ? nil : count == args.length end def self.warn_unavailable_with_suggestion(cask_token, e) diff --git a/Library/Homebrew/cask/lib/hbc/cli/internal_appcast_checkpoint.rb b/Library/Homebrew/cask/lib/hbc/cli/internal_appcast_checkpoint.rb index ed90bc4a9b..6b83b24464 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/internal_appcast_checkpoint.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/internal_appcast_checkpoint.rb @@ -1,17 +1,18 @@ module Hbc class CLI class InternalAppcastCheckpoint < AbstractInternalCommand - def initialize(*args) - @cask_tokens = cask_tokens_from(args) - raise CaskUnspecifiedError if cask_tokens.empty? - @calculate = args.include? "--calculate" + option "--calculate", :calculate, false + + def initialize(*) + super + raise CaskUnspecifiedError if args.empty? end def run - if @cask_tokens.all? { |t| t =~ %r{^https?://} && t !~ /\.rb$/ } + if cask_tokens.all? { |t| t =~ %r{^https?://} && t !~ /\.rb$/ } self.class.appcask_checkpoint_for_url(cask_tokens) else - self.class.appcask_checkpoint(@cask_tokens, @calculate) + self.class.appcask_checkpoint(cask_tokens, calculate?) end end diff --git a/Library/Homebrew/cask/lib/hbc/cli/internal_audit_modified_casks.rb b/Library/Homebrew/cask/lib/hbc/cli/internal_audit_modified_casks.rb index e1b0e47918..f1a0308e57 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/internal_audit_modified_casks.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/internal_audit_modified_casks.rb @@ -3,23 +3,27 @@ module Hbc class InternalAuditModifiedCasks < AbstractInternalCommand RELEVANT_STANZAS = [:version, :sha256, :url, :appcast].freeze + option "--cleanup", :cleanup, false + def self.needs_init? true end - def initialize(*args) - @commit_range = self.class.commit_range(args) - @cleanup = args.any? { |a| a =~ /^-+c(leanup)?$/i } - end + attr_accessor :commit_range + private :commit_range= - def self.commit_range(args) - posargs = args.reject { |a| a.empty? || a.chars.first == "-" } - odie usage unless posargs.size == 1 - posargs.first - end + def initialize(*) + super - def self.posargs(args) - args.reject { |a| a.empty? || a.chars.first == "-" } + if args.count != 1 + raise ArgumentError, <<-EOS.undent + This command requires exactly one argument. + + #{self.class.usage} + EOS + end + + @commit_range = args.first end def self.help @@ -40,12 +44,6 @@ module Hbc EOS end - attr_reader :commit_range - - def cleanup? - @cleanup - end - def run at_exit do cleanup diff --git a/Library/Homebrew/cask/lib/hbc/cli/internal_checkurl.rb b/Library/Homebrew/cask/lib/hbc/cli/internal_checkurl.rb index b0378cfd51..a8c3d5c8f0 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/internal_checkurl.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/internal_checkurl.rb @@ -2,7 +2,7 @@ module Hbc class CLI class InternalCheckurl < AbstractInternalCommand def run - casks_to_check = @args.empty? ? Hbc.all : @args.map { |arg| CaskLoader.load(arg) } + casks_to_check = args.empty? ? Hbc.all : args.map(&CaskLoader.public_method(:load)) casks_to_check.each do |cask| odebug "Checking URL for Cask #{cask}" checker = UrlChecker.new(cask) diff --git a/Library/Homebrew/cask/lib/hbc/cli/internal_dump.rb b/Library/Homebrew/cask/lib/hbc/cli/internal_dump.rb index 6a0d458cf3..78dbf1622b 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/internal_dump.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/internal_dump.rb @@ -1,9 +1,9 @@ module Hbc class CLI class InternalDump < AbstractInternalCommand - def initialize(*args) - @cask_tokens = self.class.cask_tokens_from(args) - raise CaskUnspecifiedError if @cask_tokens.empty? + def initialize(*) + super + raise CaskUnspecifiedError if args.empty? end def run @@ -16,7 +16,7 @@ module Hbc def dump_casks count = 0 - @cask_tokens.each do |cask_token| + args.each do |cask_token| begin cask = CaskLoader.load(cask_token) count += 1 @@ -25,7 +25,7 @@ module Hbc opoo "#{cask_token} was not found or would not load: #{e}" end end - count.zero? ? nil : count == @cask_tokens.length + count.zero? ? nil : count == args.length end def self.help diff --git a/Library/Homebrew/cask/lib/hbc/cli/internal_help.rb b/Library/Homebrew/cask/lib/hbc/cli/internal_help.rb index 79f65da0e4..beac77b293 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/internal_help.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/internal_help.rb @@ -1,6 +1,12 @@ module Hbc class CLI class InternalHelp < AbstractInternalCommand + def initialize(*) + super + return if args.empty? + raise ArgumentError, "#{self.class.command_name} does not take arguments." + end + def run max_command_len = CLI.commands.map(&:length).max puts "Unstable Internal-use Commands:\n\n" diff --git a/Library/Homebrew/cask/lib/hbc/cli/internal_stanza.rb b/Library/Homebrew/cask/lib/hbc/cli/internal_stanza.rb index 75ccfef023..86dee7c9c1 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/internal_stanza.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/internal_stanza.rb @@ -50,51 +50,60 @@ module Hbc :uninstall_postflight, ] - def initialize(*args) + option "--table", :table, false + option "--quiet", :quiet, false + option "--yaml", :yaml, false + option "--inspect", :inspect, false + + attr_accessor :format + private :format, :format= + + attr_accessor :stanza + private :stanza, :stanza= + + def initialize(*) + super raise ArgumentError, "No stanza given." if args.empty? - @table = args.include? "--table" - @quiet = args.include? "--quiet" - @format = :to_yaml if args.include? "--yaml" - @format = :inspect if args.include? "--inspect" - @cask_tokens = self.class.cask_tokens_from(args) - @stanza = @cask_tokens.shift.to_sym - @cask_tokens = Hbc.all_tokens if @cask_tokens.empty? + @stanza = args.shift.to_sym + + @format = :to_yaml if yaml? + @format = :inspect if inspect? end def run retval = print_stanzas - # retval is ternary: true/false/nil if retval.nil? - exit 1 if @quiet + exit 1 if quiet? raise CaskError, "nothing to print" elsif !retval - exit 1 if @quiet + exit 1 if quiet? raise CaskError, "print incomplete" end end def print_stanzas count = 0 - if ARTIFACTS.include?(@stanza) - artifact_name = @stanza + if ARTIFACTS.include?(stanza) + artifact_name = stanza @stanza = :artifacts end - @cask_tokens.each do |cask_token| - print "#{cask_token}\t" if @table + cask_tokens = args.empty? ? Hbc.all_tokens : args + cask_tokens.each do |cask_token| + print "#{cask_token}\t" if table? begin cask = CaskLoader.load(cask_token) rescue StandardError - opoo "Cask '#{cask_token}' was not found" unless @quiet + opoo "Cask '#{cask_token}' was not found" unless quiet? puts "" next end - unless cask.respond_to?(@stanza) - opoo "no such stanza '#{@stanza}' on Cask '#{cask_token}'" unless @quiet + unless cask.respond_to?(stanza) + opoo "no such stanza '#{stanza}' on Cask '#{cask_token}'" unless quiet? puts "" next end @@ -102,13 +111,13 @@ module Hbc begin value = cask.send(@stanza) rescue StandardError - opoo "failure calling '#{@stanza}' on Cask '#{cask_token}'" unless @quiet + opoo "failure calling '#{stanza}' on Cask '#{cask_token}'" unless quiet? puts "" next end if artifact_name && !value.key?(artifact_name) - opoo "no such stanza '#{artifact_name}' on Cask '#{cask_token}'" unless @quiet + opoo "no such stanza '#{artifact_name}' on Cask '#{cask_token}'" unless quiet? puts "" next end @@ -125,7 +134,7 @@ module Hbc count += 1 end - count.zero? ? nil : count == @cask_tokens.length + count.zero? ? nil : count == cask_tokens.length end def self.help diff --git a/Library/Homebrew/cask/lib/hbc/cli/list.rb b/Library/Homebrew/cask/lib/hbc/cli/list.rb index 79f7687e1b..04dccbf858 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/list.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/list.rb @@ -1,20 +1,18 @@ module Hbc class CLI class List < AbstractCommand - def initialize(*args) - @cask_tokens = self.class.cask_tokens_from(args) - @one = true if args.delete("-1") - @versions = true if args.delete("--versions") + option "-1", :one, false + option "--versions", :versions, false - return unless args.delete("-l") - @one = true + option "-l", (lambda do |*| + one = true # rubocop:disable Lint/UselessAssignment opoo "Option -l is obsolete! Implying option -1." - end + end) def run - retval = @cask_tokens.any? ? list : list_installed + retval = args.any? ? list : list_installed # retval is ternary: true/false/nil - if retval.nil? && !@cask_tokens.any? + if retval.nil? && !args.any? opoo "nothing to list" # special case: avoid exit code elsif retval.nil? raise CaskError, "nothing to list" @@ -26,15 +24,15 @@ module Hbc def list count = 0 - @cask_tokens.each do |cask_token| + args.each do |cask_token| odebug "Listing files for Cask #{cask_token}" begin cask = CaskLoader.load(cask_token) if cask.installed? - if @one + if one? puts cask.token - elsif @versions + elsif versions? puts self.class.format_versioned(cask) else cask = CaskLoader.load_from_file(cask.installed_caskfile) @@ -50,7 +48,7 @@ module Hbc end end - count.zero? ? nil : count == @cask_tokens.length + count.zero? ? nil : count == args.length end def self.list_artifacts(cask) @@ -63,9 +61,9 @@ module Hbc def list_installed installed_casks = Hbc.installed - if @one + if one? puts installed_casks.map(&:to_s) - elsif @versions + elsif versions? puts installed_casks.map(&self.class.method(:format_versioned)) elsif !installed_casks.empty? puts Formatter.columns(installed_casks.map(&:to_s)) diff --git a/Library/Homebrew/cask/lib/hbc/cli/options.rb b/Library/Homebrew/cask/lib/hbc/cli/options.rb new file mode 100644 index 0000000000..84126caa56 --- /dev/null +++ b/Library/Homebrew/cask/lib/hbc/cli/options.rb @@ -0,0 +1,62 @@ +module Hbc + class CLI + module Options + def self.included(klass) + klass.extend(ClassMethods) + end + + module ClassMethods + def options + @options ||= {} + return @options unless superclass.respond_to?(:options) + superclass.options.merge(@options) + end + + def option(name, method, default_value = nil) + @options ||= {} + @options[name] = method + + return if method.respond_to?(:call) + + define_method(:"#{method}=") do |value| + instance_variable_set(:"@#{method}", value) + end + + if [true, false].include?(default_value) + define_method(:"#{method}?") do + instance_variable_get(:"@#{method}") == true + end + else + define_method(:"#{method}") do + instance_variable_get(:"@#{method}") + end + end + end + end + + def process_arguments(*arguments) + parser = OptionParser.new do |opts| + next if self.class.options.nil? + + self.class.options.each do |option_name, option_method| + option_type = case option_name.split(/(\ |\=)/).last + when "PATH" + Pathname + when /\w+(,\w+)+/ + Array + end + + opts.on(option_name, *option_type) do |value| + if option_method.respond_to?(:call) + option_method.call(value) + else + send(:"#{option_method}=", value) + end + end + end + end + parser.parse(*arguments) + end + end + end +end diff --git a/Library/Homebrew/cask/lib/hbc/cli/outdated.rb b/Library/Homebrew/cask/lib/hbc/cli/outdated.rb index c56e28e28d..7877ead05d 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/outdated.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/outdated.rb @@ -1,23 +1,20 @@ module Hbc class CLI class Outdated < AbstractCommand - def initialize(*args) - @cask_tokens = self.class.cask_tokens_from(args) + option "--greedy", :greedy, false + option "--quiet", :quiet, false - @greedy = args.include?("--greedy") - @verbose = ($stdout.tty? || CLI.verbose?) && !args.include?("--quiet") + def initialize(*) + super + self.verbose = ($stdout.tty? || verbose?) && !quiet? end def run - casks_to_check = if @cask_tokens.empty? - Hbc.installed - else - @cask_tokens.map(&CaskLoader.public_method(:load)) - end + casks_to_check = args.empty? ? Hbc.installed : args.map(&CaskLoader.public_method(:load)) casks_to_check.each do |cask| odebug "Checking update info of Cask #{cask}" - self.class.list_if_outdated(cask, @greedy, @verbose) + self.class.list_if_outdated(cask, greedy?, verbose?) end end diff --git a/Library/Homebrew/cask/lib/hbc/cli/reinstall.rb b/Library/Homebrew/cask/lib/hbc/cli/reinstall.rb index b675a79fa5..eb5f45c905 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/reinstall.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/reinstall.rb @@ -3,15 +3,16 @@ module Hbc class Reinstall < Install def install_casks count = 0 - @cask_tokens.each do |cask_token| + args.each do |cask_token| begin cask = CaskLoader.load(cask_token) Installer.new(cask, - binaries: CLI.binaries?, - force: @force, - skip_cask_deps: @skip_cask_deps, - require_sha: @require_sha).reinstall + binaries: binaries?, + verbose: verbose?, + force: force?, + skip_cask_deps: skip_cask_deps?, + require_sha: require_sha?).reinstall count += 1 rescue CaskUnavailableError => e @@ -22,7 +23,7 @@ module Hbc end end - count.zero? ? nil : count == @cask_tokens.length + count.zero? ? nil : count == args.length end def self.help diff --git a/Library/Homebrew/cask/lib/hbc/cli/search.rb b/Library/Homebrew/cask/lib/hbc/cli/search.rb index 255010baeb..b24091aef6 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/search.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/search.rb @@ -1,8 +1,13 @@ module Hbc class CLI class Search < AbstractCommand + def initialize(*args) + @args = args + end + def run - self.class.render_results(*self.class.search(*@args)) + results = self.class.search(*args) + self.class.render_results(*results) end def self.extract_regexp(string) diff --git a/Library/Homebrew/cask/lib/hbc/cli/style.rb b/Library/Homebrew/cask/lib/hbc/cli/style.rb index 992e1bb136..078796e7e1 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/style.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/style.rb @@ -7,15 +7,7 @@ module Hbc "checks Cask style using RuboCop" end - attr_reader :args - def initialize(*args) - @cask_tokens = self.class.cask_tokens_from(args) - @fix = args.any? { |arg| arg =~ /^--(fix|(auto-?)?correct)$/ } - end - - def fix? - @fix - end + option "--fix", :fix, false def run install_rubocop @@ -35,12 +27,12 @@ module Hbc end def cask_paths - @cask_paths ||= if @cask_tokens.empty? + @cask_paths ||= if args.empty? Hbc.all_tapped_cask_dirs - elsif @cask_tokens.any? { |file| File.exist?(file) } - @cask_tokens + elsif args.any? { |file| File.exist?(file) } + args else - @cask_tokens.map { |token| CaskLoader.path(token) } + args.map { |token| CaskLoader.path(token) } end end diff --git a/Library/Homebrew/cask/lib/hbc/cli/uninstall.rb b/Library/Homebrew/cask/lib/hbc/cli/uninstall.rb index 55c733108d..33ee5afa9a 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/uninstall.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/uninstall.rb @@ -1,25 +1,26 @@ module Hbc class CLI class Uninstall < AbstractCommand - def initialize(*args) - @cask_tokens = self.class.cask_tokens_from(args) - raise CaskUnspecifiedError if @cask_tokens.empty? - @force = args.include? "--force" + option "--force", :force, false + + def initialize(*) + super + raise CaskUnspecifiedError if args.empty? end def run - @cask_tokens.each do |cask_token| + args.each do |cask_token| odebug "Uninstalling Cask #{cask_token}" cask = CaskLoader.load(cask_token) - raise CaskNotInstalledError, cask unless cask.installed? || @force + raise CaskNotInstalledError, cask unless cask.installed? || force? if cask.installed? && !cask.installed_caskfile.nil? # use the same cask file that was used for installation, if possible cask = CaskLoader.load_from_file(cask.installed_caskfile) if cask.installed_caskfile.exist? end - Installer.new(cask, binaries: CLI.binaries?, force: @force).uninstall + Installer.new(cask, binaries: binaries?, verbose: verbose?, force: force?).uninstall next if (versions = cask.versions).empty? diff --git a/Library/Homebrew/cask/lib/hbc/cli/zap.rb b/Library/Homebrew/cask/lib/hbc/cli/zap.rb index 61a0df27ce..3c07ff9e88 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/zap.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/zap.rb @@ -1,16 +1,16 @@ module Hbc class CLI class Zap < AbstractCommand - def initialize(*args) - @cask_tokens = self.class.cask_tokens_from(args) - raise CaskUnspecifiedError if @cask_tokens.empty? + def initialize(*) + super + raise CaskUnspecifiedError if args.empty? end def run - @cask_tokens.each do |cask_token| + args.each do |cask_token| odebug "Zapping Cask #{cask_token}" cask = CaskLoader.load(cask_token) - Installer.new(cask).zap + Installer.new(cask, verbose: verbose?).zap end end diff --git a/Library/Homebrew/cask/lib/hbc/installer.rb b/Library/Homebrew/cask/lib/hbc/installer.rb index d9addd6040..a783f764bf 100644 --- a/Library/Homebrew/cask/lib/hbc/installer.rb +++ b/Library/Homebrew/cask/lib/hbc/installer.rb @@ -14,24 +14,35 @@ module Hbc include Staged include Verify - attr_reader :force, :skip_cask_deps - PERSISTENT_METADATA_SUBDIRS = ["gpg"].freeze - def initialize(cask, command: SystemCommand, force: false, skip_cask_deps: false, binaries: true, require_sha: false) + def initialize(cask, command: SystemCommand, force: false, skip_cask_deps: false, binaries: true, verbose: false, require_sha: false) @cask = cask @command = command @force = force @skip_cask_deps = skip_cask_deps @binaries = binaries + @verbose = verbose @require_sha = require_sha @reinstall = false end + def skip_cask_deps? + @skip_cask_deps + end + + def force? + @force + end + def binaries? @binaries end + def verbose? + @verbose + end + def self.print_caveats(cask) odebug "Printing caveats" return if cask.caveats.empty? @@ -64,7 +75,7 @@ module Hbc odebug "Hbc::Installer#fetch" satisfy_dependencies - verify_has_sha if @require_sha && !@force + verify_has_sha if @require_sha && !force? download verify end @@ -82,7 +93,7 @@ module Hbc def install odebug "Hbc::Installer#install" - if @cask.installed? && !force && !@reinstall + if @cask.installed? && !force? && !@reinstall raise CaskAlreadyInstalledAutoUpdatesError, @cask if @cask.auto_updates raise CaskAlreadyInstalledError, @cask end @@ -113,7 +124,7 @@ module Hbc installed_cask = installed_caskfile.exist? ? CaskLoader.load_from_file(installed_caskfile) : @cask # Always force uninstallation, ignore method parameter - Installer.new(installed_cask, binaries: binaries?, force: true).uninstall + Installer.new(installed_cask, binaries: binaries?, verbose: verbose?, force: true).uninstall end def summary @@ -161,7 +172,7 @@ module Hbc already_installed_artifacts = [] odebug "Installing artifacts" - artifacts = Artifact.for_cask(@cask, command: @command, force: force) + artifacts = Artifact.for_cask(@cask, command: @command, verbose: verbose?, force: force?) odebug "#{artifacts.length} artifact/s defined", artifacts artifacts.each do |artifact| @@ -199,7 +210,7 @@ module Hbc arch_dependencies x11_dependencies formula_dependencies - cask_dependencies unless skip_cask_deps + cask_dependencies unless skip_cask_deps? puts "complete" end @@ -264,7 +275,7 @@ module Hbc if dep.installed? puts "already installed" else - Installer.new(dep, force: false, binaries: binaries?, skip_cask_deps: true).install + Installer.new(dep, binaries: binaries?, verbose: verbose?, skip_cask_deps: true, force: false).install puts "done" end end @@ -340,12 +351,12 @@ module Hbc disable_accessibility_access uninstall_artifacts purge_versioned_files - purge_caskroom_path if force + purge_caskroom_path if force? end def uninstall_artifacts odebug "Un-installing artifacts" - artifacts = Artifact.for_cask(@cask, command: @command, force: force) + artifacts = Artifact.for_cask(@cask, command: @command, verbose: verbose?, force: force?) # Make sure the `uninstall` stanza is run first, as it # may depend on other artifacts still being installed. diff --git a/Library/Homebrew/cmd/cask.rb b/Library/Homebrew/cmd/cask.rb index 8a68b8d9a7..550081d46d 100644 --- a/Library/Homebrew/cmd/cask.rb +++ b/Library/Homebrew/cmd/cask.rb @@ -5,6 +5,6 @@ module Homebrew module_function def cask - Hbc::CLI.process(ARGV) + Hbc::CLI.run(*ARGV) end end