From 29a6a1ec103d50d9addc4fa8387af6bb77bb4296 Mon Sep 17 00:00:00 2001 From: Roland Walker Date: Sat, 21 Jun 2014 14:51:57 -0400 Subject: [PATCH] Extend subcommand dispatch to include full paths Covering all cases - external commands as executables - external commands as Ruby libraries - built-in command verbs This is intended as a development aid. A side benefit is that an external command can be constructed to use a `run` method, rather than having to accomplish everything at `require` time. --- doc/HACKING.md | 12 ++++++++++++ lib/cask/cli.rb | 40 ++++++++++++++++++++++++++++++++++++++-- 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/doc/HACKING.md b/doc/HACKING.md index f7c958790e..e227e73d4a 100644 --- a/doc/HACKING.md +++ b/doc/HACKING.md @@ -144,6 +144,18 @@ with fully-qualified paths, like this: $ HOMEBREW_BREW_FILE=/usr/local/bin/brew /System/Library/Frameworks/Ruby.framework/Versions/Current/usr/bin/ruby /usr/local/Library/brew.rb /usr/local/bin/brew-cask.rb help ``` +## How Can I Force a Specific Homebrew-cask Subcommand? + +If you are developing a subcommand, you can force `brew cask` to dispatch a +specific file by giving a fully-qualified path to the file containing the +subcommand, like this: + +```bash +$ brew cask /usr/local/Cellar/brew-cask/0.37.0/rubylib/cask/cli/info.rb google-chrome +``` + +This form can also be combined with a specific Ruby interpreter as above. + ## Hanging out on IRC We're on IRC at `#homebrew-cask` on Freenode. If you are going to develop for diff --git a/lib/cask/cli.rb b/lib/cask/cli.rb index 64dcf6e7c7..12a055503d 100644 --- a/lib/cask/cli.rb +++ b/lib/cask/cli.rb @@ -63,14 +63,50 @@ class Cask::CLI @@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.run_command(command, *rest) if command.respond_to?(:run) + # usual case: built-in command verb command.run(*rest) - elsif which "brewcask-#{command}" - exec "brewcask-#{command}", *ARGV[1..-1] elsif require? which("brewcask-#{command}.rb").to_s + # external command as Ruby library on PATH, Homebrew-style exit 0 + elsif command.to_s.include?('/') and 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 + Cask::CLI.const_get(sym) + rescue + 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" + exit 0 + end + elsif which "brewcask-#{command}" + # arbitrary external executable on PATH, Homebrew-style + exec "brewcask-#{command}", *ARGV[1..-1] + elsif Pathname.new(command.to_s).executable? and + command.to_s.include?('/') and + not command.to_s.match(%{\.rb$}) + # arbitrary external executable with literal path, useful + # for development and troubleshooting + exec command, *ARGV[1..-1] else + # failure Cask::CLI::NullCommand.new(command).run end end