From f203c29fbbd681b06f44851e534ad9a6b6109216 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sun, 7 Apr 2013 14:17:40 -0700 Subject: [PATCH] Builders are merged when using hooks. [GH-1555] --- CHANGELOG.md | 2 ++ lib/vagrant/action/builder.rb | 9 +++++- test/unit/vagrant/action/builder_test.rb | 38 +++++++++++++++++++++++- 3 files changed, 47 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 27ea259bf..989ea1efa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -58,6 +58,8 @@ BUG FIXES: for VirtualBox shared folders. - Output the proper clear line text for shells in Cygwin when reporting dynamic progress. + - When using `Builder` instances for hooks, the builders will be + merged for the proper before/after chain. [GH-1555] ## 1.1.6 (April 3, 2013) diff --git a/lib/vagrant/action/builder.rb b/lib/vagrant/action/builder.rb index 95fa96267..aaf94d7ce 100644 --- a/lib/vagrant/action/builder.rb +++ b/lib/vagrant/action/builder.rb @@ -74,7 +74,14 @@ module Vagrant def insert(index, middleware, *args, &block) index = self.index(index) unless index.is_a?(Integer) raise "no such middleware to insert before: #{index.inspect}" unless index - stack.insert(index, [middleware, args, block]) + + if middleware.kind_of?(Builder) + middleware.stack.reverse.each do |stack_item| + stack.insert(index, stack_item) + end + else + stack.insert(index, [middleware, args, block]) + end end alias_method :insert_before, :insert diff --git a/test/unit/vagrant/action/builder_test.rb b/test/unit/vagrant/action/builder_test.rb index 474dc5642..50d80eb37 100644 --- a/test/unit/vagrant/action/builder_test.rb +++ b/test/unit/vagrant/action/builder_test.rb @@ -6,7 +6,14 @@ describe Vagrant::Action::Builder do # This returns a proc that can be used with the builder # that simply appends data to an array in the env. def appender_proc(data) - Proc.new { |env| env[:data] << data } + result = Proc.new { |env| env[:data] << data } + + # Define a to_s on it for helpful output + result.define_singleton_method(:to_s) do + "" + end + + result end context "copying" do @@ -119,6 +126,35 @@ describe Vagrant::Action::Builder do data[:data].should == [1, 2, 3] end + it "merges middleware stacks of other builders" do + wrapper_class = Proc.new do |letter| + Class.new do + def initialize(app, env) + @app = app + end + + define_method(:call) do |env| + env[:data] << "#{letter}1" + @app.call(env) + env[:data] << "#{letter}2" + end + end + end + + proc2 = appender_proc(2) + subject.use appender_proc(1) + subject.use proc2 + + builder = described_class.new + builder.use wrapper_class.call("A") + builder.use wrapper_class.call("B") + + subject.insert(proc2, builder) + subject.call(data) + + data[:data].should == [1, "A1", "B1", 2, "B2", "A2"] + end + it "raises an exception if an invalid object given for insert" do expect { subject.insert "object", appender_proc(1) }. to raise_error(RuntimeError)