diff options
| author | AnastasiaSulyagina | 2016-08-18 22:11:42 +0300 |
|---|---|---|
| committer | AnastasiaSulyagina | 2016-08-19 14:50:14 +0300 |
| commit | e81f4ab7deeb40308f240be5ea00091fc8786d7a (patch) | |
| tree | b5418f9149de71c0f05f90cb2b39ab47f46e27b4 /Library/Homebrew/cask/lib/hbc/cli.rb | |
| parent | 5c7c9de669025bbe4cad9829be39c5cf3b31ad25 (diff) | |
| download | brew-e81f4ab7deeb40308f240be5ea00091fc8786d7a.tar.bz2 | |
init
Diffstat (limited to 'Library/Homebrew/cask/lib/hbc/cli.rb')
| -rw-r--r-- | Library/Homebrew/cask/lib/hbc/cli.rb | 274 |
1 files changed, 274 insertions, 0 deletions
diff --git a/Library/Homebrew/cask/lib/hbc/cli.rb b/Library/Homebrew/cask/lib/hbc/cli.rb new file mode 100644 index 000000000..be40ce11b --- /dev/null +++ b/Library/Homebrew/cask/lib/hbc/cli.rb @@ -0,0 +1,274 @@ +class Hbc::CLI; end + +require "optparse" +require "shellwords" + +require "hbc/cli/base" +require "hbc/cli/audit" +require "hbc/cli/cat" +require "hbc/cli/cleanup" +require "hbc/cli/create" +require "hbc/cli/doctor" +require "hbc/cli/edit" +require "hbc/cli/fetch" +require "hbc/cli/home" +require "hbc/cli/info" +require "hbc/cli/install" +require "hbc/cli/list" +require "hbc/cli/search" +require "hbc/cli/style" +require "hbc/cli/uninstall" +require "hbc/cli/update" +require "hbc/cli/zap" + +require "hbc/cli/internal_use_base" +require "hbc/cli/internal_audit_modified_casks" +require "hbc/cli/internal_checkurl" +require "hbc/cli/internal_dump" +require "hbc/cli/internal_help" +require "hbc/cli/internal_stanza" + +class Hbc::CLI + ALIASES = { + "ls" => "list", + "homepage" => "home", + "-S" => "search", # verb starting with "-" is questionable + "up" => "update", + "instal" => "install", # gem does the same + "rm" => "uninstall", + "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=, + "--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 + + FLAGS = { + "--no-binaries" => :no_binaries=, + "--debug" => :debug=, + "--verbose" => :verbose=, + "--outdated" => :cleanup_outdated=, + "--help" => :help=, + }.freeze + + def self.command_classes + @command_classes ||= Hbc::CLI.constants + .map(&Hbc::CLI.method(:const_get)) + .select { |sym| sym.respond_to?(:run) } + end + + def self.commands + @commands ||= command_classes.map(&:command_name) + end + + def self.lookup_command(command_string) + @lookup ||= Hash[commands.zip(command_classes)] + command_string = ALIASES.fetch(command_string, command_string) + @lookup.fetch(command_string, command_string) + end + + # modified from Homebrew + def self.require?(path) + require path + true # OK if already loaded + rescue LoadError => e + # HACK: :( because we should raise on syntax errors + # but not if the file doesn't exist. + # TODO: make robust! + raise unless e.to_s.include? path + end + + def self.should_init?(command) + (command.is_a? Class) && (command < Hbc::CLI::Base) && command.needs_init? + end + + def self.run_command(command, *rest) + if command.respond_to?(:run) + # usual case: built-in command verb + command.run(*rest) + elsif require? Hbc::Utils.which("brewcask-#{command}.rb").to_s + # external command as Ruby library on PATH, Homebrew-style + elsif command.to_s.include?("/") && require?(command.to_s) + # external command as Ruby library with literal path, useful + # for development and troubleshooting + sym = Pathname.new(command.to_s).basename(".rb").to_s.capitalize + klass = begin + Hbc::CLI.const_get(sym) + rescue NameError + nil + end + if klass.respond_to?(:run) + # invoke "run" on a Ruby library which follows our coding conventions + klass.run(*rest) + else + # other Ruby libraries must do everything via "require" + end + elsif Hbc::Utils.which "brewcask-#{command}" + # arbitrary external executable on PATH, Homebrew-style + exec "brewcask-#{command}", *ARGV[1..-1] + elsif Pathname.new(command.to_s).executable? && + command.to_s.include?("/") && + !command.to_s.match(%r{\.rb$}) + # arbitrary external executable with literal path, useful + # for development and troubleshooting + exec command, *ARGV[1..-1] + else + # failure + Hbc::CLI::NullCommand.new(command).run + end + end + + def self.process(arguments) + command_string, *rest = *arguments + rest = process_options(rest) + command = Hbc.help ? "help" : lookup_command(command_string) + Hbc.init if should_init?(command) + run_command(command, *rest) + rescue Hbc::CaskError, Hbc::CaskSha256MismatchError => e + msg = e.message + msg << e.backtrace.join("\n") if Hbc.debug + onoe msg + exit 1 + rescue StandardError, ScriptError, NoMemoryError => e + msg = e.message + msg << Hbc::Utils.error_message_with_suggestions + msg << e.backtrace.join("\n") + onoe msg + exit 1 + end + + def self.nice_listing(cask_list) + cask_taps = {} + cask_list.each do |c| + user, repo, token = c.split "/" + repo.sub!(%r{^homebrew-}i, "") + cask_taps[token] ||= [] + cask_taps[token].push "#{user}/#{repo}" + end + list = [] + cask_taps.each do |token, taps| + if taps.length == 1 + list.push token + else + taps.each { |r| list.push [r, token].join "/" } + end + end + list.sort + end + + def self.parser + # If you modify these arguments, please update USAGE.md + @parser ||= OptionParser.new do |opts| + 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 <<-EOF.undent + Option --binarydir is obsolete! + Homebrew-Cask now uses the same location as your Homebrew installation for executable links. + EOF + end + + FLAGS.each do |flag, method| + opts.on(flag) do + Hbc.public_send(method, true) + end + end + + opts.on("--version") do + raise OptionParser::InvalidOption # override default handling of --version + end + end + end + + def self.process_options(args) + all_args = Shellwords.shellsplit(ENV["HOMEBREW_CASK_OPTS"] || "") + args + remaining = [] + until all_args.empty? + begin + head = all_args.shift + remaining.concat(parser.parse([head])) + rescue OptionParser::InvalidOption + remaining << head + retry + rescue OptionParser::MissingArgument + raise Hbc::CaskError, "The option '#{head}' requires an argument" + rescue OptionParser::AmbiguousOption + raise Hbc::CaskError, "There is more than one possible option that starts with '#{head}'" + end + end + + # for compat with Homebrew, not certain if this is desirable + Hbc.verbose = true if !ENV["VERBOSE"].nil? || !ENV["HOMEBREW_VERBOSE"].nil? + + remaining + end + + class NullCommand + def initialize(attempted_verb) + @attempted_verb = attempted_verb + end + + def run(*args) + if args.include?("--version") || @attempted_verb == "--version" + puts Hbc.full_version + else + purpose + usage + unless @attempted_verb.to_s.strip.empty? || @attempted_verb == "help" + raise Hbc::CaskError, "Unknown command: #{@attempted_verb}" + end + end + end + + def purpose + puts <<-PURPOSE.undent + brew-cask provides a friendly homebrew-style CLI workflow for the + administration of macOS applications distributed as binaries. + + PURPOSE + end + + def usage + max_command_len = Hbc::CLI.commands.map(&:length).max + + puts "Commands:\n\n" + Hbc::CLI.command_classes.each do |klass| + next unless klass.visible + puts " #{klass.command_name.ljust(max_command_len)} #{_help_for(klass)}" + end + puts %Q{\nSee also "man brew-cask"} + end + + def help + "" + end + + def _help_for(klass) + klass.respond_to?(:help) ? klass.help : nil + end + end +end |
