diff options
author | Hiroshi SHIBATA <[email protected]> | 2021-04-15 12:47:04 +0900 |
---|---|---|
committer | Hiroshi SHIBATA <[email protected]> | 2021-04-15 15:36:15 +0900 |
commit | ed149dbf46d1a8b16e6de9c3dbbcc10f72c9c019 () | |
tree | 1c8c755fa592e280dc7718dc8a9317d1ac368394 | |
parent | 0d9496f924d36534bd524791554d49dc0026b0e0 (diff) |
Merge the master branch of Bundler
Notes: Merged: https://.com/ruby/ruby/pull/4383
95 files changed, 1757 insertions, 564 deletions
@@ -197,7 +197,7 @@ module Bundler def frozen_bundle? frozen = settings[:deployment] - frozen ||= settings[:frozen] unless feature_flag.deployment_means_frozen? frozen end @@ -475,6 +475,12 @@ module Bundler "do in future versions. Instead please use `bundle config set cache_all true`, " \ "and stop using this flag" if ARGV.include?("--all") require_relative "cli/cache" Cache.new(options).run end @@ -591,6 +597,9 @@ module Bundler :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"] || "", :desc => "Generate CI configuration, either Actions, Travis CI, GitLab CI or CircleCI. Set a default with `bundle config set --global gem.ci (|travis|gitlab|circle)`" def gem(name) end @@ -36,10 +36,15 @@ module Bundler def self.without_groups_message(command) command_in_past_tense = command == :install ? "installed" : "updated" groups = Bundler.settings[:without] group_list = [groups[0...-1].join(", "), groups[-1..-1]]. reject {|s| s.to_s.empty? }.join(" and ") group_str = groups.size == 1 ? "group" : "groups" - "Gems in the #{group_str} #{group_list} were not #{command_in_past_tense}." end def self.select_spec(name, regex_match = nil) @@ -53,7 +58,13 @@ module Bundler case specs.count when 0 - raise GemNotFound, gem_not_found_message(name, Bundler.definition.dependencies) when 1 specs.first else @@ -42,9 +42,17 @@ module Bundler use_git = Bundler.git_present? && options[:git] git_author_name = use_git ? `git config user.name`.chomp : "" - _username = use_git ? `git config .user`.chomp : "" git_user_email = use_git ? `git config user.email`.chomp : "" config = { :name => name, :underscored_name => underscored_name, @@ -155,15 +163,16 @@ module Bundler 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://.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 templates.merge!("exe/newgem.tt" => "exe/#{name}") if config[:exe] @@ -308,6 +317,58 @@ module Bundler ci_template end def bundler_dependency_version v = Gem::Version.new(Bundler::VERSION) req = v.segments[0..1] @@ -33,12 +33,8 @@ module Bundler options[:local] = true if Bundler.app_cache.exist? - if Bundler.feature_flag.deployment_means_frozen? - Bundler.settings.set_command_option :deployment, true - else - Bundler.settings.set_command_option :deployment, true if options[:deployment] - Bundler.settings.set_command_option :frozen, true if options[:frozen] - end end # When install is called with --no-deployment, disable deployment mode @@ -72,7 +72,7 @@ module Bundler gemfile_specs + dependency_specs end - specs.sort_by(&:name).each do |current_spec| next unless gems.empty? || gems.include?(current_spec.name) active_spec = retrieve_active_spec(definition, current_spec) @@ -92,11 +92,11 @@ module Bundler def checksum_for_file(path) return nil unless path.file? - # This must use IO.read instead of Digest.file().hexdigest # because we need to preserve \n line endings on windows when calculating # the checksum SharedHelpers.filesystem_access(path, :read) do - SharedHelpers.digest(:MD5).hexdigest(IO.read(path)) end end end @@ -111,6 +111,17 @@ module Bundler @locked_platforms = [] end @unlock[:gems] ||= [] @unlock[:sources] ||= [] @unlock[:ruby] ||= if @ruby_version && locked_ruby_version_object @@ -150,6 +161,10 @@ module Bundler end end def resolve_with_cache! raise "Specs already loaded" if @specs sources.cached! @@ -177,10 +192,10 @@ module Bundler gem_name, gem_version = extract_gem_info(e) locked_gem = @locked_specs[gem_name].last raise if locked_gem.nil? || locked_gem.version.to_s != gem_version || !@remote - raise GemNotFound, "Your bundle is locked to #{locked_gem}, but that version could not " \ - "be found in any of the sources listed in your Gemfile. If you haven't changed sources, " \ - "that means the author of #{locked_gem} has removed it. You'll need to update your bundle " \ - "to a version other than #{locked_gem} that hasn't been removed in order to install." end unless specs["bundler"].any? bundler = sources.metadata_source.specs.search(Gem::Dependency.new("bundler", VERSION)).last @@ -537,6 +552,9 @@ module Bundler attr_reader :sources private :sources def nothing_changed? !@source_changes && !@dependency_changes && !@new_platform && !@path_changes && !@local_changes && !@locked_specs_incomplete_for_platform end @@ -661,10 +679,8 @@ module Bundler end def converge_rubygems_sources - return false if Bundler.feature_flag.disable_multisource? - # 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 @@ -950,7 +966,7 @@ module Bundler end def additional_base_requirements_for_resolve - return [] unless @locked_gems && Bundler.feature_flag.only_update_to_newer_versions? dependencies_by_name = dependencies.inject({}) {|memo, dep| memo.update(dep.name => dep) } @locked_gems.specs.reduce({}) do |requirements, locked_spec| name = locked_spec.name @@ -460,19 +460,16 @@ repo_name ||= user_name @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. 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. " \ "Using `source` more than once without a block is a security risk, and " \ "may result in installing unexpected gems. To resolve this warning, use " \ - "a block to indicate which gems should come from the secondary source. " \ - "To upgrade this warning to an error, run `bundle config set --local " \ - "disable_multisource true`." end end @@ -31,11 +31,9 @@ module Bundler settings_flag(:auto_clean_without_path) { bundler_3_mode? } settings_flag(:cache_all) { bundler_3_mode? } settings_flag(:default_install_uses_path) { bundler_3_mode? } - settings_flag(:deployment_means_frozen) { bundler_3_mode? } settings_flag(:disable_multisource) { bundler_3_mode? } settings_flag(:forget_cli_options) { bundler_3_mode? } settings_flag(:global_gem_cache) { bundler_3_mode? } - settings_flag(:only_update_to_newer_versions) { bundler_3_mode? } settings_flag(:path_relative_to_cwd) { bundler_3_mode? } settings_flag(:plugins) { @bundler_version >= Gem::Version.new("1.14") } settings_flag(:print_only_version_number) { bundler_3_mode? } @@ -47,6 +47,11 @@ module Bundler built_gem_path = build_gem end desc "Build and install #{name}-#{version}.gem into system gems." task "install" => "build" do install_gem(built_gem_path) @@ -100,6 +105,17 @@ module Bundler Bundler.ui.confirm "#{name} (#{version}) installed." end protected def rubygem_push(path) @@ -128,7 +128,7 @@ module Bundler # evaluates a gemfile to remove the specified gem # from it. def remove_deps(gemfile_path) - initial_gemfile = IO.readlines(gemfile_path) Bundler.ui.info "Removing gems from #{gemfile_path}" @@ -181,7 +181,7 @@ module Bundler patterns = /gem\s+(['"])#{Regexp.union(gems)}\1|gem\s*\((['"])#{Regexp.union(gems)}\2\)/ new_gemfile = [] multiline_removal = false - IO.readlines(gemfile_path).each do |line| match_data = line.match(patterns) if match_data && is_not_within_comment?(line, match_data) multiline_removal = line.rstrip.end_with?(",") @@ -52,7 +52,7 @@ def gemfile(install = false, options = {}, &gemfile) builder.instance_eval(&gemfile) builder.check_primary_source_safety - Bundler.settings.temporary(:frozen => false) do definition = builder.to_definition(nil, true) def definition.lock(*); end definition.validate_runtime! @@ -6,10 +6,11 @@ require_relative "gem_installer" module Bundler class ParallelInstaller class SpecInstallation - attr_accessor :spec, :name, :post_install_message, :state, :error def initialize(spec) @spec = spec @name = spec.name @state = :none @post_install_message = "" @error = nil @@ -27,13 +28,8 @@ module Bundler state == :failed end - def installation_attempted? - installed? || failed? - end - - # Only true when spec in neither installed nor already enqueued def ready_to_enqueue? - !enqueued? && !installation_attempted? end def has_post_install_message? @@ -54,14 +50,11 @@ module Bundler # Represents only the non-development dependencies, the ones that are # itself and are in the total list. def dependencies - @dependencies ||= begin - all_dependencies.reject {|dep| ignorable_dependency? dep } - end end def missing_lockfile_dependencies(all_spec_names) - deps = all_dependencies.reject {|dep| ignorable_dependency? dep } - deps.reject {|dep| all_spec_names.include? dep.name } end # Represents all dependencies @@ -70,7 +63,7 @@ module Bundler end def to_s - "#<#{self.class} #{@spec.full_name} (#{state})>" end end @@ -93,18 +86,48 @@ module Bundler def call check_for_corrupt_lockfile if @size > 1 install_with_worker else install_serially end handle_error if failed_specs.any? @specs ensure worker_pool && worker_pool.stop end def check_for_corrupt_lockfile missing_dependencies = @specs.map do |s| [ @@ -217,8 +240,6 @@ module Bundler # are installed. def enqueue_specs @specs.select(&:ready_to_enqueue?).each do |spec| - next if @rake && [email protected]? && spec.name != @rake.name - if spec.dependencies_installed? @specs spec.state = :enqueued worker_pool.enq spec @@ -73,7 +73,12 @@ module Bundler same_platform_candidates = candidates.select do |spec| MatchPlatform.platforms_match?(spec.platform, platform_object) end - search = same_platform_candidates.last || candidates.last search.dependencies = dependencies if search && (search.is_a?(RemoteSpecification) || search.is_a?(EndpointSpecification)) search end @@ -131,18 +131,8 @@ module Bundler @sources << @current_source end when GEM - source_remotes = Array(@opts["remote"]) - - if source_remotes.size == 1 - @opts["remotes"] = @opts.delete("remote") - @current_source = TYPES[@type].from_lock(@opts) - else - source_remotes.each do |url| - rubygems_aggregate.add_remote(url) - end - @current_source = rubygems_aggregate - end - @sources << @current_source when PLUGIN @current_source = Plugin.source_from_lock(@opts) @@ -245,9 +235,5 @@ module Bundler def parse_ruby(line) @ruby_version = line.strip end - - def rubygems_aggregate - @rubygems_aggregate ||= Source::Rubygems.new - end end end @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-ADD" "1" "January 2021" "" "" . .SH "NAME" \fBbundle\-add\fR \- Add gem to the Gemfile and run bundle install @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-BINSTUBS" "1" "January 2021" "" "" . .SH "NAME" \fBbundle\-binstubs\fR \- Install the binstubs of the listed gems @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-CACHE" "1" "January 2021" "" "" . .SH "NAME" \fBbundle\-cache\fR \- Package your needed \fB\.gem\fR files into your application @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-CHECK" "1" "January 2021" "" "" . .SH "NAME" \fBbundle\-check\fR \- Verifies if dependencies are satisfied by installed gems @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-CLEAN" "1" "January 2021" "" "" . .SH "NAME" \fBbundle\-clean\fR \- Cleans up unused gems in your bundler directory @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-CONFIG" "1" "January 2021" "" "" . .SH "NAME" \fBbundle\-config\fR \- Set bundler configuration options @@ -199,6 +199,9 @@ The following is a list of all configuration keys and their purpose\. You can le \fBfrozen\fR (\fBBUNDLE_FROZEN\fR): Disallow changes to the \fBGemfile\fR\. When the \fBGemfile\fR is changed and the lockfile has not been updated, running Bundler commands will be blocked\. Defaults to \fBtrue\fR when \fB\-\-deployment\fR is used\. . .IP "\(bu" 4 \fBgem\.push_key\fR (\fBBUNDLE_GEM__PUSH_KEY\fR): Sets the \fB\-\-key\fR parameter for \fBgem push\fR when using the \fBrake release\fR command with a private gemstash server\. . .IP "\(bu" 4 @@ -223,9 +226,6 @@ The following is a list of all configuration keys and their purpose\. You can le \fBno_prune\fR (\fBBUNDLE_NO_PRUNE\fR): Whether Bundler should leave outdated gems unpruned when caching\. . .IP "\(bu" 4 -\fBonly_update_to_newer_versions\fR (\fBBUNDLE_ONLY_UPDATE_TO_NEWER_VERSIONS\fR): During \fBbundle update\fR, only resolve to newer versions of the gems in the lockfile\. -. -.IP "\(bu" 4 \fBpath\fR (\fBBUNDLE_PATH\fR): The location on disk where all gems in your bundle will be located regardless of \fB$GEM_HOME\fR or \fB$GEM_PATH\fR values\. Bundle gems not found in this location will be installed by \fBbundle install\fR\. Defaults to \fBGem\.dir\fR\. When \-\-deployment is used, defaults to vendor/bundle\. . .IP "\(bu" 4 @@ -194,6 +194,10 @@ learn more about their operation in [bundle install(1)](bundle-install.1.html). Disallow changes to the `Gemfile`. When the `Gemfile` is changed and the lockfile has not been updated, running Bundler commands will be blocked. Defaults to `true` when `--deployment` is used. * `gem.push_key` (`BUNDLE_GEM__PUSH_KEY`): Sets the `--key` parameter for `gem push` when using the `rake release` command with a private gemstash server. @@ -218,9 +222,6 @@ learn more about their operation in [bundle install(1)](bundle-install.1.html). Whether `bundle package` should skip installing gems. * `no_prune` (`BUNDLE_NO_PRUNE`): Whether Bundler should leave outdated gems unpruned when caching. -* `only_update_to_newer_versions` (`BUNDLE_ONLY_UPDATE_TO_NEWER_VERSIONS`): - During `bundle update`, only resolve to newer versions of the gems in the - lockfile. * `path` (`BUNDLE_PATH`): The location on disk where all gems in your bundle will be located regardless of `$GEM_HOME` or `$GEM_PATH` values. Bundle gems not found in this location @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-DOCTOR" "1" "January 2021" "" "" . .SH "NAME" \fBbundle\-doctor\fR \- Checks the bundle for common problems @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-EXEC" "1" "January 2021" "" "" . .SH "NAME" \fBbundle\-exec\fR \- Execute a command in the context of the bundle @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-GEM" "1" "January 2021" "" "" . .SH "NAME" \fBbundle\-gem\fR \- Generate a project skeleton for creating a rubygem @@ -90,6 +90,19 @@ When Bundler is configured to not generate CI files, an interactive prompt will When Bundler is unconfigured, an interactive prompt will be displayed and the answer will be saved in Bundler\'s global config for future \fBbundle gem\fR use\. . .TP \fB\-e\fR, \fB\-\-edit[=EDITOR]\fR Open the resulting GEM_NAME\.gemspec in EDITOR, or the default editor if not specified\. The default is \fB$BUNDLER_EDITOR\fR, \fB$VISUAL\fR, or \fB$EDITOR\fR\. . @@ -92,6 +92,22 @@ configuration file using the following names: the answer will be saved in Bundler's global config for future `bundle gem` use. * `-e`, `--edit[=EDITOR]`: Open the resulting GEM_NAME.gemspec in EDITOR, or the default editor if not specified. The default is `$BUNDLER_EDITOR`, `$VISUAL`, or `$EDITOR`. @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-INFO" "1" "January 2021" "" "" . .SH "NAME" \fBbundle\-info\fR \- Show information for the given gem in your bundle @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-INIT" "1" "January 2021" "" "" . .SH "NAME" \fBbundle\-init\fR \- Generates a Gemfile into the current working directory @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-INJECT" "1" "January 2021" "" "" . .SH "NAME" \fBbundle\-inject\fR \- Add named gem(s) with version requirements to Gemfile @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-INSTALL" "1" "January 2021" "" "" . .SH "NAME" \fBbundle\-install\fR \- Install the dependencies specified in your Gemfile @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-LIST" "1" "January 2021" "" "" . .SH "NAME" \fBbundle\-list\fR \- List all the gems in the bundle @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-LOCK" "1" "January 2021" "" "" . .SH "NAME" \fBbundle\-lock\fR \- Creates / Updates a lockfile without installing @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-OPEN" "1" "January 2021" "" "" . .SH "NAME" \fBbundle\-open\fR \- Opens the source directory for a gem in your bundle @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-OUTDATED" "1" "January 2021" "" "" . .SH "NAME" \fBbundle\-outdated\fR \- List installed gems with newer versions available @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-PLATFORM" "1" "January 2021" "" "" . .SH "NAME" \fBbundle\-platform\fR \- Displays platform compatibility information @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-PRISTINE" "1" "January 2021" "" "" . .SH "NAME" \fBbundle\-pristine\fR \- Restores installed gems to their pristine condition @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-REMOVE" "1" "January 2021" "" "" . .SH "NAME" \fBbundle\-remove\fR \- Removes gems from the Gemfile @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-SHOW" "1" "January 2021" "" "" . .SH "NAME" \fBbundle\-show\fR \- Shows all the gems in your bundle, or the path to a gem @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-UPDATE" "1" "January 2021" "" "" . .SH "NAME" \fBbundle\-update\fR \- Update your gems to the latest available versions @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-VIZ" "1" "January 2021" "" "" . .SH "NAME" \fBbundle\-viz\fR \- Generates a visual dependency graph for your Gemfile @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE" "1" "January 2021" "" "" . .SH "NAME" \fBbundle\fR \- Ruby Dependency Management @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://.com/rtomayko/ronn/tree/0.7.3 . -.TH "GEMFILE" "5" "January 2021" "" "" . .SH "NAME" \fBGemfile\fR \- A format for describing gem dependencies for Ruby programs @@ -140,6 +140,13 @@ module Bundler end end # Set internal representation to fetch the gems/specs from remote. # # When this is called, the source should try to fetch the specs and @@ -15,7 +15,6 @@ module Bundler cache_all_platforms default_install_uses_path deployment - deployment_means_frozen disable_checksum_validation disable_exec_load disable_local_branch_check @@ -33,7 +32,6 @@ module Bundler init_gems_rb no_install no_prune - only_update_to_newer_versions path_relative_to_cwd path.system plugins @@ -33,6 +33,12 @@ module Bundler spec.source == self end # it's possible that gems from one source depend on gems from some # other source, so now we download gemspecs and iterate over those # dependencies, looking for gems we don't have info on yet. @@ -33,10 +33,6 @@ module Bundler end end - def cached!; end - - def remote!; end - def options {} end @@ -82,7 +82,9 @@ module Bundler end def install(spec, options = {}) - print_using_message "Using #{version_message(spec)} from #{self}" generate_bin(spec, :disable_extensions => true) nil # no post-install message end @@ -35,7 +35,7 @@ module Bundler run_hooks(:post_build) end - generate_bin unless spec.executables.nil? || spec.executables.empty? run_hooks(:post_install) ensure @@ -20,17 +20,29 @@ module Bundler @dependency_names = [] @allow_remote = false @allow_cached = false @caches = [cache_path, *Bundler.rubygems.gem_cache] - Array(options["remotes"] || []).reverse_each {|r| add_remote(r) } end def remote! @specs = nil @allow_remote = true end def cached! @specs = nil @allow_cached = true end @@ -49,8 +61,12 @@ module Bundler o.is_a?(Rubygems) && (o.credless_remotes - credless_remotes).empty? end def can_lock?(spec) - return super if Bundler.feature_flag.disable_multisource? spec.source.is_a?(Rubygems) end @@ -87,7 +103,7 @@ module Bundler # small_idx.use large_idx. idx = @allow_remote ? remote_specs.dup : Index.new idx.use(cached_specs, :override_dupes) if @allow_cached || @allow_remote - idx.use(installed_specs, :override_dupes) idx end end @@ -365,7 +381,7 @@ module Bundler def cached_specs @cached_specs ||= begin - idx = installed_specs.dup Dir["#{cache_path}/*.gem"].each do |gemfile| next if gemfile =~ /^bundler\-[\d\.]+?\.gem/ @@ -9,7 +9,7 @@ module Bundler :metadata_source def global_rubygems_source - @global_rubygems_source ||= rubygems_aggregate_class.new end def initialize @@ -20,6 +20,16 @@ module Bundler @global_path_source = nil @rubygems_sources = [] @metadata_source = Source::Metadata.new end def add_path_source(options = {}) @@ -47,7 +57,7 @@ module Bundler end def global_rubygems_source=(uri) - @global_rubygems_source ||= rubygems_aggregate_class.new("remotes" => uri) end def add_rubygems_remote(uri) @@ -77,8 +87,8 @@ module Bundler def lock_sources lock_sources = (path_sources + git_sources + plugin_sources).sort_by(&:to_s) - if Bundler.feature_flag.disable_multisource? - lock_sources + rubygems_sources.sort_by(&:to_s) else lock_sources << combine_rubygems_sources end @@ -94,7 +104,7 @@ module Bundler end end - replacement_rubygems = !Bundler.feature_flag.disable_multisource? && replacement_sources.detect {|s| s.is_a?(Source::Rubygems) } @global_rubygems_source = replacement_rubygems if replacement_rubygems @@ -82,6 +82,7 @@ module Bundler materialized.map! do |s| next s unless s.is_a?(LazySpecification) s.source.dependency_names = deps if s.source.respond_to?(:dependency_names=) spec = s.__materialize__ unless spec unless missing_specs @@ -102,6 +103,7 @@ module Bundler @specs.map do |s| next s unless s.is_a?(LazySpecification) s.source.dependency_names = names if s.source.respond_to?(:dependency_names=) s.source.remote! spec = s.__materialize__ raise GemNotFound, "Could not find #{s.full_name} in any of the sources" unless spec @@ -2,6 +2,6 @@ source "https://rubygems.org" -git_source(:) {|repo_name| "https://.com/#{repo_name}" } # gem "rails" @@ -3,6 +3,6 @@ # A sample gems.rb source "https://rubygems.org" -git_source(:) {|repo_name| "https://.com/#{repo_name}" } # gem "rails" @@ -14,7 +14,10 @@ gem "rake-compiler" gem "<%= config[:test] %>", "~> <%= config[:test_framework_version] %>" <%- end -%> -<%- if config[:rubocop] -%> -gem "rubocop", "~> <%= config[:rubocop_version] %>" <%- end -%> @@ -27,12 +27,16 @@ require "rspec/core/rake_task" RSpec::Core::RakeTask.new(:spec) <% end -%> -<% if config[:rubocop] -%> <% default_task_names << :rubocop -%> require "rubocop/rake_task" RuboCop::RakeTask.new <% end -%> <% if config[:ext] -%> <% default_task_names.unshift(:clobber, :compile) -%> @@ -11,8 +11,6 @@ jobs: uses: ruby/setup-ruby@v1 with: ruby-version: <%= RUBY_VERSION %> - name: Run the default task - run: | - gem install bundler -v <%= Bundler::VERSION %> - bundle install - bundle exec rake @@ -3,16 +3,16 @@ require_relative "lib/<%=config[:namespaced_path]%>/version" Gem::Specification.new do |spec| - spec.name = <%= config[:name].inspect %> - spec.version = <%= config[:constant_name] %>::VERSION - spec.authors = [<%= config[:author].inspect %>] - spec.email = [<%= config[:email].inspect %>] - - spec.summary = "TODO: Write a short summary, because RubyGems requires one." - spec.description = "TODO: Write a longer description or delete this line." - spec.homepage = "TODO: Put your gem's website or public repo URL here." <%- if config[:mit] -%> - spec.license = "MIT" <%- end -%> spec.required_ruby_version = Gem::Requirement.new(">= <%= config[:required_ruby_version] %>") @@ -29,11 +29,11 @@ Gem::Specification.new do |spec| f.match(%r{\A(?:(?:test|spec|features)/|\.(?:git|travis|circleci)|appveyor)}) end end - spec.bindir = "exe" - spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) } spec.require_paths = ["lib"] <%- if config[:ext] -%> - spec.extensions = ["ext/<%= config[:underscored_name] %>/extconf.rb"] <%- end -%> # Uncomment to register a new dependency of your gem @@ -0,0 +1,4 @@ @@ -115,7 +115,7 @@ class Bundler::Dir < Dir Bundler::Dir.tmpdir end - UNUSABLE_CHARS = [File::SEPARATOR, File::ALT_SEPARATOR, File::PATH_SEPARATOR, ":"].uniq.join("").freeze class << (RANDOM = Random.new) MAX = 36**6 # < 0x100000000 @@ -22,7 +22,7 @@ RSpec.describe Bundler::DepProxy do end describe "frozen" do - if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("2.5.0") error = Object.const_get("FrozenError") else error = RuntimeError @@ -9,7 +9,7 @@ RSpec.describe Bundler::GemHelper do let(:app_gemspec_path) { app_path.join("#{app_name}.gemspec") } before(:each) do - global_config "BUNDLE_GEM__MIT" => "false", "BUNDLE_GEM__TEST" => "false", "BUNDLE_GEM__COC" => "false", "BUNDLE_GEM__RUBOCOP" => "false", "BUNDLE_GEM__CI" => "false", "BUNDLE_GEM__CHANGELOG" => "false" bundle "gem #{app_name}" prepare_gemspec(app_gemspec_path) @@ -61,10 +61,16 @@ RSpec.describe Bundler::GemHelper do mock_confirm_message message end subject! { Bundler::GemHelper.new(app_path) } let(:app_version) { "0.1.0" } let(:app_gem_dir) { app_path.join("pkg") } let(:app_gem_path) { app_gem_dir.join("#{app_name}-#{app_version}.gem") } let(:app_gemspec_content) { File.read(app_gemspec_path) } before(:each) do @@ -162,6 +168,37 @@ RSpec.describe Bundler::GemHelper do end end describe "#install_gem" do context "when installation was successful" do it "gem is installed" do @@ -44,4 +44,37 @@ The missing gems are: end end end end @@ -8,6 +8,10 @@ RSpec.describe Bundler::ParallelInstaller::SpecInstallation do def a_spec.name "I like tests" end a_spec end @@ -372,26 +372,7 @@ RSpec.describe Bundler::SourceList do source_list.add_git_source("uri" => "git://first-git.org/path.git") end - it "combines the rubygems sources into a single instance, removing duplicate remotes from the end", :bundler => "< 3" do - expect(source_list.lock_sources).to eq [ - Bundler::Source::Git.new("uri" => "git://first-git.org/path.git"), - Bundler::Source::Git.new("uri" => "git://second-git.org/path.git"), - Bundler::Source::Git.new("uri" => "git://third-git.org/path.git"), - ASourcePlugin.new("uri" => "https://second-plugin.org/random"), - ASourcePlugin.new("uri" => "https://third-bar.org/foo"), - Bundler::Source::Path.new("path" => "/first/path/to/gem"), - Bundler::Source::Path.new("path" => "/second/path/to/gem"), - Bundler::Source::Path.new("path" => "/third/path/to/gem"), - Bundler::Source::Rubygems.new("remotes" => [ - "https://duplicate-rubygems.org", - "https://first-rubygems.org", - "https://second-rubygems.org", - "https://third-rubygems.org", - ]), - ] - end - - it "returns all sources, without combining rubygems sources", :bundler => "3" do expect(source_list.lock_sources).to eq [ Bundler::Source::Git.new("uri" => "git://first-git.org/path.git"), Bundler::Source::Git.new("uri" => "git://second-git.org/path.git"), @@ -182,4 +182,18 @@ RSpec.describe "bundle info" do expect(err).to include("Could not find gem '#{invalid_regexp}'.") end end end @@ -86,7 +86,7 @@ RSpec.describe "bundle lock" do it "does not fetch remote specs when using the --local option" do bundle "lock --update --local", :raise_on_error => false - expect(err).to match(/sources listed in your Gemfile|installed locally/) end it "works with --gemfile flag" do @@ -12,15 +12,16 @@ RSpec.describe "bundle gem" do def bundle_exec_rubocop prepare_gemspec(bundled_app(gem_name, "#{gem_name}.gemspec")) - rubocop_version = RUBY_VERSION > "2.4" ? "1.7.0" : "0.81.0" - gems = ["minitest", "rake", "rake-compiler", "rspec", "rubocop -v #{rubocop_version}", "test-unit"] - gems.unshift "parallel -v 1.19.2" if RUBY_VERSION < "2.5" - gems += ["rubocop-ast -v 1.4.0"] if rubocop_version == "1.7.0" - path = Bundler.feature_flag.default_install_uses_path? ? local_gem_path(:base => bundled_app(gem_name)) : system_gem_path - realworld_system_gems gems, :path => path bundle "exec rubocop --debug --config .rubocop.yml", :dir => bundled_app(gem_name) end let(:generated_gemspec) { Bundler.load_gemspec_uncached(bundled_app(gem_name).join("#{gem_name}.gemspec")) } let(:gem_name) { "mygem" } @@ -102,7 +103,7 @@ RSpec.describe "bundle gem" do expect(bundled_app("#{gem_name}/README.md").read).to match(%r{https://\.com/bundleuser/#{gem_name}/blob/.*/CODE_OF_CONDUCT.md}) end - it "generates the README with a section for the Code of Conduct, respecting the configured git default branch" do sys_exec("git config --global init.defaultBranch main") bundle "gem #{gem_name} --coc" @@ -147,8 +148,68 @@ RSpec.describe "bundle gem" do end shared_examples_for "--rubocop flag" do before do - bundle "gem #{gem_name} --rubocop" end it "generates a gem skeleton with rubocop" do @@ -175,11 +236,38 @@ RSpec.describe "bundle gem" do end end - shared_examples_for "--no-rubocop flag" do define_negated_matcher :exclude, :include before do - bundle "gem #{gem_name} --no-rubocop" end it "generates a gem skeleton without rubocop" do @@ -197,46 +285,66 @@ RSpec.describe "bundle gem" do expect(rubocop_dep).to be_nil end it "doesn't generate a default .rubocop.yml" do expect(bundled_app("#{gem_name}/.rubocop.yml")).to_not exist end end - it "has no rubocop offenses when using --rubocop flag", :readline do skip "ruby_core has an 'ast.rb' file that gets in the middle and breaks this spec" if ruby_core? - bundle "gem #{gem_name} --rubocop" bundle_exec_rubocop expect(err).to be_empty end - it "has no rubocop offenses when using --ext and --rubocop flag", :readline do skip "ruby_core has an 'ast.rb' file that gets in the middle and breaks this spec" if ruby_core? - bundle "gem #{gem_name} --ext --rubocop" bundle_exec_rubocop expect(err).to be_empty end - it "has no rubocop offenses when using --ext, --test=minitest, and --rubocop flag", :readline do skip "ruby_core has an 'ast.rb' file that gets in the middle and breaks this spec" if ruby_core? - bundle "gem #{gem_name} --ext --test=minitest --rubocop" bundle_exec_rubocop expect(err).to be_empty end - it "has no rubocop offenses when using --ext, --test=rspec, and --rubocop flag", :readline do skip "ruby_core has an 'ast.rb' file that gets in the middle and breaks this spec" if ruby_core? - bundle "gem #{gem_name} --ext --test=rspec --rubocop" bundle_exec_rubocop expect(err).to be_empty end - it "has no rubocop offenses when using --ext, --ext=test-unit, and --rubocop flag", :readline do skip "ruby_core has an 'ast.rb' file that gets in the middle and breaks this spec" if ruby_core? - bundle "gem #{gem_name} --ext --test=test-unit --rubocop" bundle_exec_rubocop expect(err).to be_empty end shared_examples_for "CI config is absent" do it "does not create any CI files" do expect(bundled_app("#{gem_name}/./workflows/main.yml")).to_not exist @@ -351,6 +459,55 @@ RSpec.describe "bundle gem" do end end shared_examples_for "generating a gem" do it "generates a gem skeleton" do bundle "gem #{gem_name}" @@ -841,6 +998,127 @@ RSpec.describe "bundle gem" do end end context "--edit option" do it "opens the generated gemspec in the user's text editor" do output = bundle "gem #{gem_name} --edit=echo" @@ -891,6 +1169,9 @@ RSpec.describe "bundle gem" do before do global_config "BUNDLE_GEM__RUBOCOP" => "true" end it_behaves_like "--rubocop flag" it_behaves_like "--no-rubocop flag" end @@ -899,10 +1180,40 @@ RSpec.describe "bundle gem" do before do global_config "BUNDLE_GEM__RUBOCOP" => "false" end it_behaves_like "--rubocop flag" it_behaves_like "--no-rubocop flag" end context "with changelog option in bundle config settings set to true" do before do global_config "BUNDLE_GEM__CHANGELOG" => "true" @@ -920,6 +1231,57 @@ RSpec.describe "bundle gem" do end end context "gem naming with underscore", :readline do let(:gem_name) { "test_gem" } @@ -1073,7 +1435,7 @@ Usage: "bundle gem NAME [OPTIONS]" end it "asks about CI service" do - global_config "BUNDLE_GEM__TEST" => "false", "BUNDLE_GEM__MIT" => "false", "BUNDLE_GEM__COC" => "false", "BUNDLE_GEM__RUBOCOP" => "false" bundle "gem foobar" do |input, _, _| input.puts "" @@ -1083,7 +1445,7 @@ Usage: "bundle gem NAME [OPTIONS]" end it "asks about MIT license" do - global_config "BUNDLE_GEM__TEST" => "false", "BUNDLE_GEM__COC" => "false", "BUNDLE_GEM__CI" => "false", "BUNDLE_GEM__RUBOCOP" => "false" bundle "config list" @@ -1095,7 +1457,7 @@ Usage: "bundle gem NAME [OPTIONS]" end it "asks about CoC" do - global_config "BUNDLE_GEM__MIT" => "false", "BUNDLE_GEM__TEST" => "false", "BUNDLE_GEM__CI" => "false", "BUNDLE_GEM__RUBOCOP" => "false" bundle "gem foobar" do |input, _, _| input.puts "yes" @@ -1105,7 +1467,7 @@ Usage: "bundle gem NAME [OPTIONS]" end it "asks about CHANGELOG" do - global_config "BUNDLE_GEM__MIT" => "false", "BUNDLE_GEM__TEST" => "false", "BUNDLE_GEM__CI" => "false", "BUNDLE_GEM__RUBOCOP" => "false", "BUNDLE_GEM__COC" => "false" bundle "gem foobar" do |input, _, _| @@ -929,4 +929,54 @@ RSpec.describe "bundle outdated" do expect(out).to end_with(expected_output) end end end @@ -32,21 +32,21 @@ RSpec.describe "post bundle message" do bundle "config set --local without emo" bundle :install expect(out).to include(bundle_show_message) - expect(out).to include("Gems in the group emo were not installed") expect(out).to include(bundle_complete_message) expect(out).to include(installed_gems_stats) bundle "config set --local without emo test" bundle :install expect(out).to include(bundle_show_message) - expect(out).to include("Gems in the groups emo and test were not installed") expect(out).to include(bundle_complete_message) expect(out).to include("4 Gemfile dependencies, 3 gems now installed.") bundle "config set --local without emo obama test" bundle :install expect(out).to include(bundle_show_message) - expect(out).to include("Gems in the groups emo, obama and test were not installed") expect(out).to include(bundle_complete_message) expect(out).to include("4 Gemfile dependencies, 2 gems now installed.") end @@ -65,21 +65,21 @@ RSpec.describe "post bundle message" do bundle "config set --local without emo" bundle :install expect(out).to include(bundle_show_path_message) - expect(out).to include("Gems in the group emo were not installed") expect(out).to include(bundle_complete_message) bundle "config set --local path vendor" bundle "config set --local without emo test" bundle :install expect(out).to include(bundle_show_path_message) - expect(out).to include("Gems in the groups emo and test were not installed") expect(out).to include(bundle_complete_message) bundle "config set --local path vendor" bundle "config set --local without emo obama test" bundle :install expect(out).to include(bundle_show_path_message) - expect(out).to include("Gems in the groups emo, obama and test were not installed") expect(out).to include(bundle_complete_message) end end @@ -156,7 +156,7 @@ The source does not contain any versions of 'not-a-gem' bundle "install --without emo" bundle :install expect(out).to include(bundle_show_message) - expect(out).to include("Gems in the group emo were not installed") expect(out).to include(bundle_complete_message) expect(out).to include(installed_gems_stats) end @@ -165,7 +165,7 @@ The source does not contain any versions of 'not-a-gem' bundle "install --without emo test" bundle :install expect(out).to include(bundle_show_message) - expect(out).to include("Gems in the groups emo and test were not installed") expect(out).to include(bundle_complete_message) end @@ -173,7 +173,7 @@ The source does not contain any versions of 'not-a-gem' bundle "install --without emo obama test" bundle :install expect(out).to include(bundle_show_message) - expect(out).to include("Gems in the groups emo, obama and test were not installed") expect(out).to include(bundle_complete_message) end end @@ -187,19 +187,19 @@ The source does not contain any versions of 'not-a-gem' bundle "config set --local without emo" bundle :install bundle :update, :all => true - expect(out).to include("Gems in the group emo were not updated") expect(out).to include(bundle_updated_message) bundle "config set --local without emo test" bundle :install bundle :update, :all => true - expect(out).to include("Gems in the groups emo and test were not updated") expect(out).to include(bundle_updated_message) bundle "config set --local without emo obama test" bundle :install bundle :update, :all => true - expect(out).to include("Gems in the groups emo, obama and test were not updated") expect(out).to include(bundle_updated_message) end end @@ -148,72 +148,66 @@ RSpec.describe "bundle update" do end describe "when a possible resolve requires an older version of a locked gem" do - context "and only_update_to_newer_versions is set" do - before do - bundle "config set only_update_to_newer_versions true" - end - - it "does not go to an older version" do - build_repo4 do - build_gem "tilt", "2.0.8" - build_gem "slim", "3.0.9" do |s| - s.add_dependency "tilt", [">= 1.3.3", "< 2.1"] - end - build_gem "slim_lint", "0.16.1" do |s| - s.add_dependency "slim", [">= 3.0", "< 5.0"] - end - build_gem "slim-rails", "0.2.1" do |s| - s.add_dependency "slim", ">= 0.9.2" - end - build_gem "slim-rails", "3.1.3" do |s| - s.add_dependency "slim", "~> 3.0" - end end - install_gemfile <<-G - source "#{file_uri_for(gem_repo4)}" - gem "slim-rails" - gem "slim_lint" - G - expect(the_bundle).to include_gems("slim 3.0.9", "slim-rails 3.1.3", "slim_lint 0.16.1") - update_repo4 do - build_gem "slim", "4.0.0" do |s| - s.add_dependency "tilt", [">= 2.0.6", "< 2.1"] - end end - bundle "update", :all => true - expect(the_bundle).to include_gems("slim 3.0.9", "slim-rails 3.1.3", "slim_lint 0.16.1") - end - it "should still downgrade if forced by the Gemfile" do - build_repo4 do - build_gem "a" - build_gem "b", "1.0" - build_gem "b", "2.0" - end - install_gemfile <<-G - source "#{file_uri_for(gem_repo4)}" - gem "a" - gem "b" - G - expect(the_bundle).to include_gems("a 1.0", "b 2.0") - gemfile <<-G - source "#{file_uri_for(gem_repo4)}" - gem "a" - gem "b", "1.0" - G - bundle "update b" - expect(the_bundle).to include_gems("a 1.0", "b 1.0") - end end end @@ -126,21 +126,21 @@ RSpec.describe "install in deployment or frozen mode" do bundle "config set --local path vendor/bundle" bundle "install" gemfile <<-G - source "http://user_name:[email protected]/" - gem "rack" G lockfile <<-G - GEM - remote: http://localgemserver.test/ - specs: - rack (1.0.0) - PLATFORMS - #{local} - DEPENDENCIES - rack G bundle "config set --local deployment true" @@ -259,7 +259,7 @@ RSpec.describe "bundle install from an existing gemspec" do expect(out).to eq("WIN") end - it "works with only_update_to_newer_versions" do build_lib "omg", "2.0", :path => lib_path("omg") install_gemfile <<-G @@ -268,7 +268,7 @@ RSpec.describe "bundle install from an existing gemspec" do build_lib "omg", "1.0", :path => lib_path("omg") - bundle :install, :env => { "BUNDLE_BUNDLE_ONLY_UPDATE_TO_NEWER_VERSIONS" => "true" } expect(the_bundle).to include_gems "omg 1.0" end @@ -173,7 +173,7 @@ RSpec.describe "bundle install with explicit source paths" do expect(the_bundle).to include_gems "foo 1.0" end - it "works with only_update_to_newer_versions" do build_lib "omg", "2.0", :path => lib_path("omg") install_gemfile <<-G @@ -182,7 +182,7 @@ RSpec.describe "bundle install with explicit source paths" do build_lib "omg", "1.0", :path => lib_path("omg") - bundle :install, :env => { "BUNDLE_BUNDLE_ONLY_UPDATE_TO_NEWER_VERSIONS" => "true" } expect(the_bundle).to include_gems "omg 1.0" end @@ -328,11 +328,12 @@ RSpec.describe "bundle install with explicit source paths" do s.executables = "foobar" end - install_gemfile <<-G path "#{lib_path("foo-1.0")}" do gem 'foo' end G expect(the_bundle).to include_gems "foo 1.0" bundle "exec foobar" @@ -141,156 +141,159 @@ RSpec.describe "bundle install with gems on multiple sources" do end end - context "when a pinned gem has an indirect dependency" do before do build_repo gem_repo3 do build_gem "depends_on_rack", "1.0.1" do |s| s.add_dependency "rack" end end - end - context "when the indirect dependency is in the pinned source" do - before do - # we need a working rack gem in repo3 - update_repo gem_repo3 do - build_gem "rack", "1.0.0" - end - - gemfile <<-G - source "#{file_uri_for(gem_repo2)}" - source "#{file_uri_for(gem_repo3)}" do - gem "depends_on_rack" - end - G end - context "and not in any other sources" do - before do - build_repo(gem_repo2) {} end - it "installs from the same source without any warning" do - bundle :install - expect(err).not_to include("Warning") - expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0", :source => "remote3") - end end - context "and in another source" do - before do - # need this to be broken to check for correct source ordering - build_repo gem_repo2 do - build_gem "rack", "1.0.0" do |s| - s.write "lib/rack.rb", "RACK = 'FAIL'" - end end end - it "installs from the same source without any warning" do - bundle :install - expect(err).not_to include("Warning: the gem 'rack' was found in multiple sources.") - expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0", :source => "remote3") - # In https://.com/bundler/bundler/issues/3585 this failed - # when there is already a lock file, and the gems are missing, so try again - system_gems [] - bundle :install - expect(err).not_to include("Warning: the gem 'rack' was found in multiple sources.") - expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0", :source => "remote3") - end end end - context "when the indirect dependency is in a different source" do - before do - # In these tests, we need a working rack gem in repo2 and not repo3 - build_repo gem_repo2 do - build_gem "rack", "1.0.0" end end - context "and not in any other sources" do - before do - install_gemfile <<-G - source "#{file_uri_for(gem_repo2)}" - source "#{file_uri_for(gem_repo3)}" do - gem "depends_on_rack" - end - G - end - it "installs from the other source without any warning" do - expect(err).not_to include("Warning") - expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0") - end end - context "and in yet another source" do - before do - gemfile <<-G - source "#{file_uri_for(gem_repo1)}" - source "#{file_uri_for(gem_repo2)}" - source "#{file_uri_for(gem_repo3)}" do - gem "depends_on_rack" - end - G - end - it "installs from the other source and warns about ambiguous gems", :bundler => "< 3" do - bundle :install - expect(err).to include("Warning: the gem 'rack' was found in multiple sources.") - expect(err).to include("Installed from: #{file_uri_for(gem_repo2)}") - expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0") - end - it "fails", :bundler => "3" do - bundle :install, :raise_on_error => false - expect(err).to include("Each source after the first must include a block") - expect(exitstatus).to eq(4) - end end - context "and only the dependency is pinned" do - before do - # need this to be broken to check for correct source ordering - build_repo gem_repo2 do - build_gem "rack", "1.0.0" do |s| - s.write "lib/rack.rb", "RACK = 'FAIL'" - end end - gemfile <<-G - source "#{file_uri_for(gem_repo3)}" # contains depends_on_rack - source "#{file_uri_for(gem_repo2)}" # contains broken rack - gem "depends_on_rack" # installed from gem_repo3 - gem "rack", :source => "#{file_uri_for(gem_repo1)}" - G - end - it "installs the dependency from the pinned source without warning", :bundler => "< 3" do - bundle :install - expect(err).not_to include("Warning: the gem 'rack' was found in multiple sources.") - expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0") - # In https://.com/rubygems/bundler/issues/3585 this failed - # when there is already a lock file, and the gems are missing, so try again - system_gems [] - bundle :install - expect(err).not_to include("Warning: the gem 'rack' was found in multiple sources.") - expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0") - end - it "fails", :bundler => "3" do - bundle :install, :raise_on_error => false - expect(err).to include("Each source after the first must include a block") - expect(exitstatus).to eq(4) - end end end end @@ -511,9 +514,149 @@ RSpec.describe "bundle install with gems on multiple sources" do L end - it "upgrades gems when running bundle update, without printing any warnings or errors" do bundle "update --all" expect(err).to be_empty end end end @@ -551,7 +694,7 @@ RSpec.describe "bundle install with gems on multiple sources" do end end - context "when a pinned gem has an indirect dependency with more than one level of indirection in the default source ", :bundler => "< 3" do before do build_repo gem_repo3 do build_gem "handsoap", "0.2.5.5" do |s| @@ -578,12 +721,38 @@ RSpec.describe "bundle install with gems on multiple sources" do G end - it "installs from the proper sources without any warnings or errors" do bundle "install --verbose" expect(err).not_to include("Warning") expect(the_bundle).to include_gems("handsoap 0.2.5.5", "nokogiri 1.11.1", "racca 1.5.2") expect(the_bundle).to include_gems("handsoap 0.2.5.5", :source => "remote3") expect(the_bundle).to include_gems("nokogiri 1.11.1", "racca 1.5.2", :source => "remote2") # Even if the gems are already installed FileUtils.rm bundled_app_lock @@ -592,6 +761,7 @@ RSpec.describe "bundle install with gems on multiple sources" do expect(the_bundle).to include_gems("handsoap 0.2.5.5", "nokogiri 1.11.1", "racca 1.5.2") expect(the_bundle).to include_gems("handsoap 0.2.5.5", :source => "remote3") expect(the_bundle).to include_gems("nokogiri 1.11.1", "racca 1.5.2", :source => "remote2") end end @@ -619,6 +789,9 @@ RSpec.describe "bundle install with gems on multiple sources" do lockfile <<-L GEM remote: #{file_uri_for(gem_repo1)} remote: #{file_uri_for(gem_repo3)} specs: rack (0.9.1) @@ -644,6 +817,84 @@ RSpec.describe "bundle install with gems on multiple sources" do end end context "with a path gem in the same Gemfile" do before do build_lib "foo" @@ -825,13 +1076,34 @@ RSpec.describe "bundle install with gems on multiple sources" do G end - it "keeps the old version", :bundler => "< 3" do - expect(the_bundle).to include_gems("rack 1.0.0") end - it "installs the higher version in the new repo", :bundler => "3" do - expect(the_bundle).to include_gems("rack 1.2") end end context "when a gem is available from multiple ambiguous sources", :bundler => "3" do @@ -104,6 +104,50 @@ RSpec.describe "bundle install with specific platforms" do L end it "caches the universal-darwin gem when --all-platforms is passed and properly picks it up on further bundler invocations" do setup_multiplatform_gem gemfile(google_protobuf) @@ -245,37 +245,7 @@ RSpec.describe "bundle flex_install" do end describe "when adding a new source" do - it "updates the lockfile", :bundler => "< 3" do - build_repo2 - install_gemfile <<-G - source "#{file_uri_for(gem_repo1)}" - gem "rack" - G - install_gemfile <<-G - source "#{file_uri_for(gem_repo1)}" - source "#{file_uri_for(gem_repo2)}" - gem "rack" - G - - lockfile_should_be <<-L - GEM - remote: #{file_uri_for(gem_repo1)}/ - remote: #{file_uri_for(gem_repo2)}/ - specs: - rack (1.0.0) - - PLATFORMS - #{lockfile_platforms} - - DEPENDENCIES - rack - - BUNDLED WITH - #{Bundler::VERSION} - L - end - - it "updates the lockfile", :bundler => "3" do build_repo2 install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" @@ -3,6 +3,32 @@ RSpec.describe "bundle install with install-time dependencies" do before do build_repo2 do # Test complicated gem dependencies for install build_gem "net_a" do |s| s.add_dependency "net_b" @@ -55,6 +81,25 @@ RSpec.describe "bundle install with install-time dependencies" do expect(out).to eq("YES\nYES") end it "installs gems with a dependency with no type" do skip "incorrect data check error" if Gem.win_platform? @@ -49,8 +49,23 @@ RSpec.describe "when using sudo", :sudo => true do end it "installs rake and a gem dependent on rake in the same session" do gemfile <<-G - source "#{file_uri_for(gem_repo1)}" gem "rake" gem "another_implicit_rake_dep" G @@ -13,7 +13,7 @@ RSpec.describe "bundle install" do expect(the_bundle).to include_gems "foo 1.0", :source => "git@#{lib_path("foo")}" end - it "displays the correct default branch" do build_git "foo", "1.0", :path => lib_path("foo"), :default_branch => "main" install_gemfile <<-G, :verbose => true @@ -318,40 +318,7 @@ RSpec.describe "the lockfile format" do G end - it "generates a lockfile without credentials for a configured source", :bundler => "< 3" do - bundle "config set http://localgemserver.test/ user:pass" - - install_gemfile(<<-G, :artifice => "endpoint_strict_basic_authentication", :quiet => true) - source "http://localgemserver.test/" do - - end - - source "http://user:[email protected]/" do - gem "rack-obama", ">= 1.0" - end - G - - lockfile_should_be <<-G - GEM - remote: http://localgemserver.test/ - remote: http://user:[email protected]/ - specs: - rack (1.0.0) - rack-obama (1.0) - rack - - PLATFORMS - #{lockfile_platforms} - - DEPENDENCIES - rack-obama (>= 1.0)! - - BUNDLED WITH - #{Bundler::VERSION} - G - end - - it "generates a lockfile without credentials for a configured source", :bundler => "3" do bundle "config set http://localgemserver.test/ user:pass" install_gemfile(<<-G, :artifice => "endpoint_strict_basic_authentication", :quiet => true) @@ -674,6 +641,30 @@ RSpec.describe "the lockfile format" do G end it "lists gems alphabetically" do install_gemfile <<-G source "#{file_uri_for(gem_repo2)}/" @@ -165,6 +165,28 @@ RSpec.describe "major deprecations" do pending "fails with a helpful error", :bundler => "3" end describe "bundle config" do describe "old list interface" do before do @@ -383,15 +405,53 @@ RSpec.describe "major deprecations" do "Your Gemfile contains multiple primary sources. " \ "Using `source` more than once without a block is a security risk, and " \ "may result in installing unexpected gems. To resolve this warning, use " \ - "a block to indicate which gems should come from the secondary source. " \ - "To upgrade this warning to an error, run `bundle config set --local " \ - "disable_multisource true`." ) end pending "fails with a helpful error", :bundler => "3" end context "when Bundler.setup is run in a ruby script" do before do create_file "gems.rb" @@ -609,4 +669,50 @@ The :gist git source is deprecated, and will be removed in the future. Add this pending "fails with a helpful message", :bundler => "3" end end @@ -169,7 +169,6 @@ RSpec.describe "The library itself" do it "documents all used settings" do exemptions = %w[ - deployment_means_frozen forget_cli_options gem.coc gem.mit @@ -6,7 +6,7 @@ PATH GEM remote: https://rubygems.org/ specs: - jruby-jars (9.2.14.0) jruby-rack (1.1.21) rake (13.0.1) rubyzip (1.3.0) @@ -19,6 +19,7 @@ GEM PLATFORMS java ruby DEPENDENCIES demo! @@ -26,4 +27,4 @@ DEPENDENCIES warbler (~> 2.0) BUNDLED WITH - 2.2.0.rc.2 @@ -246,6 +246,19 @@ RSpec.describe "bundler/inline#gemfile" do expect(last_command.stderr).to be_empty end it "installs inline gems when BUNDLE_GEMFILE is set to an empty string" do ENV["BUNDLE_GEMFILE"] = "" @@ -108,6 +108,44 @@ RSpec.describe "Bundler.setup with multi platform stuff" do expect(lockfile).to eq(good_lockfile) end it "will use the java platform if both generic java and generic ruby platforms are locked", :jruby do gemfile <<-G source "#{file_uri_for(gem_repo1)}" @@ -1244,16 +1244,16 @@ end describe "default gem activation" do let(:exemptions) do - exempts = if Gem::Version.new(Gem::VERSION) >= Gem::Version.new("2.7") %w[did_you_mean] else %w[io-console openssl] end << "bundler" - exempts << "fiddle" if Gem.win_platform? && Gem::Version.new(Gem::VERSION) >= Gem::Version.new("2.7") - exempts << "uri" if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("2.7") - exempts << "pathname" if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("3.0") - exempts << "set" unless Gem::Version.new(Gem::VERSION) >= Gem::Version.new("3.2.6") - exempts << "tsort" if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("3.0") exempts end @@ -66,16 +66,9 @@ RSpec.configure do |config| mocks.allow_message_expectations_on_nil = false end - config.around :each do |example| - if ENV["RUBY"] - orig_ruby = Gem.ruby - Gem.ruby = ENV["RUBY"] - end - example.run - Gem.ruby = orig_ruby if ENV["RUBY"] - end - config.before :suite do require_relative "support/rubygems_ext" Spec::Rubygems.test_setup ENV["BUNDLE_SPEC_RUN"] = "true" @@ -90,6 +83,8 @@ RSpec.configure do |config| end config.before :all do build_repo1 reset_paths! @@ -30,7 +30,11 @@ module Spec end def build_repo1 build_repo gem_repo1 do build_gem "rack", %w[0.9.1 1.0.0] do |s| s.executables = "rackup" s.post_install_message = "Rack's post install message" @@ -150,32 +154,6 @@ module Spec build_gem "duradura", "7.0" - build_gem "with_implicit_rake_dep" do |s| - s.extensions << "Rakefile" - s.write "Rakefile", <<-RUBY - task :default do - path = File.expand_path("../lib", __FILE__) - FileUtils.mkdir_p(path) - File.open("\#{path}/implicit_rake_dep.rb", "w") do |f| - f.puts "IMPLICIT_RAKE_DEP = 'YES'" - end - end - RUBY - end - - build_gem "another_implicit_rake_dep" do |s| - s.extensions << "Rakefile" - s.write "Rakefile", <<-RUBY - task :default do - path = File.expand_path("../lib", __FILE__) - FileUtils.mkdir_p(path) - File.open("\#{path}/another_implicit_rake_dep.rb", "w") do |f| - f.puts "ANOTHER_IMPLICIT_RAKE_DEP = 'YES'" - end - end - RUBY - end - build_gem "very_simple_binary", &:add_c_extension build_gem "simple_binary", &:add_c_extension @@ -255,6 +233,13 @@ module Spec def build_repo(path, &blk) return if File.directory?(path) rake_path = Dir["#{Path.base_system_gems}/**/rake*.gem"].first if rake_path.nil? @@ -263,14 +248,9 @@ module Spec rake_path = Dir["#{Path.base_system_gems}/**/rake*.gem"].first end - if rake_path - FileUtils.mkdir_p("#{path}/gems") - FileUtils.cp rake_path, "#{path}/gems/" - else abort "Your test gems are missing! Run `rm -rf #{tmp}` and try again." end - - update_repo(path, &blk) end def update_repo(path) @@ -0,0 +1,8 @@ @@ -29,7 +29,7 @@ module Gem end # We only need this hack for rubygems versions without the BundlerVersionFinder - if Gem::Version.new(Gem::VERSION) < Gem::Version.new("2.7.0") @path_to_default_spec_map.delete_if do |_path, spec| spec.name == "bundler" end @@ -10,7 +10,7 @@ module Spec def reset! Dir.glob("#{tmp}/{gems/*,*}", File::FNM_DOTMATCH).each do |dir| - next if %w[base base_system remote1 gems rubygems . ..].include?(File.basename(dir)) FileUtils.rm_rf(dir) end FileUtils.mkdir_p(home) @@ -130,7 +130,7 @@ module Spec def ruby(ruby, options = {}) ruby_cmd = build_ruby_cmd - escaped_ruby = RUBY_PLATFORM == "java" ? ruby.shellescape.dump : ruby.shellescape sys_exec(%(#{ruby_cmd} -w -e #{escaped_ruby}), options) end @@ -114,30 +114,49 @@ module Spec match do opts = names.last.is_a?(Hash) ? names.pop : {} source = opts.delete(:source) - groups = Array(opts[:groups]) opts[:raise_on_error] = false - groups << opts - @errors = names.map do |name| - name, version, platform = name.split(/\s+/) require_path = name == "bundler" ? "#{lib_dir}/bundler" : name.tr("-", "/") version_const = name == "bundler" ? "Bundler::VERSION" : Spec::Builders.constantize(name) - code = [] - code << "require '#{require_path}.rb'" - code << "puts #{version_const}" - run code.join("; "), *groups - actual_version, actual_platform = out.strip.split(/\s+/, 2) - unless Gem::Version.new(actual_version) == Gem::Version.new(version) next "#{name} was expected to be at version #{version} but was #{actual_version}" end - unless actual_platform == platform next "#{name} was expected to be of platform #{platform} but was #{actual_platform}" end - next unless source - source_const = "#{Spec::Builders.constantize(name)}_SOURCE" - run "require '#{require_path}/source'; puts #{source_const}", *groups - unless out.strip == source - next "Expected #{name} (#{version}) to be installed from `#{source}`, was actually from `#{out}`" end end.compact @errors.empty? @@ -6,7 +6,7 @@ require "rbconfig" module Spec module Path def source_root - @source_root ||= Pathname.new(ruby_core? ? "../../../.." : "../../..").expand_path(__FILE__) end def root @@ -30,7 +30,15 @@ module Spec end def test_gemfile - @test_gemfile ||= source_root.join(ruby_core? ? "tool/bundler/test_gems.rb" : "test_gems.rb") end def dev_gemfile @@ -119,7 +127,7 @@ module Spec end def vendored_gems(path = nil) - bundled_app(*["vendor/bundle", Gem.ruby_engine, RbConfig::CONFIG["ruby_version"], path].compact) end def cached_gem(path) @@ -138,6 +146,14 @@ module Spec tmp.join("gems/base") end def file_uri_for(path) protocol = "file://" root = Gem.win_platform? ? "/" : "" @@ -178,7 +194,11 @@ module Spec end def local_gem_path(*path, base: bundled_app) - base.join(*[".bundle", Gem.ruby_engine, RbConfig::CONFIG["ruby_version"], *path].compact) end def lib_path(*args) @@ -193,10 +213,6 @@ module Spec root.join("lib") end - def xdg_config_home - home(".config") - end - def global_plugin_gem(*args) home ".bundle", "plugin", "gems", *args end @@ -255,6 +271,14 @@ module Spec !git_root.join(".git").directory? end extend self end end @@ -9,7 +9,7 @@ module Spec extend self def dev_setup - install_gems(dev_gemfile, dev_lockfile) end def gem_load(gem_name, bin_container) @@ -33,25 +33,25 @@ module Spec ENV["HOME"] = Path.home.to_s ENV["TMPDIR"] = Path.tmpdir.to_s - ENV["XDG_CONFIG_HOME"] = Path.xdg_config_home.to_s require "rubygems/user_interaction" Gem::DefaultUserInteraction.ui = Gem::SilentUI.new end def install_parallel_test_deps require "parallel" - prev_env_test_number = ENV["TEST_ENV_NUMBER"] - begin - Parallel.processor_count.times do |n| - ENV["TEST_ENV_NUMBER"] = (n + 1).to_s - install_test_deps - end - ensure - ENV["TEST_ENV_NUMBER"] = prev_env_test_number end end @@ -67,9 +67,9 @@ module Spec def install_test_deps setup_test_paths - workaround_loaded_specs_issue - - install_gems(test_gemfile, test_lockfile) end def check_source_control_changes(success_message:, error_message:) @@ -94,18 +94,6 @@ module Spec private - # Some rubygems versions include loaded specs when loading gemspec stubs - # from the file system. In this situation, that makes bundler incorrectly - # assume that `rake` is already installed at `tmp/` because it's installed - # globally, and makes it skip installing it to the proper location for our - # tests. To workaround, we remove `rake` from the loaded specs when running - # under those versions, so that `bundler` does the right thing. - def workaround_loaded_specs_issue - current_rubygems_version = Gem::Version.new(Gem::VERSION) - - Gem.loaded_specs.delete("rake") if current_rubygems_version >= Gem::Version.new("3.0.0.beta2") && current_rubygems_version < Gem::Version.new("3.2.0") - end - def gem_load_and_activate(gem_name, bin_container) gem_activate(gem_name) load Gem.bin_path(gem_name, bin_container) @@ -119,14 +107,27 @@ module Spec gem gem_name, gem_requirement end - def install_gems(gemfile, lockfile) old_gemfile = ENV["BUNDLE_GEMFILE"] ENV["BUNDLE_GEMFILE"] = gemfile.to_s - require "bundler" - definition = Bundler::Definition.build(gemfile, lockfile, nil) - definition.validate_runtime! - Bundler::Installer.install(Path.source_root, definition, :path => ENV["GEM_HOME"]) ensure ENV["BUNDLE_GEMFILE"] = old_gemfile end @@ -134,8 +135,12 @@ module Spec Path.test_gemfile end - def test_lockfile - lockfile_for(test_gemfile) end def dev_gemfile |