Builder can now use other builders or merge other builders

This commit is contained in:
Mitchell Hashimoto 2010-07-06 20:08:36 -07:00
parent 29458061df
commit 3c943834ea
3 changed files with 68 additions and 5 deletions

View File

@ -31,15 +31,22 @@ module Vagrant
@stack ||= []
end
# Returns a mergeable version of the builder. If `use` is called with
# the return value of this method, then the stack will merge, instead
# of being treated as a separate single middleware.
def mergeable
[:merge, self]
end
# Adds a middleware class to the middleware stack. Any additional
# args and a block, if given, are saved and passed to the initializer
# of the middleware.
#
# @param [Class] middleware The middleware class
def use(middleware, *args, &block)
if middleware.kind_of?(Builder)
if middleware.kind_of?(Array) && middleware[0] == :merge
# Merge in the other builder's stack into our own
self.stack.concat(middleware.stack)
self.stack.concat(middleware[1].stack)
else
self.stack << [middleware, args, block]
end
@ -104,7 +111,23 @@ module Vagrant
# middleware.
items = items.collect do |item|
klass, args, block = item
lambda { |app| klass.new(app, env, *args, &block) }
lambda do |app|
if klass.is_a?(Class)
# A middleware klass which is to be instantiated with the
# app, env, and any arguments given
klass.new(app, env, *args, &block)
elsif klass.respond_to?(:call)
# Make it a lambda which calls the item then forwards
# up the chain
lambda do |e|
klass.call(e)
app.call(e)
end
else
raise "Invalid middleware: #{item.inspect}"
end
end
end
# Append the final step and convert into flattened call chain.

View File

@ -41,9 +41,26 @@ class ActionBuilderTest < Test::Unit::TestCase
end
@instance.use 1
@instance.use other
@instance.use other.mergeable
assert_equal 3, @instance.stack.length
end
should "not merge in another builder if not mergeable" do
other = @klass.new do
use 2
use 3
end
@instance.use 1
@instance.use other
assert_equal 2, @instance.stack.length
end
end
context "mergeable" do
should "return the merge format with the builder" do
assert_equal [:merge, @instance], @instance.mergeable
end
end
context "inserting" do
@ -131,12 +148,29 @@ class ActionBuilderTest < Test::Unit::TestCase
result = mock("result")
env = {:a => :b}
middleware = mock("middleware")
middleware.stubs(:is_a?).with(Class).returns(true)
middleware.expects(:new).with(anything, env).returns(result)
@instance.use middleware
result = @instance.to_app(env)
assert result.kind_of?(Vagrant::Action::ErrorHalt)
end
should "make non-classes lambdas" do
env = Vagrant::Action::Environment.new(nil)
env.expects(:foo).once
func = lambda { |x| x.foo }
@instance.use func
@instance.to_app(env).call(env)
end
should "raise exception if given invalid middleware" do
@instance.use 7
assert_raises(RuntimeError) {
@instance.to_app(nil)
}
end
# TODO: Better testing of this method
end

View File

@ -9,7 +9,7 @@ Gem::Specification.new do |s|
s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version=
s.authors = ["Mitchell Hashimoto", "John Bender"]
s.date = %q{2010-07-05}
s.date = %q{2010-07-06}
s.default_executable = %q{vagrant}
s.description = %q{Vagrant is a tool for building and distributing virtualized development environments.}
s.email = ["mitchell.hashimoto@gmail.com", "john.m.bender@gmail.com"]
@ -41,8 +41,10 @@ Gem::Specification.new do |s|
"lib/vagrant/action/vm/boot.rb",
"lib/vagrant/action/vm/check_guest_additions.rb",
"lib/vagrant/action/vm/customize.rb",
"lib/vagrant/action/vm/destroy.rb",
"lib/vagrant/action/vm/destroy_unused_network_interfaces.rb",
"lib/vagrant/action/vm/forward_ports.rb",
"lib/vagrant/action/vm/halt.rb",
"lib/vagrant/action/vm/import.rb",
"lib/vagrant/action/vm/match_mac_address.rb",
"lib/vagrant/action/vm/network.rb",
@ -135,8 +137,10 @@ Gem::Specification.new do |s|
"test/vagrant/action/vm/boot_test.rb",
"test/vagrant/action/vm/check_guest_additions_test.rb",
"test/vagrant/action/vm/customize_test.rb",
"test/vagrant/action/vm/destroy_test.rb",
"test/vagrant/action/vm/destroy_unused_network_interfaces_test.rb",
"test/vagrant/action/vm/forward_ports_test.rb",
"test/vagrant/action/vm/halt_test.rb",
"test/vagrant/action/vm/import_test.rb",
"test/vagrant/action/vm/match_mac_address_test.rb",
"test/vagrant/action/vm/network_test.rb",
@ -227,8 +231,10 @@ Gem::Specification.new do |s|
"test/vagrant/action/vm/boot_test.rb",
"test/vagrant/action/vm/check_guest_additions_test.rb",
"test/vagrant/action/vm/customize_test.rb",
"test/vagrant/action/vm/destroy_test.rb",
"test/vagrant/action/vm/destroy_unused_network_interfaces_test.rb",
"test/vagrant/action/vm/forward_ports_test.rb",
"test/vagrant/action/vm/halt_test.rb",
"test/vagrant/action/vm/import_test.rb",
"test/vagrant/action/vm/match_mac_address_test.rb",
"test/vagrant/action/vm/network_test.rb",