Commands can now be registered as subcommands (similar to how config works)
This commit is contained in:
parent
83da66ee91
commit
aec05eff0d
|
@ -21,18 +21,7 @@ module Vagrant
|
|||
# Execute a subcommand with the given name and args. This method properly
|
||||
# finds the subcommand, instantiates it, and executes.
|
||||
def subcommand(name, *args)
|
||||
command_klass = Commands.const_get(camelize(name))
|
||||
command = command_klass.new(env)
|
||||
command.execute(args)
|
||||
end
|
||||
|
||||
# Camel-case a string.
|
||||
def camelize(string)
|
||||
parts = string.to_s.split(/[^a-z0-9]/).collect do |part|
|
||||
part.capitalize
|
||||
end
|
||||
|
||||
parts.join("")
|
||||
Commands::Base.dispatch(env, name, *args)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -7,6 +7,61 @@ module Vagrant
|
|||
class Base
|
||||
attr_reader :env
|
||||
|
||||
class <<self
|
||||
# Contains the list of registered subcommands. The registered commands are
|
||||
# stored in a hash table and are therefore unordered.
|
||||
#
|
||||
# @return [Hash]
|
||||
def subcommands
|
||||
@subcommands ||= {}
|
||||
end
|
||||
|
||||
# Registers a command with `vagrant`. This method allows 3rd parties to
|
||||
# dynamically add new commands to the `vagrant` command, allowing plugins
|
||||
# to act as 1st class citizens within vagrant.
|
||||
#
|
||||
# @param [String] key The subcommand which will invoke the registered command.
|
||||
# @param [Class] klass. The subcommand class (a subclass of {Base})
|
||||
def subcommand(key, klass)
|
||||
subcommands[key] = klass
|
||||
end
|
||||
|
||||
# Dispatches a subcommand to the proper registered command. Otherwise, it
|
||||
# prints a help message.
|
||||
def dispatch(env, name, *args)
|
||||
klass = subcommands[name]
|
||||
if klass.nil?
|
||||
puts_help
|
||||
return # For tests
|
||||
end
|
||||
|
||||
command = klass.new(env)
|
||||
command.execute(args)
|
||||
end
|
||||
|
||||
# Prints out the list of supported commands and their descriptions (if
|
||||
# available) then exits.
|
||||
def puts_help
|
||||
puts "Usage: vagrant SUBCOMMAND ...\n\n"
|
||||
|
||||
puts "Supported commands:"
|
||||
subcommands.each do |key, klass|
|
||||
puts "#{' ' * 4}#{key.ljust(20)}#{klass.description}"
|
||||
end
|
||||
|
||||
exit
|
||||
end
|
||||
|
||||
# Sets or reads the description, depending on if the value is set in the
|
||||
# parameter.
|
||||
def description(value=nil)
|
||||
@description ||= ''
|
||||
|
||||
return @description if value.nil?
|
||||
@description = value
|
||||
end
|
||||
end
|
||||
|
||||
def initialize(env)
|
||||
@env = env
|
||||
end
|
||||
|
|
|
@ -1,10 +1,15 @@
|
|||
module Vagrant
|
||||
class Commands
|
||||
class Init < Base
|
||||
Base.subcommand "init", self
|
||||
description "Initializes current folder for Vagrant usage"
|
||||
|
||||
def execute(args)
|
||||
parse_options(args) do |opts, options|
|
||||
opts.banner = "Usage: vagrant init [name]"
|
||||
end
|
||||
|
||||
puts "HEY"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -43,28 +43,10 @@ class CommandTest < Test::Unit::TestCase
|
|||
@instance.stubs(:camelize).with(@raw_name).returns(@name)
|
||||
end
|
||||
|
||||
should "send the command to the proper class" do
|
||||
klass = mock("klass")
|
||||
instance = mock("instance")
|
||||
should "send the env, name, and args to the base class" do
|
||||
args = [1,2,3]
|
||||
Vagrant::Commands.expects(:const_get).with(@name).returns(klass)
|
||||
klass.expects(:new).with(@env).returns(instance)
|
||||
instance.expects(:execute).with(args)
|
||||
|
||||
@instance.subcommand(@raw_name, *args)
|
||||
end
|
||||
end
|
||||
|
||||
context "camelizing" do
|
||||
should "camel case a string" do
|
||||
tests = {
|
||||
"foo_bar_baz" => "FooBarBaz",
|
||||
"ssh-config" => "SshConfig"
|
||||
}
|
||||
|
||||
tests.each do |test, expected|
|
||||
assert_equal expected, @instance.camelize(test)
|
||||
end
|
||||
Vagrant::Commands::Base.expects(:dispatch).with(@env, @name, *args)
|
||||
@instance.subcommand(@name, *args)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -13,6 +13,51 @@ class CommandsBastTest < Test::Unit::TestCase
|
|||
end
|
||||
end
|
||||
|
||||
context "class methods" do
|
||||
setup do
|
||||
@klass.subcommands.clear
|
||||
end
|
||||
|
||||
context "registering commands" do
|
||||
should "register commands" do
|
||||
klass = mock("klass")
|
||||
@klass.subcommand("init", klass)
|
||||
assert_equal klass, @klass.subcommands["init"]
|
||||
end
|
||||
end
|
||||
|
||||
context "dispatching to subcommands" do
|
||||
setup do
|
||||
@command_klass = mock("klass")
|
||||
@name = "init"
|
||||
@klass.subcommand(@name, @command_klass)
|
||||
|
||||
@args = [1,2,3]
|
||||
end
|
||||
|
||||
should "instantiate and execute on registered subcommands" do
|
||||
instance = mock("instance")
|
||||
@command_klass.expects(:new).with(@env).returns(instance)
|
||||
instance.expects(:execute).with(@args)
|
||||
|
||||
@klass.dispatch(@env, @name, *@args)
|
||||
end
|
||||
|
||||
should "print help if command doesn't exist" do
|
||||
@klass.expects(:puts_help).once
|
||||
@klass.dispatch(@env, "#{@name}foo")
|
||||
end
|
||||
end
|
||||
|
||||
context "descriptions" do
|
||||
should "be able to set description" do
|
||||
description = "The lazy fox yada yada"
|
||||
@klass.description(description)
|
||||
assert_equal description, @klass.description
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "instance methods" do
|
||||
setup do
|
||||
@env = mock_environment
|
||||
|
|
Loading…
Reference in New Issue