Check dependency list on initialization

When initializing for internal plugin resolution inspect contraints
on all defined dependencies. If a prerelease constraint is detected,
automatically enable prerelease resolution.
This commit is contained in:
Chris Roberts 2020-11-06 08:01:42 -08:00
parent e9cae1a2f2
commit 18c1607c6e
4 changed files with 159 additions and 16 deletions

View File

@ -234,6 +234,8 @@ module Vagrant
Gem::Specification.reset
end
enable_prerelease!(specs: @initial_specifications)
solution_file = load_solution_file(opts)
@logger.debug("solution file in use for init: #{solution_file}")
@ -464,6 +466,30 @@ module Vagrant
protected
# This will enable prerelease if any of the root dependency constraints
# include prerelease versions
#
# @param [Array<Gem::Specification>] spec_list List of specifications
# @param [Gem::RequestSet] rs Request set of dependencies
def enable_prerelease!(specs: nil, request_set: nil)
pre = specs.detect do |spec|
spec.version.prerelease?
end if specs
if pre
@logger.debug("Enabling prerelease plugin resolution due to dependency: #{pre.full_name}")
ENV["VAGRANT_ALLOW_PRERELEASE"] = "1"
return
end
dep = request_set.dependencies.detect do |d|
d.prerelease?
end if request_set
if dep
@logger.debug("Enabling prerelease plugin resolution due to dependency: #{dep}")
ENV["VAGRANT_ALLOW_PRERELEASE"] = "1"
return
end
end
def internal_install(plugins, update, **extra)
update = {} if !update.is_a?(Hash)
skips = []
@ -550,6 +576,7 @@ module Vagrant
# Create the request set for the new plugins
request_set = Gem::RequestSet.new(*plugin_deps)
enable_prerelease!(request_set: request_set)
request_set.prerelease = Vagrant.prerelease?
installer_set = Gem::Resolver.compose_sets(
@ -740,7 +767,6 @@ module Vagrant
request.name == matcher["gem_name"]
end
if desired_activation_request && !desired_activation_request.full_spec.activated?
activation_request = desired_activation_request
@logger.warn("Found misordered activation request for #{desired_activation_request.full_name}. Moving to solution HEAD.")
solution.delete(desired_activation_request)
solution.unshift(desired_activation_request)
@ -813,7 +839,8 @@ module Vagrant
def find_all(req)
@specs.select do |spec|
allow_prerelease = spec.name == "vagrant" && Vagrant.prerelease?
allow_prerelease = Vagrant.allow_prerelease_dependencies? ||
spec.name == "vagrant" && Vagrant.prerelease?
req.match?(spec, allow_prerelease)
end.map do |spec|
Gem::Resolver::InstalledSpecification.new(self, spec)
@ -861,7 +888,7 @@ module Vagrant
##
# Loads a spec with the given +name+. +version+, +platform+ and +source+ are
# ignored.
def load_spec (name, version, platform, source)
def load_spec(name, version, platform, source)
version = Gem::Version.new(version) if !version.is_a?(Gem::Version)
@specs.fetch(name, []).detect{|s| s.name == name && s.version == version}
end

View File

@ -122,8 +122,15 @@ module Vagrant
#
# @return [Boolean]
def self.prerelease?
!!ENV["VAGRANT_ALLOW_PRERELEASE"] ||
Gem::Version.new(Vagrant::VERSION).prerelease?
Gem::Version.new(Vagrant::VERSION).prerelease?
end
# This returns true/false if the Vagrant should allow prerelease
# versions when resolving plugin dependency constraints
#
# @return [Boolean]
def self.allow_prerelease_dependencies?
!!ENV["VAGRANT_ALLOW_PRERELEASE"]
end
# This allows control over dependency resolution when installing

View File

@ -618,6 +618,117 @@ describe Vagrant::Bundler do
end
end
end
describe "#enable_prerelease!" do
before do
@_ev = ENV.delete("VAGRANT_ALLOW_PRERELEASE")
end
after do
ENV["VAGRANT_ALLOW_PRERELEASE"] = @_ev
end
context "with specification list" do
let(:specifications) { [] }
it "should not modify prerelease by default" do
subject.send(:enable_prerelease!, specs: specifications)
expect(ENV["VAGRANT_ALLOW_PRERELEASE"]).to be_falsey
end
it "should not have enabled allow prerelease dependencies" do
subject.send(:enable_prerelease!, specs: specifications)
expect(Vagrant.allow_prerelease_dependencies?).to be_falsey
end
context "when specifications do not contain prerelease versions" do
let(:specifications) { [
double("spec1", full_name: "spec1", version: double("version1", prerelease?: false)),
double("spec2", full_name: "spec2", version: double("version2", prerelease?: false)),
double("spec3", full_name: "spec3", version: double("version3", prerelease?: false))
] }
it "should not modify prerelease" do
subject.send(:enable_prerelease!, specs: specifications)
expect(ENV["VAGRANT_ALLOW_PRERELEASE"]).to be_falsey
end
it "should not have enabled allow prerelease dependencies" do
subject.send(:enable_prerelease!, specs: specifications)
expect(Vagrant.allow_prerelease_dependencies?).to be_falsey
end
end
context "when specifications contain prerelease versions" do
let(:specifications) { [
double("spec1", full_name: "spec1", version: double("version1", prerelease?: false)),
double("spec2", full_name: "spec2", version: double("version2", prerelease?: true)),
double("spec3", full_name: "spec3", version: double("version3", prerelease?: false))
] }
it "should enable prerelease" do
subject.send(:enable_prerelease!, specs: specifications)
expect(ENV["VAGRANT_ALLOW_PRERELEASE"]).to be_truthy
end
it "should have enabled allow prerelease dependencies" do
subject.send(:enable_prerelease!, specs: specifications)
expect(Vagrant.allow_prerelease_dependencies?).to be_truthy
end
end
end
context "with request set" do
let(:request_set) { double("request_set", dependencies: dependencies) }
let(:dependencies) { [] }
it "should not modify prerelease by default" do
subject.send(:enable_prerelease!, request_set: request_set)
expect(ENV["VAGRANT_ALLOW_PRERELEASE"]).to be_falsey
end
it "should not have enabled allow prerelease dependencies" do
subject.send(:enable_prerelease!, request_set: request_set)
expect(Vagrant.allow_prerelease_dependencies?).to be_falsey
end
context "when specifications do not contain prerelease versions" do
let(:dependencies) { [
double("dep1", prerelease?: false, to_s: nil),
double("dep2", prerelease?: false, to_s: nil),
double("dep3", prerelease?: false, to_s: nil)
] }
it "should not modify prerelease" do
subject.send(:enable_prerelease!, request_set: request_set)
expect(ENV["VAGRANT_ALLOW_PRERELEASE"]).to be_falsey
end
it "should not have enabled allow prerelease dependencies" do
subject.send(:enable_prerelease!, request_set: request_set)
expect(Vagrant.allow_prerelease_dependencies?).to be_falsey
end
end
context "when specifications contain prerelease versions" do
let(:dependencies) { [
double("dep1", prerelease?: false, to_s: nil),
double("dep2", prerelease?: true, to_s: nil),
double("dep3", prerelease?: false, to_s: nil)
] }
it "should enable prerelease" do
subject.send(:enable_prerelease!, request_set: request_set)
expect(ENV["VAGRANT_ALLOW_PRERELEASE"]).to be_truthy
end
it "should have enabled allow prerelease dependencies" do
subject.send(:enable_prerelease!, request_set: request_set)
expect(Vagrant.allow_prerelease_dependencies?).to be_truthy
end
end
end
end
end
describe Vagrant::Bundler::PluginSet do

View File

@ -142,24 +142,22 @@ describe Vagrant do
stub_const("Vagrant::VERSION", "1.0.0")
expect(subject.prerelease?).to be(false)
end
end
describe ".allow_prerelease_dependencies?" do
context "with environment variable set" do
before { allow(ENV).to receive(:[]).with("VAGRANT_ALLOW_PRERELEASE").and_return("1") }
context "when version is development version" do
before { stub_const("Vagrant::VERSION", "1.0.0.dev") }
it "should return true" do
expect(subject.prerelease?).to be(true)
end
it "should return true" do
expect(subject.allow_prerelease_dependencies?).to be(true)
end
end
context "when version is non-development version" do
before { stub_const("Vagrant::VERSION", "1.0.0") }
context "with environment variable unset" do
before { allow(ENV).to receive(:[]).with("VAGRANT_ALLOW_PRERELEASE").and_return(nil) }
it "should return true" do
expect(subject.prerelease?).to be(true)
end
it "should return false" do
expect(subject.allow_prerelease_dependencies?).to be(false)
end
end
end