From 3470d98fca867c51a80ec683474a169512d215bd Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Fri, 3 Sep 2010 14:58:27 -0700 Subject: [PATCH] Load the root path on demand. --- CHANGELOG.md | 1 + lib/vagrant/environment.rb | 36 +++++----- test/vagrant/environment_test.rb | 111 +++++++++++++------------------ 3 files changed, 63 insertions(+), 85 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c52232c5e..b5c05b376 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ ## 0.6.0 (unreleased) + - Fixed issue with not detecting Vagrantfile at root directory ("/"). - Vagrant now gives a nice error message if there is a syntax error in any Vagrantfile. [GH-154] - The format of the ".vagrant" file which stores persisted VMs has diff --git a/lib/vagrant/environment.rb b/lib/vagrant/environment.rb index 3ac118230..5fdbfaa30 100644 --- a/lib/vagrant/environment.rb +++ b/lib/vagrant/environment.rb @@ -14,7 +14,6 @@ module Vagrant attr_reader :vm_name # The name of the VM (internal name) which this environment represents attr_reader :cwd - attr_reader :root_path attr_reader :config attr_reader :box attr_accessor :vm @@ -173,6 +172,21 @@ module Vagrant @logger ||= Util::ResourceLogger.new(resource, self) end + # The root path is the path where the top-most (loaded last) + # Vagrantfile resides. It can be considered the project root for + # this environment. + def root_path + return @root_path if defined?(@root_path) + + root_finder = lambda do |path| + return path.to_s if File.exist?(File.join(path.to_s, ROOTFILE_NAME)) + return nil if path.root? + root_finder.call(path.parent) + end + + @root_path = root_finder.call(Pathname.new(cwd)) + end + #--------------------------------------------------------------- # Load Methods #--------------------------------------------------------------- @@ -181,7 +195,6 @@ module Vagrant # such as `vm`, `config`, etc. on this environment. The order this # method calls its other methods is very particular. def load! - load_root_path! load_config! load_home_directory! load_box! @@ -191,25 +204,6 @@ module Vagrant self end - # Loads the root path of this environment, given the starting - # directory (the "cwd" of this environment for lack of better words). - # This method allows an environment in `/foo` to be detected from - # `/foo/bar` (similar to how git works in subdirectories) - def load_root_path!(path=nil) - path = Pathname.new(File.expand_path(path || cwd)) - - # Stop if we're at the root. - return false if path.root? - - file = "#{path}/#{ROOTFILE_NAME}" - if File.exist?(file) - @root_path = path.to_s - return true - end - - load_root_path!(path.parent) - end - # Loads this environment's configuration and stores it in the {config} # variable. The configuration loaded by this method is specified to # this environment, meaning that it will use the given root directory diff --git a/test/vagrant/environment_test.rb b/test/vagrant/environment_test.rb index 69ab77860..bb82c9b2a 100644 --- a/test/vagrant/environment_test.rb +++ b/test/vagrant/environment_test.rb @@ -304,6 +304,53 @@ class EnvironmentTest < Test::Unit::TestCase end end + context "loading the root path" do + setup do + @env = mock_environment + @env.stubs(:cwd).returns("/foo") + end + + should "should walk the parent directories looking for rootfile" do + paths = [Pathname.new("/foo/bar/baz"), + Pathname.new("/foo/bar"), + Pathname.new("/foo"), + Pathname.new("/") + ] + + search_seq = sequence("search_seq") + paths.each do |path| + File.expects(:exist?).with(File.join(path.to_s, @klass::ROOTFILE_NAME)).returns(false).in_sequence(search_seq) + end + + @env.stubs(:cwd).returns(paths.first.to_s) + assert !@env.root_path + end + + should "should set the path for the rootfile" do + path = File.expand_path("/foo") + @env.stubs(:cwd).returns(path) + File.expects(:exist?).with(File.join(path, @klass::ROOTFILE_NAME)).returns(true) + + assert_equal path, @env.root_path + end + + should "only load the root path once" do + File.expects(:exist?).with(File.join(@env.cwd, @klass::ROOTFILE_NAME)).returns(true).once + + assert_equal @env.cwd, @env.root_path + assert_equal @env.cwd, @env.root_path + assert_equal @env.cwd, @env.root_path + end + + should "only load the root path once even if nil" do + File.expects(:exist?).twice.returns(false) + + assert @env.root_path.nil? + assert @env.root_path.nil? + assert @env.root_path.nil? + end + end + context "loading" do setup do @env = mock_environment @@ -312,7 +359,6 @@ class EnvironmentTest < Test::Unit::TestCase context "overall load method" do should "load! should call proper sequence and return itself" do call_seq = sequence("call_sequence") - @env.expects(:load_root_path!).once.in_sequence(call_seq) @env.expects(:load_config!).once.in_sequence(call_seq) @env.expects(:load_home_directory!).once.in_sequence(call_seq) @env.expects(:load_box!).once.in_sequence(call_seq) @@ -323,69 +369,6 @@ class EnvironmentTest < Test::Unit::TestCase end end - context "loading the root path" do - setup do - @env.stubs(:cwd).returns("/foo") - end - - should "default the path to the cwd instance var if nil" do - @path = mock("path") - @path.stubs(:root?).returns(true) - File.expects(:expand_path).with(@env.cwd).returns(@env.cwd) - Pathname.expects(:new).with(@env.cwd).returns(@path) - @env.load_root_path!(nil) - end - - should "not default the path to pwd if its not nil" do - @path = mock("path") - @path.stubs(:to_s).returns("/") - File.expects(:expand_path).with(@path).returns("/") - Pathname.expects(:new).with("/").returns(@path) - @path.stubs(:root?).returns(true) - @env.load_root_path!(@path) - end - - should "should walk the parent directories looking for rootfile" do - paths = [ - Pathname.new("/foo/bar/baz"), - Pathname.new("/foo/bar"), - Pathname.new("/foo") - ] - - search_seq = sequence("search_seq") - paths.each do |path| - # NOTE File.expect(:expand_path) causes tests to hang in windows below is the interim solution - File.expects(:exist?).with("#{File.expand_path(path)}/#{@klass::ROOTFILE_NAME}").returns(false).in_sequence(search_seq) - end - - assert !@env.load_root_path!(paths.first) - end - - should "return false if not found" do - path = Pathname.new("/") - assert !@env.load_root_path!(path) - end - - should "return false if not found on windows-style root" do - # TODO: Is there _any_ way to test this on unix machines? The - # expand path doesn't work [properly for the test] on unix machines. - if RUBY_PLATFORM.downcase.include?("mswin") - # Note the escaped back slash - path = Pathname.new("C:\\") - assert !@env.load_root_path!(path) - end - end - - should "should set the path for the rootfile" do - # NOTE File.expect(:expand_path) causes tests to hang in windows below is the interim solution - path = File.expand_path("/foo") - File.expects(:exist?).with("#{path}/#{@klass::ROOTFILE_NAME}").returns(true) - - assert @env.load_root_path!(Pathname.new(path)) - assert_equal path, @env.root_path - end - end - context "loading config" do setup do @root_path = "/foo"