Builder supports action hooks

This commit is contained in:
Mitchell Hashimoto 2013-02-06 15:06:13 -08:00
parent 9251b880f5
commit d720205810
2 changed files with 60 additions and 11 deletions

View File

@ -17,6 +17,12 @@ module Vagrant
# Vagrant::Action.run(app) # Vagrant::Action.run(app)
# #
class Builder class Builder
# This is the stack of middlewares added. This should NOT be used
# directly.
#
# @return [Array]
attr_reader :stack
# This is a shortcut for a middleware sequence with only one item # This is a shortcut for a middleware sequence with only one item
# in it. For a description of the arguments and the documentation, please # in it. For a description of the arguments and the documentation, please
# see {#use} instead. # see {#use} instead.
@ -26,6 +32,18 @@ module Vagrant
new.use(middleware, *args, &block) new.use(middleware, *args, &block)
end end
def initialize
@stack = []
end
# Implement a custom copy that copies the stack variable over so that
# we don't clobber that.
def initialize_copy(original)
super
@stack = original.stack.dup
end
# Returns a mergeable version of the builder. If `use` is called with # Returns a mergeable version of the builder. If `use` is called with
# the return value of this method, then the stack will merge, instead # the return value of this method, then the stack will merge, instead
# of being treated as a separate single middleware. # of being treated as a separate single middleware.
@ -109,19 +127,27 @@ module Vagrant
# @param [Vagrant::Action::Environment] env The action environment # @param [Vagrant::Action::Environment] env The action environment
# @return [Object] A callable object # @return [Object] A callable object
def to_app(env) def to_app(env)
app_stack = nil
# If we have action hooks, then we apply them
if env[:action_hooks]
builder = self.dup
# Apply all the hooks to the new builder instance
env[:action_hooks].each do |hook|
hook.apply(builder)
end
# The stack is now the result of the new builder
app_stack = builder.stack.dup
end
# If we don't have a stack then default to using our own
app_stack ||= stack.dup
# Wrap the middleware stack with the Warden to provide a consistent # Wrap the middleware stack with the Warden to provide a consistent
# and predictable behavior upon exceptions. # and predictable behavior upon exceptions.
Warden.new(stack.dup, env) Warden.new(app_stack, env)
end
protected
# Returns the current stack of middlewares. You probably won't
# need to use this directly, and it's recommended that you don't.
#
# @return [Array]
def stack
@stack ||= []
end end
end end
end end

View File

@ -9,6 +9,13 @@ describe Vagrant::Action::Builder do
Proc.new { |env| env[:data] << data } Proc.new { |env| env[:data] << data }
end end
context "copying" do
it "should copy the stack" do
copy = subject.dup
copy.stack.object_id.should_not == subject.stack.object_id
end
end
context "build" do context "build" do
it "should provide build as a shortcut for basic sequences" do it "should provide build as a shortcut for basic sequences" do
data = {} data = {}
@ -170,4 +177,20 @@ describe Vagrant::Action::Builder do
data[:data].should == [2] data[:data].should == [2]
end end
end end
describe "action hooks" do
it "applies them properly" do
hook = double("hook")
hook.stub(:apply) do |builder|
builder.use appender_proc(2)
end
data[:action_hooks] = [hook]
subject.use appender_proc(1)
subject.call(data)
data[:data].should == [1, 2]
end
end
end end