Always apply builtin constraints within dependency restrictions
Include detection of running context (within Bundler or not) and load the "buitin" gems based on that context.
This commit is contained in:
parent
53b9f1747c
commit
a51949933f
|
@ -52,7 +52,6 @@ module Vagrant
|
||||||
begin
|
begin
|
||||||
# Compose set for resolution
|
# Compose set for resolution
|
||||||
composed_set = generate_vagrant_set
|
composed_set = generate_vagrant_set
|
||||||
@logger.debug("Composed local RubyGems set for plugin init resolution: #{composed_set}")
|
|
||||||
# Resolve the request set to ensure proper activation order
|
# Resolve the request set to ensure proper activation order
|
||||||
solution = request_set.resolve(composed_set)
|
solution = request_set.resolve(composed_set)
|
||||||
rescue Gem::UnsatisfiableDependencyError => failure
|
rescue Gem::UnsatisfiableDependencyError => failure
|
||||||
|
@ -128,6 +127,7 @@ module Vagrant
|
||||||
|
|
||||||
# Clean removes any unused gems.
|
# Clean removes any unused gems.
|
||||||
def clean(plugins)
|
def clean(plugins)
|
||||||
|
@logger.debug("Cleaning Vagrant plugins of stale gems.")
|
||||||
# Generate dependencies for all registered plugins
|
# Generate dependencies for all registered plugins
|
||||||
plugin_deps = plugins.map do |name, info|
|
plugin_deps = plugins.map do |name, info|
|
||||||
gem_version = info['installed_gem_version']
|
gem_version = info['installed_gem_version']
|
||||||
|
@ -136,6 +136,8 @@ module Vagrant
|
||||||
Gem::Dependency.new(name, gem_version)
|
Gem::Dependency.new(name, gem_version)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@logger.debug("Current plugin dependency list: #{plugin_deps}")
|
||||||
|
|
||||||
# Load dependencies into a request set for resolution
|
# Load dependencies into a request set for resolution
|
||||||
request_set = Gem::RequestSet.new(*plugin_deps)
|
request_set = Gem::RequestSet.new(*plugin_deps)
|
||||||
# Never allow dependencies to be remotely satisfied during cleaning
|
# Never allow dependencies to be remotely satisfied during cleaning
|
||||||
|
@ -151,6 +153,8 @@ module Vagrant
|
||||||
Gem::Specification.load(spec_path)
|
Gem::Specification.load(spec_path)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@logger.debug("Generating current plugin state solution set.")
|
||||||
|
|
||||||
# Resolve the request set to ensure proper activation order
|
# Resolve the request set to ensure proper activation order
|
||||||
solution = request_set.resolve(current_set)
|
solution = request_set.resolve(current_set)
|
||||||
solution_specs = solution.map(&:full_spec)
|
solution_specs = solution.map(&:full_spec)
|
||||||
|
@ -228,20 +232,31 @@ module Vagrant
|
||||||
request_set = Gem::RequestSet.new(*plugin_deps)
|
request_set = Gem::RequestSet.new(*plugin_deps)
|
||||||
|
|
||||||
# Generate all existing deps within the "vagrant system"
|
# Generate all existing deps within the "vagrant system"
|
||||||
existing_deps = Gem::Specification.find_all{true}.map do |item|
|
existing_deps = vagrant_internal_specs.map do |item|
|
||||||
|
@logger.debug("Activating builtin specification: #{item.full_name}")
|
||||||
Gem::Dependency.new(item.name, item.version)
|
Gem::Dependency.new(item.name, item.version)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@logger.debug("Required constraints from builtin gems: #{existing_deps}")
|
||||||
|
|
||||||
# Import constraints into the request set to prevent installing
|
# Import constraints into the request set to prevent installing
|
||||||
# gems that are incompatible with the core system
|
# gems that are incompatible with the core system
|
||||||
request_set.import(existing_deps)
|
request_set.import(existing_deps)
|
||||||
|
|
||||||
installer_set = Gem::Resolver.compose_sets(installer_set, generate_plugin_set(skips))
|
installer_set = Gem::Resolver.compose_sets(
|
||||||
|
installer_set,
|
||||||
|
generate_builtin_set,
|
||||||
|
generate_plugin_set(skips)
|
||||||
|
)
|
||||||
|
|
||||||
|
@logger.debug("Generating solution set for installation.")
|
||||||
|
|
||||||
# Generate the required solution set for new plugins
|
# Generate the required solution set for new plugins
|
||||||
solution = request_set.resolve(installer_set)
|
solution = request_set.resolve(installer_set)
|
||||||
activate_solution(solution)
|
activate_solution(solution)
|
||||||
|
|
||||||
|
@logger.debug("Installing required gems.")
|
||||||
|
|
||||||
# Install all remote gems into plugin path. Set the installer to ignore dependencies
|
# Install all remote gems into plugin path. Set the installer to ignore dependencies
|
||||||
# as we know the dependencies are satisfied and it will attempt to validate a gem's
|
# as we know the dependencies are satisfied and it will attempt to validate a gem's
|
||||||
# dependencies are satisified by gems in the install directory (which will likely not
|
# dependencies are satisified by gems in the install directory (which will likely not
|
||||||
|
@ -256,9 +271,32 @@ module Vagrant
|
||||||
Gem::Resolver.compose_sets(generate_builtin_set, generate_plugin_set)
|
Gem::Resolver.compose_sets(generate_builtin_set, generate_plugin_set)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# @return [Array<[Gem::Specification, String]>] spec and directory pairs
|
||||||
|
def vagrant_internal_specs
|
||||||
|
list = {}
|
||||||
|
directories = [Gem::Specification.default_specifications_dir]
|
||||||
|
Gem::Specification.find_all{true}.each do |spec|
|
||||||
|
list[spec.full_name] = spec
|
||||||
|
end
|
||||||
|
directories += Gem::Specification.dirs.find_all do |path|
|
||||||
|
!path.start_with?(Gem.user_dir)
|
||||||
|
end
|
||||||
|
Gem::Specification.each_spec(directories) do |spec|
|
||||||
|
if !list[spec.full_name]
|
||||||
|
list[spec.full_name] = spec
|
||||||
|
end
|
||||||
|
end
|
||||||
|
list.values
|
||||||
|
end
|
||||||
|
|
||||||
# Generate the builtin resolver set
|
# Generate the builtin resolver set
|
||||||
def generate_builtin_set
|
def generate_builtin_set
|
||||||
Gem::Resolver::CurrentSet.new
|
builtin_set = BuiltinSet.new
|
||||||
|
@logger.debug("Generating new builtin set instance.")
|
||||||
|
vagrant_internal_specs.each do |spec|
|
||||||
|
builtin_set.add_builtin_spec(spec)
|
||||||
|
end
|
||||||
|
builtin_set
|
||||||
end
|
end
|
||||||
|
|
||||||
# Generate the plugin resolver set. Optionally provide specification names (short or
|
# Generate the plugin resolver set. Optionally provide specification names (short or
|
||||||
|
@ -312,6 +350,30 @@ module Vagrant
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# This is a custom Gem::Resolver::Set for use with vagrant "system" gems. It
|
||||||
|
# allows the installed set of gems to be used for providing a solution while
|
||||||
|
# enforcing strict constraints. This ensures that plugins cannot "upgrade"
|
||||||
|
# gems that are builtin to vagrant itself.
|
||||||
|
class BuiltinSet < Gem::Resolver::Set
|
||||||
|
def initialize
|
||||||
|
super
|
||||||
|
@remote = false
|
||||||
|
@specs = []
|
||||||
|
end
|
||||||
|
|
||||||
|
def add_builtin_spec(spec)
|
||||||
|
@specs.push(spec).uniq!
|
||||||
|
end
|
||||||
|
|
||||||
|
def find_all(req)
|
||||||
|
@specs.select do |spec|
|
||||||
|
req.match?(spec)
|
||||||
|
end.map do |spec|
|
||||||
|
Gem::Resolver::InstalledSpecification.new(self, spec)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# This is a custom Gem::Resolver::Set for use with Vagrant plugins. It is
|
# This is a custom Gem::Resolver::Set for use with Vagrant plugins. It is
|
||||||
# a modified Gem::Resolver::VendorSet that supports multiple versions of
|
# a modified Gem::Resolver::VendorSet that supports multiple versions of
|
||||||
# a specific gem
|
# a specific gem
|
||||||
|
|
Loading…
Reference in New Issue