diff --git a/lib/vagrant/action/builtin/lock.rb b/lib/vagrant/action/builtin/lock.rb index 260645e69..23e7a3ed7 100644 --- a/lib/vagrant/action/builtin/lock.rb +++ b/lib/vagrant/action/builtin/lock.rb @@ -13,6 +13,8 @@ module Vagrant def call(env) lock_path = @options[:path] + lock_path = lock_path.call(env) if lock_path.is_a?(Proc) + env_key = "has_lock_#{lock_path}" if !env[env_key] @@ -24,7 +26,9 @@ module Vagrant # succeeds it returns a 0, so we must explicitly check for # the proper error case. if f.flock(File::LOCK_EX | File::LOCK_NB) === false - raise @options[:exception] + exception = @options[:exception] + exception = exception.call(env) if exception.is_a?(Proc) + raise exception end # Set that we gained the lock and call deeper into the diff --git a/test/unit/vagrant/action/builtin/lock_test.rb b/test/unit/vagrant/action/builtin/lock_test.rb index 44356cb18..35f0b9720 100644 --- a/test/unit/vagrant/action/builtin/lock_test.rb +++ b/test/unit/vagrant/action/builtin/lock_test.rb @@ -29,6 +29,37 @@ describe Vagrant::Action::Builtin::Lock do to_not raise_error end + it "should allow the path to be a proc" do + inner_acquire = true + app = lambda do |env| + File.open(lock_path, "w+") do |f| + inner_acquire = f.flock(File::LOCK_EX | File::LOCK_NB) + end + end + + options[:path] = lambda { |env| lock_path } + + instance = described_class.new(app, env, options) + instance.call(env) + + inner_acquire.should == false + end + + it "should allow the exception to be a proc" do + exception = options[:exception] + options[:exception] = lambda { |env| exception } + + File.open(lock_path, "w+") do |f| + # Acquire lock + f.flock(File::LOCK_EX | File::LOCK_NB).should == 0 + + # Test! + instance = described_class.new(app, env, options) + expect { instance.call(env) }. + to raise_error(exception) + end + end + it "should call the middleware with the lock held" do inner_acquire = true app = lambda do |env|