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|