lib/bundler/definition.rb in bundler-2.4.14 vs lib/bundler/definition.rb in bundler-2.4.15

- old
+ new

@@ -74,12 +74,15 @@ @ruby_version = ruby_version @gemfiles = gemfiles @lockfile = lockfile @lockfile_contents = String.new + @locked_bundler_version = nil - @locked_ruby_version = nil + @resolved_bundler_version = nil + + @locked_ruby_version = nil @new_platform = nil @removed_platform = nil if lockfile && File.exist?(lockfile) @lockfile_contents = Bundler.read_file(lockfile) @@ -144,11 +147,11 @@ end @dependency_changes = converge_dependencies @local_changes = converge_locals - @incomplete_lockfile = check_missing_lockfile_specs + @missing_lockfile_dep = check_missing_lockfile_dep end def gem_version_promoter @gem_version_promoter ||= GemVersionPromoter.new end @@ -232,10 +235,18 @@ def requested_dependencies dependencies_for(requested_groups) end def current_dependencies + filter_relevant(dependencies) + end + + def current_locked_dependencies + filter_relevant(locked_dependencies) + end + + def filter_relevant(dependencies) dependencies.select do |d| d.should_include? && !d.gem_platforms([generic_local_platform]).empty? end end @@ -271,11 +282,11 @@ # @return [SpecSet] resolved dependencies def resolve @resolve ||= if Bundler.frozen_bundle? Bundler.ui.debug "Frozen, using resolution from the lockfile" @locked_specs - elsif !unlocking? && nothing_changed? + elsif no_resolve_needed? if deleted_deps.any? 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" @@ -308,11 +319,11 @@ # i.e., Windows with `git config core.autocrlf=true` contents.gsub!(/\n/, "\r\n") if @lockfile_contents.match?("\r\n") if @locked_bundler_version locked_major = @locked_bundler_version.segments.first - current_major = Bundler.gem_version.segments.first + current_major = bundler_version_to_lock.segments.first updating_major = locked_major < current_major end preserve_unknown_sections ||= !updating_major && (Bundler.frozen_bundle? || !(unlocking? || @unlocking_bundler)) @@ -348,29 +359,20 @@ end version end end + def bundler_version_to_lock + @resolved_bundler_version || Bundler.gem_version + end + def to_lock require_relative "lockfile_generator" LockfileGenerator.generate(self) end def ensure_equivalent_gemfile_and_lockfile(explicit_flag = false) - msg = String.new - msg << "You are trying to install in deployment mode after changing\n" \ - "your Gemfile. Run `bundle install` elsewhere and add the\n" \ - "updated #{Bundler.default_lockfile.relative_path_from(SharedHelpers.pwd)} to version control." - - unless explicit_flag - suggested_command = unless Bundler.settings.locations("frozen").keys.include?(:env) - "bundle config set frozen false" - end - msg << "\n\nIf this is a development machine, remove the #{Bundler.default_gemfile} " \ - "freeze \nby running `#{suggested_command}`." if suggested_command - end - added = [] deleted = [] changed = [] new_platforms = @platforms - @locked_platforms @@ -380,18 +382,13 @@ added.concat new_deps.map {|d| "* #{pretty_dep(d)}" } if new_deps.any? deleted.concat deleted_deps.map {|d| "* #{pretty_dep(d)}" } if deleted_deps.any? both_sources = Hash.new {|h, k| h[k] = [] } - @dependencies.each {|d| both_sources[d.name][0] = d } + current_dependencies.each {|d| both_sources[d.name][0] = d } + current_locked_dependencies.each {|d| both_sources[d.name][1] = d } - locked_dependencies.each do |d| - next if !Bundler.feature_flag.bundler_3_mode? && @locked_specs[d.name].empty? - - both_sources[d.name][1] = d - end - both_sources.each do |name, (dep, lock_dep)| next if dep.nil? || lock_dep.nil? gemfile_source = dep.source || sources.default_source lock_source = lock_dep.source || sources.default_source @@ -401,16 +398,25 @@ lockfile_source_name = lock_dep.source ? lock_source.identifier : "no specified source" changed << "* #{name} from `#{lockfile_source_name}` to `#{gemfile_source_name}`" end reason = change_reason - msg << "\n\n#{reason.split(", ").map(&:capitalize).join("\n")}" unless reason.strip.empty? + msg = String.new + msg << "#{reason.capitalize.strip}, but the lockfile can't be updated because frozen mode is set" msg << "\n\nYou have added to the Gemfile:\n" << added.join("\n") if added.any? msg << "\n\nYou have deleted from the Gemfile:\n" << deleted.join("\n") if deleted.any? msg << "\n\nYou have changed in the Gemfile:\n" << changed.join("\n") if changed.any? - msg << "\n" + msg << "\n\nRun `bundle install` elsewhere and add the updated #{Bundler.default_lockfile.relative_path_from(SharedHelpers.pwd)} to version control.\n" + unless explicit_flag + suggested_command = unless Bundler.settings.locations("frozen").keys.include?(:env) + "bundle config set frozen false" + end + msg << "If this is a development machine, remove the #{Bundler.default_gemfile.relative_path_from(SharedHelpers.pwd)} " \ + "freeze by running `#{suggested_command}`." if suggested_command + end + raise ProductionError, msg if added.any? || deleted.any? || changed.any? || !nothing_changed? end def validate_runtime! validate_ruby! @@ -470,13 +476,17 @@ attr_reader :sources private :sources def nothing_changed? - !@source_changes && !@dependency_changes && !@new_platform && !@path_changes && !@local_changes && !@incomplete_lockfile + !@source_changes && !@dependency_changes && !@new_platform && !@path_changes && !@local_changes && !@missing_lockfile_dep && !@unlocking_bundler end + def no_resolve_needed? + !unlocking? && nothing_changed? + end + def unlocking? @unlocking end private @@ -484,13 +494,20 @@ def resolver @resolver ||= Resolver.new(resolution_packages, gem_version_promoter) end def expanded_dependencies - dependencies + metadata_dependencies + dependencies_with_bundler + metadata_dependencies end + def dependencies_with_bundler + return dependencies unless @unlocking_bundler + return dependencies if dependencies.map(&:name).include?("bundler") + + [Dependency.new("bundler", @unlocking_bundler)] + dependencies + end + def resolution_packages @resolution_packages ||= begin last_resolve = converge_locked_specs remove_ruby_from_platforms_if_necessary!(current_dependencies) packages = Resolver::Base.new(source_requirements, expanded_dependencies, last_resolve, @platforms, :locked_specs => @originally_locked_specs, :unlock => @unlock[:gems], :prerelease => gem_version_promoter.pre?) @@ -550,10 +567,12 @@ end def start_resolution result = resolver.start + @resolved_bundler_version = result.find {|spec| spec.name == "bundler" }&.version + SpecSet.new(SpecSet.new(result).for(dependencies, false, @platforms)) end def precompute_source_requirements_for_indirect_dependencies? sources.non_global_rubygems_sources.all?(&:dependency_api_available?) && !sources.aggregate_global_source? @@ -607,11 +626,12 @@ [@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"], + [@missing_lockfile_dep, "your lock file is missing \"#{@missing_lockfile_dep}\""], + [@unlocking_bundler, "an update to the version of Bundler itself was requested"], ].select(&:first).map(&:last).join(", ") end def pretty_dep(dep) SharedHelpers.pretty_dependency(dep) @@ -662,24 +682,28 @@ changed || specs_changed?(source) end.map(&:first) !sources_with_changes.each {|source| @unlock[:sources] << source.name }.empty? end - def check_missing_lockfile_specs + def check_missing_lockfile_dep all_locked_specs = @locked_specs.map(&:name) << "bundler" missing = @locked_specs.select do |s| s.dependencies.any? {|dep| !all_locked_specs.include?(dep.name) } end if missing.any? @locked_specs.delete(missing) - true - else - false + return missing.first.name end + + return if @dependency_changes + + current_dependencies.find do |d| + @locked_specs[d.name].empty? + end&.name end def converge_paths sources.path_sources.any? do |source| specs_changed?(source) @@ -859,11 +883,19 @@ end source_requirements.merge!(source_map.locked_requirements) unless @remote metadata_dependencies.each do |dep| source_requirements[dep.name] = sources.metadata_source end - source_requirements[:default_bundler] = source_requirements["bundler"] || sources.default_source - source_requirements["bundler"] = sources.metadata_source # needs to come last to override + + default_bundler_source = source_requirements["bundler"] || sources.default_source + + if @unlocking_bundler + default_bundler_source.add_dependency_names("bundler") + else + source_requirements[:default_bundler] = default_bundler_source + source_requirements["bundler"] = sources.metadata_source # needs to come last to override + end + verify_changed_sources! source_requirements end def verify_changed_sources!