From bb0d3f7f933a4c58f8ae30b41af76317bc4f93aa Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Tue, 13 Apr 2010 13:53:27 -0700 Subject: [PATCH] Base command now recursively dispatches, allowing for arbitrarily complex commands such as `vagrant a b c` --- lib/vagrant/commands/base.rb | 32 +++++++++++++++++++++++------- lib/vagrant/commands/init.rb | 2 +- test/vagrant/commands/base_test.rb | 22 +++++++++----------- 3 files changed, 35 insertions(+), 21 deletions(-) diff --git a/lib/vagrant/commands/base.rb b/lib/vagrant/commands/base.rb index d5c5c806a..da81c2687 100644 --- a/lib/vagrant/commands/base.rb +++ b/lib/vagrant/commands/base.rb @@ -28,15 +28,21 @@ module Vagrant # Dispatches a subcommand to the proper registered command. Otherwise, it # prints a help message. - def dispatch(env, name, *args) - klass = subcommands[name] + def dispatch(env, *args) + klass = subcommands[args[0]] unless args.empty? if klass.nil? - puts_help - return # For tests + # Run _this_ command! + command = self.new(env) + command.execute(args) + return end - command = klass.new(env) - command.execute(args) + # Shift off the front arg, since we just consumed it in finding the + # subcommand. + args.shift + + # Dispatch to the next class + klass.dispatch(env, *args) end # Prints out the list of supported commands and their descriptions (if @@ -71,7 +77,9 @@ module Vagrant # executed. The `args` parameter is an array of parameters to the # command (similar to ARGV) def execute(args) - raise "Subcommands should implement the execute method properly." + # Just print out the help, since this top-level command does nothing + # on its own + self.class.puts_help end # Parse options out of the command-line. This method uses `optparse` @@ -90,10 +98,20 @@ module Vagrant show_help end + # Gets the description of the command. This is similar grabbed from the + # class level. + def description + self.class.description + end + # Prints the help for the given command. Prior to calling this method, # {#parse_options} must be called or a nilerror will be raised. This # is by design. def show_help + if !description.empty? + puts "Description: #{description}" + end + puts @parser.help exit end diff --git a/lib/vagrant/commands/init.rb b/lib/vagrant/commands/init.rb index 53e4def78..cd3812200 100644 --- a/lib/vagrant/commands/init.rb +++ b/lib/vagrant/commands/init.rb @@ -9,7 +9,7 @@ module Vagrant opts.banner = "Usage: vagrant init [name]" end - puts "HEY" + show_help end end end diff --git a/test/vagrant/commands/base_test.rb b/test/vagrant/commands/base_test.rb index 9adb08347..ee4af2c0a 100644 --- a/test/vagrant/commands/base_test.rb +++ b/test/vagrant/commands/base_test.rb @@ -15,6 +15,7 @@ class CommandsBastTest < Test::Unit::TestCase context "class methods" do setup do + @env = mock_environment @klass.subcommands.clear end @@ -35,17 +36,16 @@ class CommandsBastTest < Test::Unit::TestCase @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) - + should "call dispatch on child if subcommand is found" do + @command_klass.expects(:dispatch).with(@env, *@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") + should "instantiate and execute when no subcommand is found" do + instance = mock("instance") + @klass.expects(:new).with(@env).returns(instance) + instance.expects(:execute).with(@args) + @klass.dispatch(@env, *@args) end end @@ -65,11 +65,7 @@ class CommandsBastTest < Test::Unit::TestCase end context "executing" do - should "raise an error if called (since not a subclass)" do - assert_raises(RuntimeError) { - @instance.execute([]) - } - end + # TODO end context "parsing options" do