lib/bundler/definition.rb in bundler-2.3.27 vs lib/bundler/definition.rb in bundler-2.4.0
- old
+ new
@@ -14,11 +14,10 @@
attr_reader(
:dependencies,
:locked_deps,
:locked_gems,
:platforms,
- :requires,
:ruby_version,
:lockfile,
:gemfiles
)
@@ -144,15 +143,15 @@
end
@dependency_changes = converge_dependencies
@local_changes = converge_locals
- @requires = compute_requires
+ @incomplete_lockfile = check_missing_lockfile_specs
end
def gem_version_promoter
- @gem_version_promoter ||= GemVersionPromoter.new(@originally_locked_specs, @unlock[:gems])
+ @gem_version_promoter ||= GemVersionPromoter.new
end
def resolve_only_locally!
@remote = false
sources.local_only!
@@ -262,23 +261,23 @@
@resolve ||= if Bundler.frozen_bundle?
Bundler.ui.debug "Frozen, using resolution from the lockfile"
@locked_specs
elsif !unlocking? && nothing_changed?
if deleted_deps.any?
- Bundler.ui.debug("Some dependencies were deleted, using a subset of the resolution from the lockfile")
+ Bundler.ui.debug "Some dependencies were deleted, using a subset of the resolution from the lockfile"
SpecSet.new(filter_specs(@locked_specs, @dependencies - deleted_deps))
else
- Bundler.ui.debug("Found no changes, using resolution from the lockfile")
+ Bundler.ui.debug "Found no changes, using resolution from the lockfile"
if @locked_gems.may_include_redundant_platform_specific_gems?
SpecSet.new(filter_specs(@locked_specs, @dependencies))
else
@locked_specs
end
end
else
- Bundler.ui.debug("Found changes from the lockfile, re-resolving dependencies because #{change_reason}")
- resolver.start(expanded_dependencies)
+ Bundler.ui.debug "Found changes from the lockfile, re-resolving dependencies because #{change_reason}"
+ start_resolution
end
end
def spec_git_paths
sources.git_sources.map {|s| File.realpath(s.path) if File.exist?(s.path) }.compact
@@ -293,15 +292,15 @@
contents = to_lock
# Convert to \r\n if the existing lock has them
# i.e., Windows with `git config core.autocrlf=true`
- contents.gsub!(/\n/, "\r\n") if @lockfile_contents.match("\r\n")
+ contents.gsub!(/\n/, "\r\n") if @lockfile_contents.match?("\r\n")
if @locked_bundler_version
locked_major = @locked_bundler_version.segments.first
- current_major = Gem::Version.create(Bundler::VERSION).segments.first
+ current_major = Bundler.gem_version.segments.first
updating_major = locked_major < current_major
end
preserve_unknown_sections ||= !updating_major && (Bundler.frozen_bundle? || !(unlocking? || @unlocking_bundler))
@@ -459,11 +458,11 @@
attr_reader :sources
private :sources
def nothing_changed?
- !@source_changes && !@dependency_changes && !@new_platform && !@path_changes && !@local_changes
+ !@source_changes && !@dependency_changes && !@new_platform && !@path_changes && !@local_changes && !@incomplete_lockfile
end
def unlocking?
@unlocking
end
@@ -472,18 +471,35 @@
def resolver
@resolver ||= begin
last_resolve = converge_locked_specs
remove_ruby_from_platforms_if_necessary!(current_dependencies)
- Resolver.new(source_requirements, last_resolve, gem_version_promoter, additional_base_requirements_for_resolve(last_resolve), platforms)
+ Resolver.new(source_requirements, last_resolve, gem_version_promoter, additional_base_requirements_for_resolve(last_resolve))
end
end
def expanded_dependencies
@expanded_dependencies ||= dependencies + metadata_dependencies
end
+ def resolution_packages
+ @resolution_packages ||= begin
+ packages = Hash.new do |h, k|
+ h[k] = Resolver::Package.new(k, @platforms, @originally_locked_specs, @unlock[:gems])
+ end
+
+ expanded_dependencies.each do |dep|
+ name = dep.name
+ platforms = dep.gem_platforms(@platforms)
+
+ packages[name] = Resolver::Package.new(name, platforms, @originally_locked_specs, @unlock[:gems], :dependency => dep)
+ end
+
+ packages
+ end
+ end
+
def filter_specs(specs, deps)
SpecSet.new(specs).for(deps, false, platforms)
end
def materialize(dependencies)
@@ -505,25 +521,40 @@
end
raise GemNotFound, "Could not find #{missing_specs_list.join(" nor ")}"
end
+ incomplete_specs = specs.incomplete_specs
loop do
- incomplete_specs = specs.incomplete_specs
break if incomplete_specs.empty?
Bundler.ui.debug("The lockfile does not have all gems needed for the current platform though, Bundler will still re-resolve dependencies")
- @resolve = resolver.start(expanded_dependencies, :exclude_specs => incomplete_specs)
+ @resolve = start_resolution(:exclude_specs => incomplete_specs)
specs = resolve.materialize(dependencies)
+
+ still_incomplete_specs = specs.incomplete_specs
+
+ if still_incomplete_specs == incomplete_specs
+ package = resolution_packages[incomplete_specs.first.name]
+ resolver.raise_not_found! package
+ end
+
+ incomplete_specs = still_incomplete_specs
end
- bundler = sources.metadata_source.specs.search(Gem::Dependency.new("bundler", VERSION)).last
+ bundler = sources.metadata_source.specs.search(["bundler", Bundler.gem_version]).last
specs["bundler"] = bundler
specs
end
+ def start_resolution(exclude_specs: [])
+ result = resolver.start(expanded_dependencies, resolution_packages, :exclude_specs => exclude_specs)
+
+ SpecSet.new(SpecSet.new(result).for(dependencies, false, @platforms))
+ end
+
def precompute_source_requirements_for_indirect_dependencies?
@remote && sources.non_global_rubygems_sources.all?(&:dependency_api_available?) && !sources.aggregate_global_source?
end
def pin_locally_available_names(source_requirements)
@@ -572,10 +603,11 @@
[@source_changes, "the list of sources changed"],
[@dependency_changes, "the dependencies in your gemfile changed"],
[@new_platform, "you added a new platform to your gemfile"],
[@path_changes, "the gemspecs for path gems changed"],
[@local_changes, "the gemspecs for git local gems changed"],
+ [@incomplete_lockfile, "your lock file is missing some gems"],
].select(&:first).map(&:last).join(", ")
end
def pretty_dep(dep)
SharedHelpers.pretty_dependency(dep)
@@ -626,10 +658,18 @@
changed || specs_changed?(source)
end.map(&:first)
!sources_with_changes.each {|source| @unlock[:sources] << source.name }.empty?
end
+ def check_missing_lockfile_specs
+ all_locked_specs = @locked_specs.map(&:name) << "bundler"
+
+ @locked_specs.any? do |s|
+ s.dependencies.any? {|dep| !all_locked_specs.include?(dep.name) }
+ end
+ end
+
def converge_paths
sources.path_sources.any? do |source|
specs_changed?(source)
end
end
@@ -764,16 +804,17 @@
raise
end
new_spec = new_specs[s].first
-
- # If the spec is no longer in the path source, unlock it. This
- # commonly happens if the version changed in the gemspec
- next unless new_spec
-
- s.dependencies.replace(new_spec.dependencies)
+ if new_spec
+ s.dependencies.replace(new_spec.dependencies)
+ else
+ # If the spec is no longer in the path source, unlock it. This
+ # commonly happens if the version changed in the gemspec
+ @unlock[:gems] << s.name
+ end
end
if dep.nil? && requested_dependencies.find {|d| s.name == d.name }
@unlock[:gems] << s.name
else
@@ -835,20 +876,9 @@
whitespace_cleanup = /\n{2,}/
current = current.gsub(pattern, "\n").gsub(whitespace_cleanup, "\n\n").strip
proposed = proposed.gsub(pattern, "\n").gsub(whitespace_cleanup, "\n\n").strip
end
current == proposed
- end
-
- def compute_requires
- dependencies.reduce({}) do |requires, dep|
- next requires unless dep.should_include?
- requires[dep.name] = Array(dep.autorequire || dep.name).map do |file|
- # Allow `require: true` as an alias for `require: <name>`
- file == true ? dep.name : file
- end
- requires
- end
end
def additional_base_requirements_for_resolve(last_resolve)
return [] unless @locked_gems && unlocking? && !sources.expired_sources?(@locked_gems.sources)
converge_specs(@originally_locked_specs - last_resolve).map do |locked_spec|