diff --git a/lib/vagrant/action/builtin/box_add.rb b/lib/vagrant/action/builtin/box_add.rb index f48020d24..154673042 100644 --- a/lib/vagrant/action/builtin/box_add.rb +++ b/lib/vagrant/action/builtin/box_add.rb @@ -21,6 +21,7 @@ module Vagrant @download_interrupted = false provider = env[:box_provider] + provider = Array(provider) if provider url = env[:box_url] version = env[:box_version] @@ -34,26 +35,29 @@ module Vagrant end end - # TODO: provider that is in an earlier version - # TODO: multiple providers - metadata_version = metadata.version(version || ">= 0") + metadata_version = metadata.version( + version || ">= 0", provider: provider) if !metadata_version - raise Errors::BoxAddNoMatchingVersion, - constraints: version || ">= 0", - url: url, - versions: metadata.versions.join(", ") + if !provider + raise Errors::BoxAddNoMatchingVersion, + constraints: version || ">= 0", + url: url, + versions: metadata.versions.join(", ") + else + # TODO: show supported providers + raise Errors::BoxAddNoMatchingProvider, + requested: provider, + url: url + end end metadata_provider = nil if provider # If a provider was specified, make sure we get that specific # version. - metadata_provider = metadata_version.provider(provider) - if !metadata_provider - raise Errors::BoxAddNoMatchingProvider, - providers: metadata_version.providers.join(", "), - requested: provider, - url: url + provider.each do |p| + metadata_provider = metadata_version.provider(p) + break if metadata_provider end elsif metadata_version.providers.length == 1 # If we have only one provider in the metadata, just use that diff --git a/templates/locales/en.yml b/templates/locales/en.yml index 5106aab2c..6744e2768 100644 --- a/templates/locales/en.yml +++ b/templates/locales/en.yml @@ -219,7 +219,6 @@ en: Box: %{url} Requested provider: %{requested} - Available providers: %{providers} box_add_no_matching_version: |- The box you're attempting to add has no available version that matches the constraints you requested. Please double-check your diff --git a/test/unit/vagrant/action/builtin/box_add_test.rb b/test/unit/vagrant/action/builtin/box_add_test.rb index 19a850b5f..e9fcb53c5 100644 --- a/test/unit/vagrant/action/builtin/box_add_test.rb +++ b/test/unit/vagrant/action/builtin/box_add_test.rb @@ -109,6 +109,52 @@ describe Vagrant::Action::Builtin::BoxAdd do subject.call(env) end + it "adds the latest version of a box with the specified provider, even if not latest" do + box_path = iso_env.box2_file(:vmware) + tf = Tempfile.new("vagrant").tap do |f| + f.write(<<-RAW) + { + "name": "foo/bar", + "versions": [ + { + "version": "0.5" + }, + { + "version": "0.7", + "providers": [ + { + "name": "virtualbox", + "url": "#{iso_env.box2_file(:virtualbox)}" + }, + { + "name": "vmware", + "url": "#{box_path}" + } + ] + }, + { + "version": "1.5" + } + ] + } + RAW + f.close + end + + env[:box_url] = tf.path + env[:box_provider] = "vmware" + box_collection.should_receive(:add).with do |path, name, version| + expect(checksum(path)).to eq(checksum(box_path)) + expect(name).to eq("foo/bar") + expect(version).to eq("0.7") + true + end + + app.should_receive(:call).with(env) + + subject.call(env) + end + it "adds the constrained version of a box with the only provider" do box_path = iso_env.box2_file(:vmware) tf = Tempfile.new("vagrant").tap do |f| @@ -188,6 +234,51 @@ describe Vagrant::Action::Builtin::BoxAdd do subject.call(env) end + it "adds the latest version of a box with any specified provider" do + box_path = iso_env.box2_file(:vmware) + tf = Tempfile.new("vagrant").tap do |f| + f.write(<<-RAW) + { + "name": "foo/bar", + "versions": [ + { + "version": "0.5", + "providers": [ + { + "name": "virtualbox", + "url": "#{iso_env.box2_file(:virtualbox)}" + } + ] + }, + { + "version": "0.7", + "providers": [ + { + "name": "vmware", + "url": "#{box_path}" + } + ] + } + ] + } + RAW + f.close + end + + env[:box_url] = tf.path + env[:box_provider] = ["virtualbox", "vmware"] + box_collection.should_receive(:add).with do |path, name, version| + expect(checksum(path)).to eq(checksum(box_path)) + expect(name).to eq("foo/bar") + expect(version).to eq("0.7") + true + end + + app.should_receive(:call).with(env) + + subject.call(env) + end + it "raises an exception if no matching version" do box_path = iso_env.box2_file(:vmware) tf = Tempfile.new("vagrant").tap do |f|