diff --git a/lib/vagrant/action/builder.rb b/lib/vagrant/action/builder.rb index 23d099a5d..5e21adb5c 100644 --- a/lib/vagrant/action/builder.rb +++ b/lib/vagrant/action/builder.rb @@ -17,6 +17,12 @@ module Vagrant # Vagrant::Action.run(app) # 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 # in it. For a description of the arguments and the documentation, please # see {#use} instead. @@ -26,6 +32,18 @@ module Vagrant new.use(middleware, *args, &block) 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 # the return value of this method, then the stack will merge, instead # of being treated as a separate single middleware. @@ -109,19 +127,27 @@ module Vagrant # @param [Vagrant::Action::Environment] env The action environment # @return [Object] A callable object 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 # and predictable behavior upon exceptions. - Warden.new(stack.dup, 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 ||= [] + Warden.new(app_stack, env) end end end diff --git a/test/unit/vagrant/action/builder_test.rb b/test/unit/vagrant/action/builder_test.rb index b3d65410b..a4fed47d5 100644 --- a/test/unit/vagrant/action/builder_test.rb +++ b/test/unit/vagrant/action/builder_test.rb @@ -9,6 +9,13 @@ describe Vagrant::Action::Builder do Proc.new { |env| env[:data] << data } 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 it "should provide build as a shortcut for basic sequences" do data = {} @@ -170,4 +177,20 @@ describe Vagrant::Action::Builder do data[:data].should == [2] 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