diff options
161 files changed, 2541 insertions, 1013 deletions
diff --git a/lib/bundler.rb b/lib/bundler.rb index c72ad27c40..d370d8a53a 100644 --- a/lib/bundler.rb +++ b/lib/bundler.rb @@ -63,7 +63,6 @@ module Bundler autoload :Resolver, File.expand_path("bundler/resolver", __dir__) autoload :Retry, File.expand_path("bundler/retry", __dir__) autoload :RubyDsl, File.expand_path("bundler/ruby_dsl", __dir__) - autoload :RubyGemsGemInstaller, File.expand_path("bundler/rubygems_gem_installer", __dir__) autoload :RubyVersion, File.expand_path("bundler/ruby_version", __dir__) autoload :Runtime, File.expand_path("bundler/runtime", __dir__) autoload :Settings, File.expand_path("bundler/settings", __dir__) @@ -441,7 +440,7 @@ EOF end def local_platform - return Gem::Platform::RUBY if settings[:force_ruby_platform] + return Gem::Platform::RUBY if settings[:force_ruby_platform] || Gem.platforms == [Gem::Platform::RUBY] Gem::Platform.local end diff --git a/lib/bundler/cli.rb b/lib/bundler/cli.rb index 249f5b2027..421f42cb52 100644 --- a/lib/bundler/cli.rb +++ b/lib/bundler/cli.rb @@ -586,6 +586,7 @@ module Bundler method_option :git, :type => :boolean, :default => true, :desc => "Initialize a git repo inside your library." method_option :mit, :type => :boolean, :desc => "Generate an MIT license file. Set a default with `bundle config set --global gem.mit true`." method_option :rubocop, :type => :boolean, :desc => "Add rubocop to the generated Rakefile and gemspec. Set a default with `bundle config set --global gem.rubocop true`." + method_option :changelog, :type => :boolean, :desc => "Generate changelog file. Set a default with `bundle config set --global gem.changelog true`." method_option :test, :type => :string, :lazy_default => Bundler.settings["gem.test"] || "", :aliases => "-t", :banner => "Use the specified test framework for your library", :desc => "Generate a test directory for your library, either rspec, minitest or test-unit. Set a default with `bundle config set --global gem.test (rspec|minitest|test-unit)`." method_option :ci, :type => :string, :lazy_default => Bundler.settings["gem.ci"] || "", diff --git a/lib/bundler/cli/cache.rb b/lib/bundler/cli/cache.rb index c14c8877f0..9cd6133879 100644 --- a/lib/bundler/cli/cache.rb +++ b/lib/bundler/cli/cache.rb @@ -30,6 +30,7 @@ module Bundler require_relative "install" options = self.options.dup options["local"] = false if Bundler.settings[:cache_all_platforms] + options["no-cache"] = true Bundler::CLI::Install.new(options).run end diff --git a/lib/bundler/cli/gem.rb b/lib/bundler/cli/gem.rb index 6ef1473b1e..5b3d9c332e 100644 --- a/lib/bundler/cli/gem.rb +++ b/lib/bundler/cli/gem.rb @@ -39,11 +39,11 @@ module Bundler constant_name = name.gsub(/-[_-]*(?![_-]|$)/) { "::" }.gsub(/([_-]+|(::)|^)(.|$)/) { $2.to_s + $3.upcase } constant_array = constant_name.split("::") - git_installed = Bundler.git_present? + use_git = Bundler.git_present? && options[:git] - git_author_name = git_installed ? `git config user.name`.chomp : "" - github_username = git_installed ? `git config github.user`.chomp : "" - git_user_email = git_installed ? `git config user.email`.chomp : "" + git_author_name = use_git ? `git config user.name`.chomp : "" + github_username = use_git ? `git config github.user`.chomp : "" + git_user_email = use_git ? `git config user.email`.chomp : "" config = { :name => name, @@ -58,7 +58,9 @@ module Bundler :ext => options[:ext], :exe => options[:exe], :bundler_version => bundler_dependency_version, + :git => use_git, :github_username => github_username.empty? ? "[USERNAME]" : github_username, + :required_ruby_version => Gem.ruby_version < Gem::Version.new("2.4.a") ? "2.3.0" : "2.4.0", } ensure_safe_gem_name(name, constant_array) @@ -78,7 +80,7 @@ module Bundler bin/setup ] - templates.merge!("gitignore.tt" => ".gitignore") if Bundler.git_present? + templates.merge!("gitignore.tt" => ".gitignore") if use_git if test_framework = ask_and_set_test_framework config[:test] = test_framework @@ -141,12 +143,25 @@ module Bundler templates.merge!("CODE_OF_CONDUCT.md.tt" => "CODE_OF_CONDUCT.md") end + if ask_and_set(:changelog, "Do you want to include a changelog?", + "A changelog is a file which contains a curated, chronologically ordered list of notable " \ + "changes for each version of a project. To make it easier for users and contributors to" \ + " see precisely what notable changes have been made between each release (or version) of" \ + " the project. Whether consumers or developers, the end users of software are" \ + " human beings who care about what's in the software. When the software changes, people " \ + "want to know why and how. see https://keepachangelog.com") + config[:changelog] = true + Bundler.ui.info "Changelog enabled in config" + templates.merge!("CHANGELOG.md.tt" => "CHANGELOG.md") + end + if ask_and_set(:rubocop, "Do you want to add rubocop as a dependency for gems you generate?", "RuboCop is a static code analyzer that has out-of-the-box rules for many " \ "of the guidelines in the community style guide. " \ "For more information, see the RuboCop docs (https://docs.rubocop.org/en/stable/) " \ "and the Ruby Style Guides (https://github.com/rubocop-hq/ruby-style-guide).") config[:rubocop] = true + config[:rubocop_version] = Gem.ruby_version < Gem::Version.new("2.4.a") ? "0.81.0" : "1.7" Bundler.ui.info "RuboCop enabled in config" templates.merge!("rubocop.yml.tt" => ".rubocop.yml") end @@ -161,24 +176,31 @@ module Bundler ) end + if File.exist?(target) && !File.directory?(target) + Bundler.ui.error "Couldn't create a new gem named `#{gem_name}` because there's an existing file named `#{gem_name}`." + exit Bundler::BundlerError.all_errors[Bundler::GenericSystemCallError] + end + + if use_git + Bundler.ui.info "Initializing git repo in #{target}" + `git init #{target}` + + config[:git_default_branch] = File.read("#{target}/.git/HEAD").split("/").last.chomp + end + templates.each do |src, dst| destination = target.join(dst) - SharedHelpers.filesystem_access(destination) do - thor.template("newgem/#{src}", destination, config) - end + thor.template("newgem/#{src}", destination, config) end executables.each do |file| - SharedHelpers.filesystem_access(target.join(file)) do |path| - executable = (path.stat.mode | 0o111) - path.chmod(executable) - end + path = target.join(file) + executable = (path.stat.mode | 0o111) + path.chmod(executable) end - if Bundler.git_present? && options[:git] - Bundler.ui.info "Initializing git repo in #{target}" + if use_git Dir.chdir(target) do - `git init` `git add .` end end @@ -188,8 +210,6 @@ module Bundler Bundler.ui.info "Gem '#{name}' was successfully created. " \ "For more information on making a RubyGem visit https://bundler.io/guides/creating_gem.html" - rescue Errno::EEXIST => e - raise GenericSystemCallError.new(e, "There was a conflict while creating the new gem.") end private diff --git a/lib/bundler/compact_index_client/updater.rb b/lib/bundler/compact_index_client/updater.rb index 66d1735583..9e0180fac7 100644 --- a/lib/bundler/compact_index_client/updater.rb +++ b/lib/bundler/compact_index_client/updater.rb @@ -1,8 +1,6 @@ # frozen_string_literal: true require_relative "../vendored_fileutils" -require "stringio" -require "zlib" module Bundler class CompactIndexClient @@ -45,24 +43,18 @@ module Bundler else "bytes=#{local_temp_path.size}-" end - else - # Fastly ignores Range when Accept-Encoding: gzip is set - headers["Accept-Encoding"] = "gzip" end response = @fetcher.call(remote_path, headers) return nil if response.is_a?(Net::HTTPNotModified) content = response.body - if response["Content-Encoding"] == "gzip" - content = Zlib::GzipReader.new(StringIO.new(content)).read - end SharedHelpers.filesystem_access(local_temp_path) do if response.is_a?(Net::HTTPPartialContent) && local_temp_path.size.nonzero? local_temp_path.open("a") {|f| f << slice_body(content, 1..-1) } else - local_temp_path.open("w") {|f| f << content } + local_temp_path.open("wb") {|f| f << content } end end diff --git a/lib/bundler/definition.rb b/lib/bundler/definition.rb index 349fa632a0..5f02b15e5f 100644 --- a/lib/bundler/definition.rb +++ b/lib/bundler/definition.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true require_relative "lockfile_parser" -require "set" module Bundler class Definition @@ -88,11 +87,7 @@ module Bundler @lockfile_contents = Bundler.read_file(lockfile) @locked_gems = LockfileParser.new(@lockfile_contents) @locked_platforms = @locked_gems.platforms - if Bundler.settings[:force_ruby_platform] - @platforms = [Gem::Platform::RUBY] - else - @platforms = @locked_platforms.dup - end + @platforms = @locked_platforms.dup @locked_bundler_version = @locked_gems.bundler_version @locked_ruby_version = @locked_gems.ruby_version @@ -264,23 +259,18 @@ module Bundler def resolve @resolve ||= begin last_resolve = converge_locked_specs - resolve = - if Bundler.frozen_bundle? - Bundler.ui.debug "Frozen, using resolution from the lockfile" - last_resolve - elsif !unlocking? && nothing_changed? - Bundler.ui.debug("Found no changes, using resolution from the lockfile") - last_resolve - else - # Run a resolve against the locally available gems - Bundler.ui.debug("Found changes from the lockfile, re-resolving dependencies because #{change_reason}") - expanded_dependencies = expand_dependencies(dependencies + metadata_dependencies, @remote) - last_resolve.merge Resolver.resolve(expanded_dependencies, index, source_requirements, last_resolve, gem_version_promoter, additional_base_requirements_for_resolve, platforms) - end - - # filter out gems that _can_ be installed on multiple platforms, but don't need - # to be - resolve.for(expand_dependencies(dependencies, true), [], false, false, false) + if Bundler.frozen_bundle? + Bundler.ui.debug "Frozen, using resolution from the lockfile" + last_resolve + elsif !unlocking? && nothing_changed? + Bundler.ui.debug("Found no changes, using resolution from the lockfile") + last_resolve + else + # Run a resolve against the locally available gems + Bundler.ui.debug("Found changes from the lockfile, re-resolving dependencies because #{change_reason}") + expanded_dependencies = expand_dependencies(dependencies + metadata_dependencies, @remote) + Resolver.resolve(expanded_dependencies, source_requirements, last_resolve, gem_version_promoter, additional_base_requirements_for_resolve, platforms) + end end end @@ -611,7 +601,7 @@ module Bundler deps_for_source = @dependencies.select {|s| s.source == source } locked_deps_for_source = @locked_deps.values.select {|dep| dep.source == locked_source } - Set.new(deps_for_source) != Set.new(locked_deps_for_source) + deps_for_source.uniq.sort != locked_deps_for_source.sort end def specs_for_source_changed?(source) @@ -673,19 +663,20 @@ module Bundler def converge_rubygems_sources return false if Bundler.feature_flag.disable_multisource? - changes = false - # Get the RubyGems sources from the Gemfile.lock locked_gem_sources = @locked_sources.select {|s| s.is_a?(Source::Rubygems) } + return false if locked_gem_sources.empty? + # Get the RubyGems remotes from the Gemfile actual_remotes = sources.rubygems_remotes + return false if actual_remotes.empty? + + changes = false # If there is a RubyGems source in both - if !locked_gem_sources.empty? && !actual_remotes.empty? - locked_gem_sources.each do |locked_gem| - # Merge the remotes from the Gemfile into the Gemfile.lock - changes |= locked_gem.replace_remotes(actual_remotes, Bundler.settings[:allow_deployment_source_credential_changes]) - end + locked_gem_sources.each do |locked_gem| + # Merge the remotes from the Gemfile into the Gemfile.lock + changes |= locked_gem.replace_remotes(actual_remotes, Bundler.settings[:allow_deployment_source_credential_changes]) end changes @@ -825,11 +816,6 @@ module Bundler # commonly happens if the version changed in the gemspec next unless new_spec - new_runtime_deps = new_spec.dependencies.select {|d| d.type != :development } - old_runtime_deps = s.dependencies.select {|d| d.type != :development } - # If the dependencies of the path source have changed and locked spec can't satisfy new dependencies, unlock it - next unless new_runtime_deps.sort == old_runtime_deps.sort || new_runtime_deps.all? {|d| satisfies_locked_spec?(d) } - s.dependencies.replace(new_spec.dependencies) end @@ -896,7 +882,7 @@ module Bundler dependencies.each do |dep| dep = Dependency.new(dep, ">= 0") unless dep.respond_to?(:name) next unless remote || dep.current_platform? - target_platforms = dep.gem_platforms(remote ? Resolver.sort_platforms(@platforms) : [generic_local_platform]) + target_platforms = dep.gem_platforms(remote ? @platforms : [generic_local_platform]) deps += expand_dependency_with_platforms(dep, target_platforms) end deps @@ -904,7 +890,7 @@ module Bundler def expand_dependency_with_platforms(dep, platforms) platforms.map do |p| - DepProxy.new(dep, p) + DepProxy.get_proxy(dep, p) end end @@ -915,29 +901,18 @@ module Bundler # Record the specs available in each gem's source, so that those # specs will be available later when the resolver knows where to # look for that gemspec (or its dependencies) - default = sources.default_source - source_requirements = { :default => default } - default = nil unless Bundler.feature_flag.disable_multisource? - dependencies.each do |dep| - next unless source = dep.source || default - source_requirements[dep.name] = source - end + source_requirements = { :default => sources.default_source }.merge(dependency_source_requirements) metadata_dependencies.each do |dep| source_requirements[dep.name] = sources.metadata_source end + source_requirements[:global] = index unless Bundler.feature_flag.disable_multisource? + source_requirements[:default_bundler] = source_requirements["bundler"] || source_requirements[:default] source_requirements["bundler"] = sources.metadata_source # needs to come last to override source_requirements end def pinned_spec_names(skip = nil) - pinned_names = [] - default = Bundler.feature_flag.disable_multisource? && sources.default_source - @dependencies.each do |dep| - next unless dep_source = dep.source || default - next if dep_source == skip - pinned_names << dep.name - end - pinned_names + dependency_source_requirements.reject {|_, source| source == skip }.keys end def requested_groups @@ -984,7 +959,7 @@ module Bundler next requirements if @locked_gems.dependencies[name] != dependency next requirements if dependency.source.is_a?(Source::Path) dep = Gem::Dependency.new(name, ">= #{locked_spec.version}") - requirements[name] = DepProxy.new(dep, locked_spec.platform) + requirements[name] = DepProxy.get_proxy(dep, locked_spec.platform) requirements end.values end @@ -994,5 +969,17 @@ module Bundler Bundler.settings[:allow_deployment_source_credential_changes] && source.equivalent_remotes?(sources.rubygems_remotes) end + + def dependency_source_requirements + @dependency_source_requirements ||= begin + source_requirements = {} + default = sources.default_source + dependencies.each do |dep| + dep_source = dep.source || default + source_requirements[dep.name] = dep_source + end + source_requirements + end + end end end diff --git a/lib/bundler/dep_proxy.rb b/lib/bundler/dep_proxy.rb index bb09fe9ea6..a32dc37b49 100644 --- a/lib/bundler/dep_proxy.rb +++ b/lib/bundler/dep_proxy.rb @@ -4,19 +4,18 @@ module Bundler class DepProxy attr_reader :__platform, :dep + @proxies = {} + + def self.get_proxy(dep, platform) + @proxies[[dep, platform]] ||= new(dep, platform).freeze + end + def initialize(dep, platform) @dep = dep @__platform = platform end - def hash - @hash ||= [dep, __platform].hash - end - - def ==(other) - return false if other.class != self.class - dep == other.dep && __platform == other.__platform - end + private_class_method :new alias_method :eql?, :== @@ -39,6 +38,14 @@ module Bundler s end + def dup + raise NoMethodError.new("DepProxy cannot be duplicated") + end + + def clone + raise NoMethodError.new("DepProxy cannot be cloned") + end + private def method_missing(*args, &blk) diff --git a/lib/bundler/dsl.rb b/lib/bundler/dsl.rb index 1cc7908b8a..23fba99ffa 100644 --- a/lib/bundler/dsl.rb +++ b/lib/bundler/dsl.rb @@ -24,6 +24,9 @@ module Bundler def initialize @source = nil @sources = SourceList.new + + @global_rubygems_sources = [] + @git_sources = {} @dependencies = [] @groups = [] @@ -45,6 +48,7 @@ module Bundler @gemfiles << expanded_gemfile_path contents ||= Bundler.read_file(@gemfile.to_s) instance_eval(contents.dup.tap{|x| x.untaint if RUBY_VERSION < "2.7" }, gemfile.to_s, 1) + check_primary_source_safety rescue Exception => e # rubocop:disable Lint/RescueException message = "There was an error " \ "#{e.is_a?(GemfileEvalError) ? "evaluating" : "parsing"} " \ @@ -164,8 +168,7 @@ module Bundler elsif block_given? with_source(@sources.add_rubygems_source("remotes" => source), &blk) else - check_primary_source_safety(@sources) - @sources.global_rubygems_source = source + @global_rubygems_sources << source end end @@ -183,24 +186,14 @@ module Bundler end def path(path, options = {}, &blk) - unless block_given? - msg = "You can no longer specify a path source by itself. Instead, \n" \ - "either use the :path option on a gem, or specify the gems that \n" \ - "bundler should find in the path source by passing a block to \n" \ - "the path method, like: \n\n" \ - " path 'dir/containing/rails' do\n" \ - " gem 'rails'\n" \ - " end\n\n" - - raise DeprecatedError, msg if Bundler.feature_flag.disable_multisource? - SharedHelpers.major_deprecation(2, msg.strip) - end - source_options = normalize_hash(options).merge( "path" => Pathname.new(path), "root_path" => gemfile_root, "gemspec" => gemspecs.find {|g| g.name == options["name"] } ) + + source_options["global"] = true unless block_given? + source = @sources.add_path_source(source_options) with_source(source, &blk) end @@ -279,6 +272,11 @@ module Bundler raise GemfileError, "Undefined local variable or method `#{name}' for Gemfile" end + def check_primary_source_safety + check_path_source_safety + check_rubygems_source_safety + end + private def add_git_sources @@ -440,17 +438,33 @@ repo_name ||= user_name end end - def check_primary_source_safety(source_list) - return if source_list.rubygems_primary_remotes.empty? && source_list.global_rubygems_source.nil? + def check_path_source_safety + return if @sources.global_path_source.nil? + + msg = "You can no longer specify a path source by itself. Instead, \n" \ + "either use the :path option on a gem, or specify the gems that \n" \ + "bundler should find in the path source by passing a block to \n" \ + "the path method, like: \n\n" \ + " path 'dir/containing/rails' do\n" \ + " gem 'rails'\n" \ + " end\n\n" + + SharedHelpers.major_deprecation(2, msg.strip) + end + + def check_rubygems_source_safety + @sources.global_rubygems_source = @global_rubygems_sources.shift + return if @global_rubygems_sources.empty? + + @global_rubygems_sources.each do |source| + @sources.add_rubygems_remote(source) + end if Bundler.feature_flag.disable_multisource? msg = "This Gemfile contains multiple primary sources. " \ "Each source after the first must include a block to indicate which gems " \ - "should come from that source" - unless Bundler.feature_flag.bundler_2_mode? - msg += ". To downgrade this error to a warning, run " \ - "`bundle config unset disable_multisource`" - end + "should come from that source. To downgrade this error to a warning, run " \ + "`bundle config unset disable_multisource`" raise GemfileEvalError, msg else Bundler::SharedHelpers.major_deprecation 2, "Your Gemfile contains multiple primary sources. " \ diff --git a/lib/bundler/feature_flag.rb b/lib/bundler/feature_flag.rb index a92ec8756d..a1b443b042 100644 --- a/lib/bundler/feature_flag.rb +++ b/lib/bundler/feature_flag.rb @@ -27,7 +27,6 @@ module Bundler (1..10).each {|v| define_method("bundler_#{v}_mode?") { major_version >= v } } - settings_flag(:allow_bundler_dependency_conflicts) { bundler_3_mode? } settings_flag(:allow_offline_install) { bundler_3_mode? } settings_flag(:auto_clean_without_path) { bundler_3_mode? } settings_flag(:cache_all) { bundler_3_mode? } diff --git a/lib/bundler/fetcher.rb b/lib/bundler/fetcher.rb index 2d9b4c2945..f9c54f7ad2 100644 --- a/lib/bundler/fetcher.rb +++ b/lib/bundler/fetcher.rb @@ -137,7 +137,6 @@ module Bundler end specs.each do |name, version, platform, dependencies, metadata| - next if name == "bundler" spec = if dependencies EndpointSpecification.new(name, version, platform, dependencies, metadata) else diff --git a/lib/bundler/gem_helper.rb b/lib/bundler/gem_helper.rb index 0acaa69f25..d3e30124f9 100644 --- a/lib/bundler/gem_helper.rb +++ b/lib/bundler/gem_helper.rb @@ -116,19 +116,21 @@ module Bundler def git_push(remote = nil) remote ||= default_remote - perform_git_push remote + perform_git_push "#{remote} refs/heads/#{current_branch}" perform_git_push "#{remote} refs/tags/#{version_tag}" Bundler.ui.confirm "Pushed git commits and release tag." end def default_remote - # We can replace this with `git branch --show-current` once we drop support for git < 2.22.0 - current_branch = sh(%w[git rev-parse --abbrev-ref HEAD]).gsub(%r{\Aheads/}, "").strip + remote_for_branch, status = sh_with_status(%W[git config --get branch.#{current_branch}.remote]) + return "origin" unless status.success? - remote_for_branch = sh(%W[git config --get branch.#{current_branch}.remote]).strip - return "origin" if remote_for_branch.empty? + remote_for_branch.strip + end - remote_for_branch + def current_branch + # We can replace this with `git branch --show-current` once we drop support for git < 2.22.0 + sh(%w[git rev-parse --abbrev-ref HEAD]).gsub(%r{\Aheads/}, "").strip end def allowed_push_host diff --git a/lib/bundler/gem_version_promoter.rb b/lib/bundler/gem_version_promoter.rb index 2e87b7d443..3cce3f2139 100644 --- a/lib/bundler/gem_version_promoter.rb +++ b/lib/bundler/gem_version_promoter.rb @@ -81,8 +81,8 @@ module Bundler sort_dep_specs(spec_groups, locked_spec) end.tap do |specs| if DEBUG - warn before_result - warn " after sort_versions: #{debug_format_result(dep, specs).inspect}" + puts before_result + puts " after sort_versions: #{debug_format_result(dep, specs).inspect}" end end end diff --git a/lib/bundler/index.rb b/lib/bundler/index.rb index f26f542fde..f945176037 100644 --- a/lib/bundler/index.rb +++ b/lib/bundler/index.rb @@ -1,7 +1,5 @@ # frozen_string_literal: true -require "set" - module Bundler class Index include Enumerable @@ -65,11 +63,14 @@ module Bundler def unsorted_search(query, base) results = local_search(query, base) - seen = results.map(&:full_name).to_set unless @sources.empty? + seen = results.map(&:full_name).uniq unless @sources.empty? @sources.each do |source| source.unsorted_search(query, base).each do |spec| - results << spec if seen.add?(spec.full_name) + next if seen.include?(spec.full_name) + + seen << spec.full_name + results << spec end end @@ -170,7 +171,7 @@ module Bundler def dependencies_eql?(spec, other_spec) deps = spec.dependencies.select {|d| d.type != :development } other_deps = other_spec.dependencies.select {|d| d.type != :development } - Set.new(deps) == Set.new(other_deps) + deps.sort == other_deps.sort end def add_source(index) diff --git a/lib/bundler/inline.rb b/lib/bundler/inline.rb index 59211193d4..02da06cee9 100644 --- a/lib/bundler/inline.rb +++ b/lib/bundler/inline.rb @@ -50,6 +50,7 @@ def gemfile(install = false, options = {}, &gemfile) Bundler::Plugin.gemfile_install(&gemfile) if Bundler.feature_flag.plugins? builder = Bundler::Dsl.new builder.instance_eval(&gemfile) + builder.check_primary_source_safety Bundler.settings.temporary(:frozen => false) do definition = builder.to_definition(nil, true) diff --git a/lib/bundler/installer.rb b/lib/bundler/installer.rb index 048b0786a7..09c8b1c157 100644 --- a/lib/bundler/installer.rb +++ b/lib/bundler/installer.rb @@ -82,7 +82,6 @@ module Bundler if resolve_if_needed(options) ensure_specs_are_compatible! - warn_on_incompatible_bundler_deps load_plugins options.delete(:jobs) else @@ -90,6 +89,8 @@ module Bundler end install(options) + Gem::Specification.reset # invalidate gem specification cache so that installed gems are immediately available + lock unless Bundler.frozen_bundle? Standalone.new(options[:standalone], @definition).generate if options[:standalone] end @@ -265,22 +266,6 @@ module Bundler end end - def warn_on_incompatible_bundler_deps - bundler_version = Gem::Version.create(Bundler::VERSION) - @definition.specs.each do |spec| - spec.dependencies.each do |dep| - next if dep.type == :development - next unless dep.name == "bundler".freeze - next if dep.requirement.satisfied_by?(bundler_version) - - Bundler.ui.warn "#{spec.name} (#{spec.version}) has dependency" \ - " #{SharedHelpers.pretty_dependency(dep)}" \ - ", which is unsatisfied by the current bundler version #{VERSION}" \ - ", so the dependency is being ignored" - end - end - end - def install_in_parallel(size, standalone, force = false) spec_installations = ParallelInstaller.call(self, @definition.specs, size, standalone, force) spec_installations.each do |installation| diff --git a/lib/bundler/installer/standalone.rb b/lib/bundler/installer/standalone.rb index 0720d6d38a..2a3f5cfe35 100644 --- a/lib/bundler/installer/standalone.rb +++ b/lib/bundler/installer/standalone.rb @@ -15,6 +15,7 @@ module Bundler file.puts "ruby_engine = RUBY_ENGINE" file.puts "ruby_version = RbConfig::CONFIG[\"ruby_version\"]" file.puts "path = File.expand_path('..', __FILE__)" + file.puts reverse_rubygems_kernel_mixin paths.each do |path| file.puts %($:.unshift File.expand_path("\#{path}/#{path}")) end @@ -48,5 +49,19 @@ module Bundler error_message = "#{spec.name} #{spec.version} has an invalid gemspec" raise Gem::InvalidSpecificationException.new(error_message) end + + def reverse_rubygems_kernel_mixin + <<~END + kernel = (class << ::Kernel; self; end) + [kernel, ::Kernel].each do |k| + if k.private_method_defined?(:gem_original_require) + private_require = k.private_method_defined?(:require) + k.send(:remove_method, :require) + k.send(:define_method, :require, k.instance_method(:gem_original_require)) + k.send(:private, :require) if private_require + end + end + END + end end end diff --git a/lib/bundler/lazy_specification.rb b/lib/bundler/lazy_specification.rb index 1081910816..04ba2a2364 100644 --- a/lib/bundler/lazy_specification.rb +++ b/lib/bundler/lazy_specification.rb @@ -4,22 +4,6 @@ require_relative "match_platform" module Bundler class LazySpecification - Identifier = Struct.new(:name, :version, :platform) - class Identifier - include Comparable - def <=>(other) - return unless other.is_a?(Identifier) - [name, version, platform_string] <=> [other.name, other.version, other.platform_string] - end - - protected - - def platform_string - platform_string = platform.to_s - platform_string == Index::RUBY ? Index::NULL : platform_string - end - end - include MatchPlatform attr_reader :name, :version, :dependencies, :platform @@ -108,7 +92,7 @@ module Bundler end def identifier - @__identifier ||= Identifier.new(name, version, platform) + @__identifier ||= [name, version, platform_string] end def git_version @@ -116,6 +100,13 @@ module Bundler " #{source.revision[0..6]}" end + protected + + def platform_string + platform_string = platform.to_s + platform_string == Index::RUBY ? Index::NULL : platform_string + end + private def to_ary @@ -140,7 +131,7 @@ module Bundler # explicitly add a more specific platform. # def ruby_platform_materializes_to_ruby_platform? - !Bundler.most_specific_locked_platform?(Gem::Platform::RUBY) + !Bundler.most_specific_locked_platform?(Gem::Platform::RUBY) || Bundler.settings[:force_ruby_platform] end end end diff --git a/lib/bundler/lockfile_parser.rb b/lib/bundler/lockfile_parser.rb index f836737621..058d353bbe 100644 --- a/lib/bundler/lockfile_parser.rb +++ b/lib/bundler/lockfile_parser.rb @@ -64,8 +64,6 @@ module Bundler @state = nil @specs = {} - @rubygems_aggregate = Source::Rubygems.new - if lockfile.match(/<<<<<<<|=======|>>>>>>>|\|\|\|\|\|\|\|/) raise LockfileError, "Your #{Bundler.default_lockfile.relative_path_from(SharedHelpers.pwd)} contains merge conflicts.\n" \ "Run `git checkout HEAD -- #{Bundler.default_lockfile.relative_path_from(SharedHelpers.pwd)}` first to get a clean lock." @@ -89,7 +87,6 @@ module Bundler send("parse_#{@state}", line) end end - @sources << @rubygems_aggregate unless Bundler.feature_flag.disable_multisource? @specs = @specs.values.sort_by(&:identifier) warn_for_outdated_bundler_version rescue ArgumentError => e @@ -134,16 +131,19 @@ module Bundler @sources << @current_source end when GEM - if Bundler.feature_flag.disable_multisource? + source_remotes = Array(@opts["remote"]) + + if source_remotes.size == 1 @opts["remotes"] = @opts.delete("remote") @current_source = TYPES[@type].from_lock(@opts) - @sources << @current_source else - Array(@opts["remote"]).each do |url| - @rubygems_aggregate.add_remote(url) + source_remotes.each do |url| + rubygems_aggregate.add_remote(url) end - @current_source = @rubygems_aggregate + @current_source = rubygems_aggregate end + + @sources << @current_source when PLUGIN @current_source = Plugin.source_from_lock(@opts) @sources << @current_source @@ -245,5 +245,9 @@ module Bundler def parse_ruby(line) @ruby_version = line.strip end + + def rubygems_aggregate + @rubygems_aggregate ||= Source::Rubygems.new + end end end diff --git a/lib/bundler/man/bundle-add.1 b/lib/bundler/man/bundle-add.1 index 29b2cadf33..b44295b2d3 100644 --- a/lib/bundler/man/bundle-add.1 +++ b/lib/bundler/man/bundle-add.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-ADD" "1" "December 2020" "" "" +.TH "BUNDLE\-ADD" "1" "January 2021" "" "" . .SH "NAME" \fBbundle\-add\fR \- Add gem to the Gemfile and run bundle install diff --git a/lib/bundler/man/bundle-binstubs.1 b/lib/bundler/man/bundle-binstubs.1 index 6ba4ed914d..99876d023e 100644 --- a/lib/bundler/man/bundle-binstubs.1 +++ b/lib/bundler/man/bundle-binstubs.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-BINSTUBS" "1" "December 2020" "" "" +.TH "BUNDLE\-BINSTUBS" "1" "January 2021" "" "" . .SH "NAME" \fBbundle\-binstubs\fR \- Install the binstubs of the listed gems diff --git a/lib/bundler/man/bundle-cache.1 b/lib/bundler/man/bundle-cache.1 index 8aa45ca213..3b3c6f9734 100644 --- a/lib/bundler/man/bundle-cache.1 +++ b/lib/bundler/man/bundle-cache.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-CACHE" "1" "December 2020" "" "" +.TH "BUNDLE\-CACHE" "1" "January 2021" "" "" . .SH "NAME" \fBbundle\-cache\fR \- Package your needed \fB\.gem\fR files into your application diff --git a/lib/bundler/man/bundle-check.1 b/lib/bundler/man/bundle-check.1 index 5013cd8cda..4436c3e971 100644 --- a/lib/bundler/man/bundle-check.1 +++ b/lib/bundler/man/bundle-check.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-CHECK" "1" "December 2020" "" "" +.TH "BUNDLE\-CHECK" "1" "January 2021" "" "" . .SH "NAME" \fBbundle\-check\fR \- Verifies if dependencies are satisfied by installed gems diff --git a/lib/bundler/man/bundle-clean.1 b/lib/bundler/man/bundle-clean.1 index 231ce273a8..b7e882ecbf 100644 --- a/lib/bundler/man/bundle-clean.1 +++ b/lib/bundler/man/bundle-clean.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-CLEAN" "1" "December 2020" "" "" +.TH "BUNDLE\-CLEAN" "1" "January 2021" "" "" . .SH "NAME" \fBbundle\-clean\fR \- Cleans up unused gems in your bundler directory diff --git a/lib/bundler/man/bundle-config.1 b/lib/bundler/man/bundle-config.1 index f690b0a8f0..ad36c6bde0 100644 --- a/lib/bundler/man/bundle-config.1 +++ b/lib/bundler/man/bundle-config.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-CONFIG" "1" "December 2020" "" "" +.TH "BUNDLE\-CONFIG" "1" "January 2021" "" "" . .SH "NAME" \fBbundle\-config\fR \- Set bundler configuration options @@ -136,9 +136,6 @@ Any periods in the configuration keys must be replaced with two underscores when The following is a list of all configuration keys and their purpose\. You can learn more about their operation in bundle install(1) \fIbundle\-install\.1\.html\fR\. . .IP "\(bu" 4 -\fBallow_bundler_dependency_conflicts\fR (\fBBUNDLE_ALLOW_BUNDLER_DEPENDENCY_CONFLICTS\fR): Allow resolving to specifications that have dependencies on \fBbundler\fR that are incompatible with the running Bundler version\. -. -.IP "\(bu" 4 \fBallow_deployment_source_credential_changes\fR (\fBBUNDLE_ALLOW_DEPLOYMENT_SOURCE_CREDENTIAL_CHANGES\fR): When in deployment mode, allow changing the credentials to a gem\'s source\. Ex: \fBhttps://some\.host\.com/gems/path/\fR \-> \fBhttps://user_name:password@some\.host\.com/gems/path\fR . .IP "\(bu" 4 @@ -184,6 +181,9 @@ The following is a list of all configuration keys and their purpose\. You can le \fBdisable_local_branch_check\fR (\fBBUNDLE_DISABLE_LOCAL_BRANCH_CHECK\fR): Allow Bundler to use a local git override without a branch specified in the Gemfile\. . .IP "\(bu" 4 +\fBdisable_local_revision_check\fR (\fBBUNDLE_DISABLE_LOCAL_REVISION_CHECK\fR): Allow Bundler to use a local git override without checking if the revision present in the lockfile is present in the repository\. +. +.IP "\(bu" 4 \fBdisable_multisource\fR (\fBBUNDLE_DISABLE_MULTISOURCE\fR): When set, Gemfiles containing multiple sources will produce errors instead of warnings\. Use \fBbundle config unset disable_multisource\fR to unset\. . .IP "\(bu" 4 diff --git a/lib/bundler/man/bundle-config.1.ronn b/lib/bundler/man/bundle-config.1.ronn index 7ca5dbed72..90ec5ab59e 100644 --- a/lib/bundler/man/bundle-config.1.ronn +++ b/lib/bundler/man/bundle-config.1.ronn @@ -133,9 +133,6 @@ the environment variable `BUNDLE_LOCAL__RACK`. The following is a list of all configuration keys and their purpose. You can learn more about their operation in [bundle install(1)](bundle-install.1.html). -* `allow_bundler_dependency_conflicts` (`BUNDLE_ALLOW_BUNDLER_DEPENDENCY_CONFLICTS`): - Allow resolving to specifications that have dependencies on `bundler` that - are incompatible with the running Bundler version. * `allow_deployment_source_credential_changes` (`BUNDLE_ALLOW_DEPLOYMENT_SOURCE_CREDENTIAL_CHANGES`): When in deployment mode, allow changing the credentials to a gem's source. Ex: `https://some.host.com/gems/path/` -> `https://user_name:[email protected]/gems/path` @@ -178,6 +175,9 @@ learn more about their operation in [bundle install(1)](bundle-install.1.html). * `disable_local_branch_check` (`BUNDLE_DISABLE_LOCAL_BRANCH_CHECK`): Allow Bundler to use a local git override without a branch specified in the Gemfile. +* `disable_local_revision_check` (`BUNDLE_DISABLE_LOCAL_REVISION_CHECK`): + Allow Bundler to use a local git override without checking if the revision + present in the lockfile is present in the repository. * `disable_multisource` (`BUNDLE_DISABLE_MULTISOURCE`): When set, Gemfiles containing multiple sources will produce errors instead of warnings. diff --git a/lib/bundler/man/bundle-doctor.1 b/lib/bundler/man/bundle-doctor.1 index dd3471cfa9..2923517608 100644 --- a/lib/bundler/man/bundle-doctor.1 +++ b/lib/bundler/man/bundle-doctor.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-DOCTOR" "1" "December 2020" "" "" +.TH "BUNDLE\-DOCTOR" "1" "January 2021" "" "" . .SH "NAME" \fBbundle\-doctor\fR \- Checks the bundle for common problems diff --git a/lib/bundler/man/bundle-exec.1 b/lib/bundler/man/bundle-exec.1 index 374d2b11ed..aa0c509278 100644 --- a/lib/bundler/man/bundle-exec.1 +++ b/lib/bundler/man/bundle-exec.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-EXEC" "1" "December 2020" "" "" +.TH "BUNDLE\-EXEC" "1" "January 2021" "" "" . .SH "NAME" \fBbundle\-exec\fR \- Execute a command in the context of the bundle diff --git a/lib/bundler/man/bundle-gem.1 b/lib/bundler/man/bundle-gem.1 index 2ec18ecc65..c1abf90f5c 100644 --- a/lib/bundler/man/bundle-gem.1 +++ b/lib/bundler/man/bundle-gem.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-GEM" "1" "December 2020" "" "" +.TH "BUNDLE\-GEM" "1" "January 2021" "" "" . .SH "NAME" \fBbundle\-gem\fR \- Generate a project skeleton for creating a rubygem diff --git a/lib/bundler/man/bundle-info.1 b/lib/bundler/man/bundle-info.1 index e7386e3699..c715af4063 100644 --- a/lib/bundler/man/bundle-info.1 +++ b/lib/bundler/man/bundle-info.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-INFO" "1" "December 2020" "" "" +.TH "BUNDLE\-INFO" "1" "January 2021" "" "" . .SH "NAME" \fBbundle\-info\fR \- Show information for the given gem in your bundle diff --git a/lib/bundler/man/bundle-init.1 b/lib/bundler/man/bundle-init.1 index 756dc2c67c..6c8f441bdd 100644 --- a/lib/bundler/man/bundle-init.1 +++ b/lib/bundler/man/bundle-init.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-INIT" "1" "December 2020" "" "" +.TH "BUNDLE\-INIT" "1" "January 2021" "" "" . .SH "NAME" \fBbundle\-init\fR \- Generates a Gemfile into the current working directory diff --git a/lib/bundler/man/bundle-inject.1 b/lib/bundler/man/bundle-inject.1 index 4c66eaf78f..2342b44716 100644 --- a/lib/bundler/man/bundle-inject.1 +++ b/lib/bundler/man/bundle-inject.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-INJECT" "1" "December 2020" "" "" +.TH "BUNDLE\-INJECT" "1" "January 2021" "" "" . .SH "NAME" \fBbundle\-inject\fR \- Add named gem(s) with version requirements to Gemfile diff --git a/lib/bundler/man/bundle-install.1 b/lib/bundler/man/bundle-install.1 index 34dca1f0bc..c223185b6f 100644 --- a/lib/bundler/man/bundle-install.1 +++ b/lib/bundler/man/bundle-install.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-INSTALL" "1" "December 2020" "" "" +.TH "BUNDLE\-INSTALL" "1" "January 2021" "" "" . .SH "NAME" \fBbundle\-install\fR \- Install the dependencies specified in your Gemfile diff --git a/lib/bundler/man/bundle-list.1 b/lib/bundler/man/bundle-list.1 index ec507a566b..929b0f79f8 100644 --- a/lib/bundler/man/bundle-list.1 +++ b/lib/bundler/man/bundle-list.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-LIST" "1" "December 2020" "" "" +.TH "BUNDLE\-LIST" "1" "January 2021" "" "" . .SH "NAME" \fBbundle\-list\fR \- List all the gems in the bundle diff --git a/lib/bundler/man/bundle-lock.1 b/lib/bundler/man/bundle-lock.1 index 6f468db581..bcf588a3cf 100644 --- a/lib/bundler/man/bundle-lock.1 +++ b/lib/bundler/man/bundle-lock.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-LOCK" "1" "December 2020" "" "" +.TH "BUNDLE\-LOCK" "1" "January 2021" "" "" . .SH "NAME" \fBbundle\-lock\fR \- Creates / Updates a lockfile without installing diff --git a/lib/bundler/man/bundle-open.1 b/lib/bundler/man/bundle-open.1 index 7131bfad9f..27308ff624 100644 --- a/lib/bundler/man/bundle-open.1 +++ b/lib/bundler/man/bundle-open.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-OPEN" "1" "December 2020" "" "" +.TH "BUNDLE\-OPEN" "1" "January 2021" "" "" . .SH "NAME" \fBbundle\-open\fR \- Opens the source directory for a gem in your bundle diff --git a/lib/bundler/man/bundle-outdated.1 b/lib/bundler/man/bundle-outdated.1 index 8c6ce260c8..40b23568d5 100644 --- a/ |