From 2c1da9566c54b8bcf07c330605388210ed1156b8 Mon Sep 17 00:00:00 2001 From: John Bender Date: Fri, 23 Jul 2010 23:57:02 -0700 Subject: [PATCH] first pass at the action warden, currently just reproducing basic rack functionality --- lib/vagrant/action/builder.rb | 27 ++-------------------- lib/vagrant/action/warden.rb | 36 +++++++++++++++++++++++++++++ test/vagrant/action/builder_test.rb | 2 +- 3 files changed, 39 insertions(+), 26 deletions(-) create mode 100644 lib/vagrant/action/warden.rb diff --git a/lib/vagrant/action/builder.rb b/lib/vagrant/action/builder.rb index 2da948214..b006b15f5 100644 --- a/lib/vagrant/action/builder.rb +++ b/lib/vagrant/action/builder.rb @@ -112,34 +112,11 @@ module Vagrant def to_app(env) # Prepend the error halt task so errneous environments are halted # before the chain even begins. - items = stack.dup.unshift([Env::ErrorHalt, [], nil]) + middleware = stack.dup.push([Env::ErrorHalt, [], nil]) # Convert each middleware into a lambda which takes the next # middleware. - items = items.collect do |item| - klass, args, block = item - - 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. - items << lambda { |env| } - items[0...-1].reverse.inject(items.last) { |a,e| e.call(a) } + Vagrant::Action::Warden.new(middleware, env) end # Runs the builder stack with the given environment. diff --git a/lib/vagrant/action/warden.rb b/lib/vagrant/action/warden.rb new file mode 100644 index 000000000..18159a3b5 --- /dev/null +++ b/lib/vagrant/action/warden.rb @@ -0,0 +1,36 @@ +module Vagrant + class Action + class Warden + attr_accessor :actions + + def initialize(middleware, env) + @stack = [] + @actions = middleware.map { |m| finalize_middleware(m, env) }.reverse + end + + def call(env) + return if @actions.empty? + @stack.push(@actions.pop).last.call(env) + end + + def finalize_middleware(middleware, env) + klass, args, block = middleware + + if klass.is_a?(Class) + # A middleware klass which is to be instantiated with the + # app, env, and any arguments given + klass.new(self, 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) + self.call(e) + end + else + raise "Invalid middleware: #{middleware.inspect}" + end + end + end + end +end diff --git a/test/vagrant/action/builder_test.rb b/test/vagrant/action/builder_test.rb index c766fa516..c8f4897a1 100644 --- a/test/vagrant/action/builder_test.rb +++ b/test/vagrant/action/builder_test.rb @@ -166,7 +166,7 @@ class ActionBuilderTest < Test::Unit::TestCase middleware.stubs(:is_a?).with(Class).returns(true) middleware.expects(:new).with(anything, env).returns(result) @instance.use middleware - result = @instance.to_app(env) + result = @instance.to_app(env).actions.first assert result.kind_of?(Vagrant::Action::Env::ErrorHalt) end