core: BoxCollection can find with version constraints
This commit is contained in:
parent
77b5fa94b7
commit
4c1fa7359d
|
@ -229,42 +229,40 @@ module Vagrant
|
||||||
#
|
#
|
||||||
# @param [String] name Name of the box (logical name).
|
# @param [String] name Name of the box (logical name).
|
||||||
# @param [Array] providers Providers that the box implements.
|
# @param [Array] providers Providers that the box implements.
|
||||||
|
# @param [String] version Version constraints to adhere to. Example:
|
||||||
|
# "~> 1.0" or "= 1.0, ~> 1.1"
|
||||||
# @return [Box] The box found, or `nil` if not found.
|
# @return [Box] The box found, or `nil` if not found.
|
||||||
def find(name, providers)
|
def find(name, providers, version)
|
||||||
providers = [providers].flatten
|
providers = Array(providers)
|
||||||
|
|
||||||
|
# Build up the requirements we have
|
||||||
|
requirements = version.split(",").map do |v|
|
||||||
|
Gem::Requirement.new(v.strip)
|
||||||
|
end
|
||||||
|
|
||||||
with_collection_lock do
|
with_collection_lock do
|
||||||
providers.each do |provider|
|
box_directory = @directory.join(name)
|
||||||
# First look directly for the box we're asking for.
|
if !box_directory.directory?
|
||||||
box_directory = @directory.join(name, provider.to_s, "metadata.json")
|
@logger.info("Box not found: #{name} (#{providers.join(", ")})")
|
||||||
@logger.info("Searching for box: #{name} (#{provider}) in #{box_directory}")
|
return nil
|
||||||
if box_directory.file?
|
end
|
||||||
@logger.info("Box found: #{name} (#{provider})")
|
|
||||||
return Box.new(name, provider, box_directory.dirname)
|
box_directory.children(true).each do |versiondir|
|
||||||
|
version = versiondir.basename.to_s
|
||||||
|
if !requirements.all? { |r| r.satisfied_by?(Gem::Version.new(version)) }
|
||||||
|
# Unsatisfied version requirements
|
||||||
|
next
|
||||||
end
|
end
|
||||||
|
|
||||||
# If we're looking for a VirtualBox box, then we check if there is
|
providers.each do |provider|
|
||||||
# a V1 box.
|
provider_dir = versiondir.join(provider.to_s)
|
||||||
if provider.to_sym == :virtualbox
|
next if !provider_dir.directory?
|
||||||
# Check if a V1 version of this box exists, and if so, raise an
|
@logger.info("Box found: #{name} (#{provider})")
|
||||||
# exception notifying the caller that the box exists but needs
|
return Box.new(name, provider, provider_dir)
|
||||||
# to be upgraded. We don't do the upgrade here because it can be
|
|
||||||
# a fairly intensive activity and don't want to immediately degrade
|
|
||||||
# user performance on a find.
|
|
||||||
#
|
|
||||||
# To determine if it is a V1 box we just do a simple heuristic
|
|
||||||
# based approach.
|
|
||||||
@logger.info("Searching for V1 box: #{name}")
|
|
||||||
if v1_box?(@directory.join(name))
|
|
||||||
@logger.warn("V1 box found: #{name}")
|
|
||||||
raise Errors::BoxUpgradeRequired, :name => name
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Didn't find it, return nil
|
|
||||||
@logger.info("Box not found: #{name} (#{providers.join(", ")})")
|
|
||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -41,37 +41,45 @@ describe Vagrant::BoxCollection do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "finding" do
|
describe "#find" do
|
||||||
it "should return nil if the box does not exist" do
|
it "returns nil if the box does not exist" do
|
||||||
instance.find("foo", :i_dont_exist).should be_nil
|
expect(subject.find("foo", :i_dont_exist, ">= 0")).to be_nil
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should return a box if the box does exist" do
|
it "returns a box if the box does exist" do
|
||||||
# Create the "box"
|
# Create the "box"
|
||||||
environment.box2("foo", :virtualbox)
|
environment.box3("foo", "0", :virtualbox)
|
||||||
|
|
||||||
# Actual test
|
# Actual test
|
||||||
result = instance.find("foo", :virtualbox)
|
result = subject.find("foo", :virtualbox, ">= 0")
|
||||||
result.should_not be_nil
|
expect(result).to_not be_nil
|
||||||
result.should be_kind_of(box_class)
|
expect(result).to be_kind_of(box_class)
|
||||||
result.name.should == "foo"
|
expect(result.name).to eq("foo")
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should throw an exception if it is a v1 box" do
|
it "can satisfy complex constraints" do
|
||||||
# Create a V1 box
|
# Create the "box"
|
||||||
environment.box1("foo")
|
environment.box3("foo", "0.1", :virtualbox)
|
||||||
|
environment.box3("foo", "1.0", :virtualbox)
|
||||||
|
environment.box3("foo", "2.1", :virtualbox)
|
||||||
|
|
||||||
# Test!
|
# Actual test
|
||||||
expect { instance.find("foo", :virtualbox) }.
|
result = subject.find("foo", :virtualbox, ">= 0.9, < 1.5")
|
||||||
to raise_error(Vagrant::Errors::BoxUpgradeRequired)
|
expect(result).to_not be_nil
|
||||||
|
expect(result).to be_kind_of(box_class)
|
||||||
|
expect(result.name).to eq("foo")
|
||||||
|
# TODO: test version
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should return nil if there is a V1 box but we're looking for another provider" do
|
it "returns nil if a box's constraints can't be satisfied" do
|
||||||
# Create a V1 box
|
# Create the "box"
|
||||||
environment.box1("foo")
|
environment.box3("foo", "0.1", :virtualbox)
|
||||||
|
environment.box3("foo", "1.0", :virtualbox)
|
||||||
|
environment.box3("foo", "2.1", :virtualbox)
|
||||||
|
|
||||||
# Test
|
# Actual test
|
||||||
instance.find("foo", :another_provider).should be_nil
|
result = subject.find("foo", :virtualbox, "> 1.0, < 1.5")
|
||||||
|
expect(result).to be_nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue