bundler 2.5.15 → 2.5.17

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7e2f845c327ff2e6c5937d3546c2f417a91026841d0f6afb1b4b1a33bf216197
4
- data.tar.gz: 3b480f0e006b22393230e007296f99aaea6fad29d01d8632cedddac8051d59d0
3
+ metadata.gz: 60cb5ee8526a6f8eb3c413e7d3d2ae8c9b32315685862943fc2a956f2fdcd5a1
4
+ data.tar.gz: 52aa4c3a435ed97c8dbc2adcfa51dc6d2113fefcb5020df0a5b0be3b605cc49f
5
5
  SHA512:
6
- metadata.gz: 0fd4e8cf425683982d0684bcaee524925a7b9937c6cbe6bb1e490c7bad78d7723defb07f2649288507d77f4d24d0f6c201eb2172c5f08e4ddd854c6a2420ecf6
7
- data.tar.gz: 2ef8c0e7d2293cd5ec6ccc2ba7bb71806a1b7504423e3adb80a60302dfa2a811e677fa90cdff90da4bd3a31eb40337afe2b9a952085d8cc0c7f626e305e3ad9c
6
+ metadata.gz: afafe4e932d1840de3938e609f45555b1fbdf3fea481ee6d395a1f1458d579606d2f5ac64edc90d74799d9b117aae3fd1028b6d3a660df97e087bb9f6475d583
7
+ data.tar.gz: fd8907298e40c98124857ea7bf2594953d962946b66da695ce929db2623e67dacbee7dec6500a3dfb89cb6308377a26c305a25cd28a7083432ec10baf0d59810
data/CHANGELOG.md CHANGED
@@ -1,4 +1,34 @@
1
- # 2.5.15 (July 8, 2024)
1
+ # 2.5.17 (August 1, 2024)
2
+
3
+ ## Enhancements:
4
+
5
+ - Print better log message when current platform is not present in the lockfile [#7891](https://github.com/rubygems/rubygems/pull/7891)
6
+ - Explicitly encode `Gem::Dependency` to yaml [#7867](https://github.com/rubygems/rubygems/pull/7867)
7
+ - Enable lockfile checksums on future Bundler 3 when there's no previous lockfile [#7805](https://github.com/rubygems/rubygems/pull/7805)
8
+
9
+ ## Bug fixes:
10
+
11
+ - Fix truffleruby removing gems from lockfile [#7795](https://github.com/rubygems/rubygems/pull/7795)
12
+ - Fix `bundle check` exit code when gem git source is not checked out [#7894](https://github.com/rubygems/rubygems/pull/7894)
13
+ - Generate gems.rb from Gemfile.tt template for `bundle-gem` [#7853](https://github.com/rubygems/rubygems/pull/7853)
14
+ - Fix git source cache being used as the install location [#4469](https://github.com/rubygems/rubygems/pull/4469)
15
+ - Fix `bundle exec gem uninstall` [#7886](https://github.com/rubygems/rubygems/pull/7886)
16
+
17
+ # 2.5.16 (July 18, 2024)
18
+
19
+ ## Bug fixes:
20
+
21
+ - Fix platform removal regression when `platforms:` used in the Gemfile [#7864](https://github.com/rubygems/rubygems/pull/7864)
22
+ - Fix standalone script when default gems with extensions are used [#7870](https://github.com/rubygems/rubygems/pull/7870)
23
+ - Fix another case of `bundle lock --add-platform` doing nothing [#7848](https://github.com/rubygems/rubygems/pull/7848)
24
+ - Fix bad error messages when using `bundle add` with frozen mode set [#7845](https://github.com/rubygems/rubygems/pull/7845)
25
+ - Fix generic platform gems getting incorrectly removed from lockfile [#7833](https://github.com/rubygems/rubygems/pull/7833)
26
+
27
+ ## Performance:
28
+
29
+ - Use `caller_locations` instead of splitting `caller` [#7708](https://github.com/rubygems/rubygems/pull/7708)
30
+
31
+ # 2.5.15 (July 9, 2024)
2
32
 
3
33
  ## Enhancements:
4
34
 
@@ -4,8 +4,8 @@ module Bundler
4
4
  # Represents metadata from when the Bundler gem was built.
5
5
  module BuildMetadata
6
6
  # begin ivars
7
- @built_at = "2024-07-09".freeze
8
- @git_commit_sha = "ee7468dc1a".freeze
7
+ @built_at = "2024-08-01".freeze
8
+ @git_commit_sha = "74d92b2502".freeze
9
9
  @release = true
10
10
  # end ivars
11
11
 
@@ -17,7 +17,7 @@ module Bundler
17
17
  begin
18
18
  definition.resolve_only_locally!
19
19
  not_installed = definition.missing_specs
20
- rescue GemNotFound, SolveFailure
20
+ rescue GemNotFound, GitError, SolveFailure
21
21
  Bundler.ui.error "Bundler can't satisfy your Gemfile's dependencies."
22
22
  Bundler.ui.warn "Install missing gems with `bundle install`."
23
23
  exit 1
@@ -79,7 +79,7 @@ module Bundler
79
79
  ensure_safe_gem_name(name, constant_array)
80
80
 
81
81
  templates = {
82
- "#{Bundler.preferred_gemfile_name}.tt" => Bundler.preferred_gemfile_name,
82
+ "Gemfile.tt" => Bundler.preferred_gemfile_name,
83
83
  "lib/newgem.rb.tt" => "lib/#{namespaced_path}.rb",
84
84
  "lib/newgem/version.rb.tt" => "lib/#{namespaced_path}/version.rb",
85
85
  "sig/newgem.rbs.tt" => "sig/#{namespaced_path}.rbs",
data/lib/bundler/cli.rb CHANGED
@@ -110,8 +110,8 @@ module Bundler
110
110
  default_task(Bundler.feature_flag.default_cli_command)
111
111
 
112
112
  class_option "no-color", type: :boolean, desc: "Disable colorization in output"
113
- class_option "retry", type: :numeric, aliases: "-r", banner: "NUM",
114
- desc: "Specify the number of times you wish to attempt network commands"
113
+ class_option "retry", type: :numeric, aliases: "-r", banner: "NUM",
114
+ desc: "Specify the number of times you wish to attempt network commands"
115
115
  class_option "verbose", type: :boolean, desc: "Enable verbose output mode", aliases: "-V"
116
116
 
117
117
  def help(cli = nil)
@@ -260,15 +260,15 @@ module Bundler
260
260
  method_option "gemfile", type: :string, banner: "Use the specified gemfile instead of Gemfile"
261
261
  method_option "group", aliases: "-g", type: :array, banner: "Update a specific group"
262
262
  method_option "jobs", aliases: "-j", type: :numeric, banner: "Specify the number of jobs to run in parallel"
263
- method_option "local", type: :boolean, banner: "Do not attempt to fetch gems remotely and use the gem cache instead"
264
- method_option "quiet", type: :boolean, banner: "Only output warnings and errors."
263
+ method_option "local", type: :boolean, banner: "Do not attempt to fetch gems remotely and use the gem cache instead"
264
+ method_option "quiet", type: :boolean, banner: "Only output warnings and errors."
265
265
  method_option "source", type: :array, banner: "Update a specific source (and all gems associated with it)"
266
266
  method_option "redownload", type: :boolean, aliases: "--force", banner: "Force downloading every gem."
267
267
  method_option "ruby", type: :boolean, banner: "Update ruby specified in Gemfile.lock"
268
268
  method_option "bundler", type: :string, lazy_default: "> 0.a", banner: "Update the locked version of bundler"
269
- method_option "patch", type: :boolean, banner: "Prefer updating only to next patch version"
270
- method_option "minor", type: :boolean, banner: "Prefer updating only to next minor version"
271
- method_option "major", type: :boolean, banner: "Prefer updating to next major version (default)"
269
+ method_option "patch", type: :boolean, banner: "Prefer updating only to next patch version"
270
+ method_option "minor", type: :boolean, banner: "Prefer updating only to next minor version"
271
+ method_option "major", type: :boolean, banner: "Prefer updating to next major version (default)"
272
272
  method_option "pre", type: :boolean, banner: "Always choose the highest allowed version when updating gems, regardless of prerelease status"
273
273
  method_option "strict", type: :boolean, banner: "Do not allow any gem to be updated past latest --patch | --minor | --major"
274
274
  method_option "conservative", type: :boolean, banner: "Use bundle install conservative update behavior and do not allow shared dependencies to be updated."
@@ -397,11 +397,11 @@ module Bundler
397
397
  end
398
398
 
399
399
  desc "cache [OPTIONS]", "Locks and then caches all of the gems into vendor/cache"
400
- method_option "all", type: :boolean,
401
- default: Bundler.feature_flag.cache_all?,
402
- banner: "Include all sources (including path and git)."
400
+ method_option "all", type: :boolean,
401
+ default: Bundler.feature_flag.cache_all?,
402
+ banner: "Include all sources (including path and git)."
403
403
  method_option "all-platforms", type: :boolean, banner: "Include gems for all platforms present in the lockfile, not only the current one"
404
- method_option "cache-path", type: :string, banner: "Specify a different cache path than the default (vendor/cache)."
404
+ method_option "cache-path", type: :string, banner: "Specify a different cache path than the default (vendor/cache)."
405
405
  method_option "gemfile", type: :string, banner: "Use the specified gemfile instead of Gemfile"
406
406
  method_option "no-install", type: :boolean, banner: "Don't install the gems, only update the cache."
407
407
  method_option "no-prune", type: :boolean, banner: "Don't remove stale gems from the cache."
@@ -605,7 +605,7 @@ module Bundler
605
605
  end
606
606
 
607
607
  desc "inject GEM VERSION", "Add the named gem, with version requirements, to the resolved Gemfile", hide: true
608
- method_option "source", type: :string, banner: "Install gem from the given source"
608
+ method_option "source", type: :string, banner: "Install gem from the given source"
609
609
  method_option "group", type: :string, banner: "Install gem into a bundler group"
610
610
  def inject(name, version)
611
611
  SharedHelpers.major_deprecation 2, "The `inject` command has been replaced by the `add` command"
@@ -615,16 +615,16 @@ module Bundler
615
615
 
616
616
  desc "lock", "Creates a lockfile without installing"
617
617
  method_option "update", type: :array, lazy_default: true, banner: "ignore the existing lockfile, update all gems by default, or update list of given gems"
618
- method_option "local", type: :boolean, default: false, banner: "do not attempt to fetch remote gemspecs and use the local gem cache only"
619
- method_option "print", type: :boolean, default: false, banner: "print the lockfile to STDOUT instead of writing to the file system"
618
+ method_option "local", type: :boolean, default: false, banner: "do not attempt to fetch remote gemspecs and use the local gem cache only"
619
+ method_option "print", type: :boolean, default: false, banner: "print the lockfile to STDOUT instead of writing to the file system"
620
620
  method_option "gemfile", type: :string, banner: "Use the specified gemfile instead of Gemfile"
621
621
  method_option "lockfile", type: :string, default: nil, banner: "the path the lockfile should be written to"
622
622
  method_option "full-index", type: :boolean, default: false, banner: "Fall back to using the single-file index of all gems"
623
623
  method_option "add-platform", type: :array, default: [], banner: "Add a new platform to the lockfile"
624
- method_option "remove-platform", type: :array, default: [], banner: "Remove a platform from the lockfile"
625
- method_option "patch", type: :boolean, banner: "If updating, prefer updating only to next patch version"
626
- method_option "minor", type: :boolean, banner: "If updating, prefer updating only to next minor version"
627
- method_option "major", type: :boolean, banner: "If updating, prefer updating to next major version (default)"
624
+ method_option "remove-platform", type: :array, default: [], banner: "Remove a platform from the lockfile"
625
+ method_option "patch", type: :boolean, banner: "If updating, prefer updating only to next patch version"
626
+ method_option "minor", type: :boolean, banner: "If updating, prefer updating only to next minor version"
627
+ method_option "major", type: :boolean, banner: "If updating, prefer updating to next major version (default)"
628
628
  method_option "pre", type: :boolean, banner: "If updating, always choose the highest allowed version, regardless of prerelease status"
629
629
  method_option "strict", type: :boolean, banner: "If updating, do not allow any gem to be updated past latest --patch | --minor | --major"
630
630
  method_option "conservative", type: :boolean, banner: "If updating, use bundle install conservative update behavior and do not allow shared dependencies to be updated"
@@ -81,7 +81,7 @@ module Bundler
81
81
  @resolved_bundler_version = nil
82
82
 
83
83
  @locked_ruby_version = nil
84
- @new_platform = nil
84
+ @new_platforms = []
85
85
  @removed_platform = nil
86
86
 
87
87
  if lockfile_exists?
@@ -115,7 +115,7 @@ module Bundler
115
115
  @originally_locked_specs = @locked_specs
116
116
  @locked_sources = []
117
117
  @locked_platforms = []
118
- @locked_checksums = nil
118
+ @locked_checksums = Bundler.feature_flag.bundler_3_mode?
119
119
  end
120
120
 
121
121
  locked_gem_sources = @locked_sources.select {|s| s.is_a?(Source::Rubygems) }
@@ -137,7 +137,7 @@ module Bundler
137
137
  end
138
138
  @unlocking ||= @unlock[:ruby] ||= (!@locked_ruby_version ^ !@ruby_version)
139
139
 
140
- add_current_platform unless Bundler.frozen_bundle?
140
+ @current_platform_missing = add_current_platform unless Bundler.frozen_bundle?
141
141
 
142
142
  converge_path_sources_to_gemspec_sources
143
143
  @path_changes = converge_paths
@@ -367,6 +367,10 @@ module Bundler
367
367
  end
368
368
 
369
369
  def ensure_equivalent_gemfile_and_lockfile(explicit_flag = false)
370
+ return unless Bundler.frozen_bundle?
371
+
372
+ raise ProductionError, "Frozen mode is set, but there's no lockfile" unless lockfile_exists?
373
+
370
374
  added = []
371
375
  deleted = []
372
376
  changed = []
@@ -395,7 +399,7 @@ module Bundler
395
399
  changed << "* #{name} from `#{lockfile_source_name}` to `#{gemfile_source_name}`"
396
400
  end
397
401
 
398
- reason = change_reason
402
+ reason = nothing_changed? ? "some dependencies were deleted from your gemfile" : change_reason
399
403
  msg = String.new
400
404
  msg << "#{reason.capitalize.strip}, but the lockfile can't be updated because frozen mode is set"
401
405
  msg << "\n\nYou have added to the Gemfile:\n" << added.join("\n") if added.any?
@@ -453,8 +457,10 @@ module Bundler
453
457
  end
454
458
 
455
459
  def add_platform(platform)
456
- @new_platform ||= !@platforms.include?(platform)
457
- @platforms |= [platform]
460
+ return if @platforms.include?(platform)
461
+
462
+ @new_platforms << platform
463
+ @platforms << platform
458
464
  end
459
465
 
460
466
  def remove_platform(platform)
@@ -478,7 +484,8 @@ module Bundler
478
484
 
479
485
  !@source_changes &&
480
486
  !@dependency_changes &&
481
- !@new_platform &&
487
+ !@current_platform_missing &&
488
+ @new_platforms.empty? &&
482
489
  !@path_changes &&
483
490
  !@local_changes &&
484
491
  !@missing_lockfile_dep &&
@@ -561,7 +568,7 @@ module Bundler
561
568
  def resolution_packages
562
569
  @resolution_packages ||= begin
563
570
  last_resolve = converge_locked_specs
564
- remove_invalid_platforms!(current_dependencies)
571
+ remove_invalid_platforms!
565
572
  packages = Resolver::Base.new(source_requirements, expanded_dependencies, last_resolve, @platforms, locked_specs: @originally_locked_specs, unlock: @gems_to_unlock, prerelease: gem_version_promoter.pre?)
566
573
  packages = additional_base_requirements_to_prevent_downgrades(packages, last_resolve)
567
574
  packages = additional_base_requirements_to_force_updates(packages)
@@ -623,13 +630,14 @@ module Bundler
623
630
  def start_resolution
624
631
  local_platform_needed_for_resolvability = @most_specific_non_local_locked_ruby_platform && !@platforms.include?(local_platform)
625
632
  @platforms << local_platform if local_platform_needed_for_resolvability
633
+ add_platform(Gem::Platform::RUBY) if RUBY_ENGINE == "truffleruby"
626
634
 
627
635
  result = SpecSet.new(resolver.start)
628
636
 
629
637
  @resolved_bundler_version = result.find {|spec| spec.name == "bundler" }&.version
630
638
 
631
639
  if @most_specific_non_local_locked_ruby_platform
632
- if result.incomplete_for_platform?(dependencies, @most_specific_non_local_locked_ruby_platform)
640
+ if spec_set_incomplete_for_platform?(result, @most_specific_non_local_locked_ruby_platform)
633
641
  @platforms.delete(@most_specific_non_local_locked_ruby_platform)
634
642
  elsif local_platform_needed_for_resolvability
635
643
  @platforms.delete(local_platform)
@@ -638,8 +646,6 @@ module Bundler
638
646
 
639
647
  @platforms = result.add_extra_platforms!(platforms) if should_add_extra_platforms?
640
648
 
641
- result.complete_platforms!(platforms)
642
-
643
649
  SpecSet.new(result.for(dependencies, false, @platforms))
644
650
  end
645
651
 
@@ -667,19 +673,19 @@ module Bundler
667
673
  end
668
674
 
669
675
  def add_current_platform
670
- @most_specific_non_local_locked_ruby_platform = find_most_specific_non_local_locked_ruby_platform
676
+ return if @platforms.include?(local_platform)
677
+
678
+ @most_specific_non_local_locked_ruby_platform = find_most_specific_locked_ruby_platform
671
679
  return if @most_specific_non_local_locked_ruby_platform
672
680
 
673
- add_platform(local_platform)
681
+ @platforms << local_platform
682
+ true
674
683
  end
675
684
 
676
- def find_most_specific_non_local_locked_ruby_platform
685
+ def find_most_specific_locked_ruby_platform
677
686
  return unless generic_local_platform_is_ruby? && current_platform_locked?
678
687
 
679
- most_specific_locked_ruby_platform = most_specific_locked_platform
680
- return unless most_specific_locked_ruby_platform != local_platform
681
-
682
- most_specific_locked_ruby_platform
688
+ most_specific_locked_platform
683
689
  end
684
690
 
685
691
  def change_reason
@@ -701,7 +707,8 @@ module Bundler
701
707
  [
702
708
  [@source_changes, "the list of sources changed"],
703
709
  [@dependency_changes, "the dependencies in your gemfile changed"],
704
- [@new_platform, "you added a new platform to your gemfile"],
710
+ [@current_platform_missing, "your lockfile does not include the current platform"],
711
+ [@new_platforms.any?, "you added a new platform to your gemfile"],
705
712
  [@path_changes, "the gemspecs for path gems changed"],
706
713
  [@local_changes, "the gemspecs for git local gems changed"],
707
714
  [@missing_lockfile_dep, "your lock file is missing \"#{@missing_lockfile_dep}\""],
@@ -1054,21 +1061,25 @@ module Bundler
1054
1061
  unlocked_definition
1055
1062
  end
1056
1063
 
1057
- def remove_invalid_platforms!(dependencies)
1064
+ def remove_invalid_platforms!
1058
1065
  return if Bundler.frozen_bundle?
1059
1066
 
1060
1067
  platforms.reverse_each do |platform|
1061
1068
  next if local_platform == platform ||
1062
- (@new_platform && platforms.last == platform) ||
1069
+ @new_platforms.include?(platform) ||
1063
1070
  @path_changes ||
1064
1071
  @dependency_changes ||
1065
1072
  @locked_spec_with_invalid_deps ||
1066
- !@originally_locked_specs.incomplete_for_platform?(dependencies, platform)
1073
+ !spec_set_incomplete_for_platform?(@originally_locked_specs, platform)
1067
1074
 
1068
1075
  remove_platform(platform)
1069
1076
  end
1070
1077
  end
1071
1078
 
1079
+ def spec_set_incomplete_for_platform?(spec_set, platform)
1080
+ spec_set.incomplete_for_platform?(current_dependencies, platform)
1081
+ end
1082
+
1072
1083
  def source_map
1073
1084
  @source_map ||= SourceMap.new(sources, dependencies, @locked_specs)
1074
1085
  end
data/lib/bundler/env.rb CHANGED
@@ -120,7 +120,7 @@ module Bundler
120
120
  specs = Bundler.rubygems.find_name(name)
121
121
  out << [" #{name}", "(#{specs.map(&:version).join(",")})"] unless specs.empty?
122
122
  end
123
- if (exe = caller.last.split(":").first)&.match? %r{(exe|bin)/bundler?\z}
123
+ if (exe = caller_locations.last.absolute_path)&.match? %r{(exe|bin)/bundler?\z}
124
124
  shebang = File.read(exe).lines.first
125
125
  shebang.sub!(/^#!\s*/, "")
126
126
  unless shebang.start_with?(Gem.ruby, "/usr/bin/env ruby")
@@ -2,8 +2,6 @@
2
2
 
3
3
  module Bundler
4
4
  module ForcePlatform
5
- private
6
-
7
5
  # The `:force_ruby_platform` value used by dependencies for resolution, and
8
6
  # by locked specifications for materialization is `false` by default, except
9
7
  # for TruffleRuby. TruffleRuby generally needs to force the RUBY platform
@@ -46,19 +46,26 @@ module Bundler
46
46
  end
47
47
  module_function :platform_specificity_match
48
48
 
49
- def select_best_platform_match(specs, platform)
50
- matching = specs.select {|spec| spec.match_platform(platform) }
49
+ def select_best_platform_match(specs, platform, force_ruby: false, prefer_locked: false)
50
+ matching = if force_ruby
51
+ specs.select {|spec| spec.match_platform(Gem::Platform::RUBY) && spec.force_ruby_platform! }
52
+ else
53
+ specs.select {|spec| spec.match_platform(platform) }
54
+ end
55
+
56
+ if prefer_locked
57
+ locked_originally = matching.select {|spec| spec.is_a?(LazySpecification) }
58
+ return locked_originally if locked_originally.any?
59
+ end
51
60
 
52
61
  sort_best_platform_match(matching, platform)
53
62
  end
54
63
  module_function :select_best_platform_match
55
64
 
56
- def force_ruby_platform(specs)
57
- matching = specs.select {|spec| spec.match_platform(Gem::Platform::RUBY) && spec.force_ruby_platform! }
58
-
59
- sort_best_platform_match(matching, Gem::Platform::RUBY)
65
+ def select_best_local_platform_match(specs, force_ruby: false)
66
+ select_best_platform_match(specs, local_platform, force_ruby: force_ruby).map(&:materialize_for_installation).compact
60
67
  end
61
- module_function :force_ruby_platform
68
+ module_function :select_best_local_platform_match
62
69
 
63
70
  def sort_best_platform_match(matching, platform)
64
71
  exact = matching.select {|spec| spec.platform == platform }
@@ -23,10 +23,7 @@ module Bundler
23
23
  # @param [Pathname] lockfile_path The lockfile in which to inject the new dependency.
24
24
  # @return [Array]
25
25
  def inject(gemfile_path, lockfile_path)
26
- if Bundler.frozen_bundle?
27
- # ensure the lock and Gemfile are synced
28
- Bundler.definition.ensure_equivalent_gemfile_and_lockfile(true)
29
- end
26
+ Bundler.definition.ensure_equivalent_gemfile_and_lockfile(true)
30
27
 
31
28
  # temporarily unfreeze
32
29
  Bundler.settings.temporary(deployment: false, frozen: false) do
@@ -58,9 +58,6 @@ module Bundler
58
58
  else
59
59
  SharedHelpers.relative_path_to(full_path, from: Bundler.root.join(bundler_path))
60
60
  end
61
- rescue TypeError
62
- error_message = "#{spec.name} #{spec.version} has an invalid gemspec"
63
- raise Gem::InvalidSpecificationException.new(error_message)
64
61
  end
65
62
 
66
63
  def prevent_gem_activation
@@ -69,9 +69,7 @@ module Bundler
69
69
  Bundler.create_bundle_path
70
70
 
71
71
  ProcessLock.lock do
72
- if Bundler.frozen_bundle?
73
- @definition.ensure_equivalent_gemfile_and_lockfile(options[:deployment])
74
- end
72
+ @definition.ensure_equivalent_gemfile_and_lockfile(options[:deployment])
75
73
 
76
74
  if @definition.dependencies.empty?
77
75
  Bundler.ui.warn "The Gemfile specifies no dependencies"
@@ -4,6 +4,7 @@ require_relative "force_platform"
4
4
 
5
5
  module Bundler
6
6
  class LazySpecification
7
+ include MatchMetadata
7
8
  include MatchPlatform
8
9
  include ForcePlatform
9
10
 
@@ -196,6 +196,7 @@ module Bundler
196
196
 
197
197
  FileUtils.rm_rf(new_cache_path)
198
198
  FileUtils.cp_r(install_path, new_cache_path)
199
+ FileUtils.rm_rf(app_cache_path.join(".git"))
199
200
  FileUtils.touch(app_cache_path.join(".bundlecache"))
200
201
  end
201
202
 
@@ -30,6 +30,10 @@ module Bundler
30
30
  end.compact
31
31
  end
32
32
 
33
+ def specs_compatible_with(result)
34
+ @base.specs_compatible_with(result)
35
+ end
36
+
33
37
  def [](name)
34
38
  @base[name]
35
39
  end
@@ -24,10 +24,10 @@ module Bundler
24
24
 
25
25
  attr_reader :version
26
26
 
27
- def initialize(version, specs: [])
28
- @spec_group = Resolver::SpecGroup.new(specs)
27
+ def initialize(version, group: nil, priority: -1)
28
+ @spec_group = group || SpecGroup.new([])
29
29
  @version = Gem::Version.new(version)
30
- @ruby_only = specs.map(&:platform).uniq == [Gem::Platform::RUBY]
30
+ @priority = priority
31
31
  end
32
32
 
33
33
  def dependencies
@@ -40,18 +40,6 @@ module Bundler
40
40
  @spec_group.to_specs(package.force_ruby_platform?)
41
41
  end
42
42
 
43
- def generic!
44
- @ruby_only = true
45
-
46
- self
47
- end
48
-
49
- def platform_specific!
50
- @ruby_only = false
51
-
52
- self
53
- end
54
-
55
43
  def prerelease?
56
44
  @version.prerelease?
57
45
  end
@@ -61,7 +49,7 @@ module Bundler
61
49
  end
62
50
 
63
51
  def sort_obj
64
- [@version, @ruby_only ? -1 : 1]
52
+ [@version, @priority]
65
53
  end
66
54
 
67
55
  def <=>(other)
@@ -25,6 +25,10 @@ module Bundler
25
25
  @prerelease = @dependency.prerelease? || @locked_version&.prerelease? || prerelease ? :consider_first : :ignore
26
26
  end
27
27
 
28
+ def platform_specs(specs)
29
+ platforms.map {|platform| GemHelpers.select_best_platform_match(specs, platform, prefer_locked: !unlock?) }
30
+ end
31
+
28
32
  def to_s
29
33
  @name.delete("\0")
30
34
  end
@@ -3,6 +3,8 @@
3
3
  module Bundler
4
4
  class Resolver
5
5
  class SpecGroup
6
+ attr_reader :specs
7
+
6
8
  def initialize(specs)
7
9
  @specs = specs
8
10
  end
@@ -38,17 +40,33 @@ module Bundler
38
40
  def dependencies
39
41
  @dependencies ||= @specs.map do |spec|
40
42
  __dependencies(spec) + metadata_dependencies(spec)
41
- end.flatten.uniq
43
+ end.flatten.uniq.sort
44
+ end
45
+
46
+ def ==(other)
47
+ sorted_spec_names == other.sorted_spec_names
48
+ end
49
+
50
+ def merge(other)
51
+ return false unless equivalent?(other)
52
+
53
+ @specs |= other.specs
54
+
55
+ true
42
56
  end
43
57
 
44
58
  protected
45
59
 
46
60
  def sorted_spec_names
47
- @sorted_spec_names ||= @specs.map(&:full_name).sort
61
+ @specs.map(&:full_name).sort
48
62
  end
49
63
 
50
64
  private
51
65
 
66
+ def equivalent?(other)
67
+ name == other.name && version == other.version && source == other.source && dependencies == other.dependencies
68
+ end
69
+
52
70
  def exemplary_spec
53
71
  @specs.first
54
72
  end
@@ -79,7 +79,8 @@ module Bundler
79
79
  def solve_versions(root:, logger:)
80
80
  solver = PubGrub::VersionSolver.new(source: self, root: root, logger: logger)
81
81
  result = solver.solve
82
- result.map {|package, version| version.to_specs(package) }.flatten.uniq
82
+ resolved_specs = result.map {|package, version| version.to_specs(package) }.flatten
83
+ resolved_specs |= @base.specs_compatible_with(SpecSet.new(resolved_specs))
83
84
  rescue PubGrub::SolveFailure => e
84
85
  incompatibility = e.incompatibility
85
86
 
@@ -254,7 +255,7 @@ module Bundler
254
255
  results = filter_matching_specs(results, locked_requirement) if locked_requirement
255
256
 
256
257
  results.group_by(&:version).reduce([]) do |groups, (version, specs)|
257
- platform_specs = package.platforms.map {|platform| select_best_platform_match(specs, platform) }
258
+ platform_specs = package.platform_specs(specs)
258
259
 
259
260
  # If package is a top-level dependency,
260
261
  # candidate is only valid if there are matching versions for all resolution platforms.
@@ -269,14 +270,22 @@ module Bundler
269
270
  next groups if platform_specs.all?(&:empty?)
270
271
  end
271
272
 
272
- platform_specs.flatten!
273
-
274
273
  ruby_specs = select_best_platform_match(specs, Gem::Platform::RUBY)
275
- groups << Resolver::Candidate.new(version, specs: ruby_specs) if ruby_specs.any?
274
+ ruby_group = Resolver::SpecGroup.new(ruby_specs)
275
+
276
+ unless ruby_group.empty?
277
+ platform_specs.each do |specs|
278
+ ruby_group.merge(Resolver::SpecGroup.new(specs))
279
+ end
280
+
281
+ groups << Resolver::Candidate.new(version, group: ruby_group, priority: -1)
282
+ next groups if package.force_ruby_platform?
283
+ end
276
284
 
277
- next groups if platform_specs == ruby_specs || package.force_ruby_platform?
285
+ platform_group = Resolver::SpecGroup.new(platform_specs.flatten.uniq)
286
+ next groups if platform_group == ruby_group
278
287
 
279
- groups << Resolver::Candidate.new(version, specs: platform_specs)
288
+ groups << Resolver::Candidate.new(version, group: platform_group, priority: 1)
280
289
 
281
290
  groups
282
291
  end
@@ -431,8 +440,8 @@ module Bundler
431
440
 
432
441
  def requirement_to_range(requirement)
433
442
  ranges = requirement.requirements.map do |(op, version)|
434
- ver = Resolver::Candidate.new(version).generic!
435
- platform_ver = Resolver::Candidate.new(version).platform_specific!
443
+ ver = Resolver::Candidate.new(version, priority: -1)
444
+ platform_ver = Resolver::Candidate.new(version, priority: 1)
436
445
 
437
446
  case op
438
447
  when "~>"
@@ -56,7 +56,16 @@ module Gem
56
56
  # Can be removed once RubyGems 3.5.14 support is dropped
57
57
  VALIDATES_FOR_RESOLUTION = Specification.new.respond_to?(:validate_for_resolution).freeze
58
58
 
59
+ # Can be removed once RubyGems 3.3.15 support is dropped
60
+ FLATTENS_REQUIRED_PATHS = Specification.new.respond_to?(:flatten_require_paths).freeze
61
+
59
62
  class Specification
63
+ # Can be removed once RubyGems 3.5.15 support is dropped
64
+ correct_array_attributes = @@default_value.select {|_k,v| v.is_a?(Array) }.keys
65
+ unless @@array_attributes == correct_array_attributes
66
+ @@array_attributes = correct_array_attributes # rubocop:disable Style/ClassVars
67
+ end
68
+
60
69
  require_relative "match_metadata"
61
70
  require_relative "match_platform"
62
71
 
@@ -161,6 +170,27 @@ module Gem
161
170
  end
162
171
  end
163
172
 
173
+ unless FLATTENS_REQUIRED_PATHS
174
+ def flatten_require_paths
175
+ return unless raw_require_paths.first.is_a?(Array)
176
+
177
+ warn "#{name} #{version} includes a gemspec with `require_paths` set to an array of arrays. Newer versions of this gem might've already fixed this"
178
+ raw_require_paths.flatten!
179
+ end
180
+
181
+ class << self
182
+ module RequirePathFlattener
183
+ def from_yaml(input)
184
+ spec = super(input)
185
+ spec.flatten_require_paths
186
+ spec
187
+ end
188
+ end
189
+
190
+ prepend RequirePathFlattener
191
+ end
192
+ end
193
+
164
194
  private
165
195
 
166
196
  def dependencies_to_gemfile(dependencies, group = nil)
@@ -207,26 +237,20 @@ module Gem
207
237
 
208
238
  include ::Bundler::ForcePlatform
209
239
 
240
+ attr_reader :force_ruby_platform
241
+
210
242
  attr_accessor :source, :groups
211
243
 
212
244
  alias_method :eql?, :==
213
245
 
214
- def force_ruby_platform
215
- return @force_ruby_platform if defined?(@force_ruby_platform) && !@force_ruby_platform.nil?
216
-
217
- @force_ruby_platform = default_force_ruby_platform
218
- end
219
-
220
- def encode_with(coder)
221
- to_yaml_properties.each do |ivar|
222
- coder[ivar.to_s.sub(/^@/, "")] = instance_variable_get(ivar)
246
+ unless method_defined?(:encode_with, false)
247
+ def encode_with(coder)
248
+ [:@name, :@requirement, :@type, :@prerelease, :@version_requirements].each do |ivar|
249
+ coder[ivar.to_s.sub(/^@/, "")] = instance_variable_get(ivar)
250
+ end
223
251
  end
224
252
  end
225
253
 
226
- def to_yaml_properties
227
- instance_variables.reject {|p| ["@source", "@groups"].include?(p.to_s) }
228
- end
229
-
230
254
  def to_lock
231
255
  out = String.new(" #{name}")
232
256
  unless requirement.none?
@@ -204,7 +204,7 @@ module Bundler
204
204
 
205
205
  [::Kernel.singleton_class, ::Kernel].each do |kernel_class|
206
206
  redefine_method(kernel_class, :gem) do |dep, *reqs|
207
- if executables&.include?(File.basename(caller.first.split(":").first))
207
+ if executables&.include?(File.basename(caller_locations(1, 1).first.path))
208
208
  break
209
209
  end
210
210
 
@@ -10,7 +10,7 @@ module Bundler
10
10
  end
11
11
 
12
12
  def setup(*groups)
13
- @definition.ensure_equivalent_gemfile_and_lockfile if Bundler.frozen_bundle?
13
+ @definition.ensure_equivalent_gemfile_and_lockfile
14
14
 
15
15
  # Has to happen first
16
16
  clean_load_path
@@ -128,11 +128,6 @@ module Bundler
128
128
  spec.source.cache(spec, custom_path) if spec.source.respond_to?(:cache)
129
129
  end
130
130
 
131
- Dir[cache_path.join("*/.git")].each do |git_dir|
132
- FileUtils.rm_rf(git_dir)
133
- FileUtils.touch(File.expand_path("../.bundlecache", git_dir))
134
- end
135
-
136
131
  prune_cache(cache_path) unless Bundler.settings[:no_prune]
137
132
  end
138
133
 
@@ -164,7 +164,8 @@ module Bundler
164
164
  "does not exist. Run `bundle config unset local.#{override_for(original_path)}` to remove the local override"
165
165
  end
166
166
 
167
- set_local!(path)
167
+ @local = true
168
+ set_paths!(path)
168
169
 
169
170
  # Create a new git proxy without the cached revision
170
171
  # so the Gemfile.lock always picks up the new revision.
@@ -187,13 +188,11 @@ module Bundler
187
188
  end
188
189
 
189
190
  def specs(*)
190
- set_local!(app_cache_path) if has_app_cache? && !local?
191
+ set_cache_path!(app_cache_path) if has_app_cache? && !local?
191
192
 
192
193
  if requires_checkout? && !@copied
193
194
  fetch
194
- git_proxy.copy_to(install_path, submodules)
195
- serialize_gemspecs_in(install_path)
196
- @copied = true
195
+ checkout
197
196
  end
198
197
 
199
198
  local_specs
@@ -206,10 +205,7 @@ module Bundler
206
205
  print_using_message "Using #{version_message(spec, options[:previous_spec])} from #{self}"
207
206
 
208
207
  if (requires_checkout? && !@copied) || force
209
- Bundler.ui.debug " * Checking out revision: #{ref}"
210
- git_proxy.copy_to(install_path, submodules)
211
- serialize_gemspecs_in(install_path)
212
- @copied = true
208
+ checkout
213
209
  end
214
210
 
215
211
  generate_bin_options = { disable_extensions: !Bundler.rubygems.spec_missing_extensions?(spec), build_args: options[:build_args] }
@@ -221,12 +217,13 @@ module Bundler
221
217
  def cache(spec, custom_path = nil)
222
218
  app_cache_path = app_cache_path(custom_path)
223
219
  return unless Bundler.feature_flag.cache_all?
224
- return if path == app_cache_path
220
+ return if install_path == app_cache_path
221
+ return if cache_path == app_cache_path
225
222
  cached!
226
223
  FileUtils.rm_rf(app_cache_path)
227
224
  git_proxy.checkout if requires_checkout?
228
- git_proxy.copy_to(app_cache_path, @submodules)
229
- serialize_gemspecs_in(app_cache_path)
225
+ FileUtils.cp_r("#{cache_path}/.", app_cache_path)
226
+ FileUtils.touch(app_cache_path.join(".bundlecache"))
230
227
  end
231
228
 
232
229
  def load_spec_files
@@ -270,6 +267,13 @@ module Bundler
270
267
 
271
268
  private
272
269
 
270
+ def checkout
271
+ Bundler.ui.debug " * Checking out revision: #{ref}"
272
+ git_proxy.copy_to(install_path, submodules)
273
+ serialize_gemspecs_in(install_path)
274
+ @copied = true
275
+ end
276
+
273
277
  def humanized_ref
274
278
  if local?
275
279
  path
@@ -298,10 +302,19 @@ module Bundler
298
302
  end
299
303
  end
300
304
 
301
- def set_local!(path)
302
- @local = true
303
- @local_specs = @git_proxy = nil
304
- @cache_path = @install_path = path
305
+ def set_paths!(path)
306
+ set_cache_path!(path)
307
+ set_install_path!(path)
308
+ end
309
+
310
+ def set_cache_path!(path)
311
+ @git_proxy = nil
312
+ @cache_path = path
313
+ end
314
+
315
+ def set_install_path!(path)
316
+ @local_specs = nil
317
+ @install_path = path
305
318
  end
306
319
 
307
320
  def has_app_cache?
@@ -206,6 +206,7 @@ module Bundler
206
206
 
207
207
  spec.full_gem_path = installed_spec.full_gem_path
208
208
  spec.loaded_from = installed_spec.loaded_from
209
+ spec.base_dir = installed_spec.base_dir
209
210
 
210
211
  spec.post_install_message
211
212
  end
@@ -71,12 +71,6 @@ module Bundler
71
71
  platforms
72
72
  end
73
73
 
74
- def complete_platforms!(platforms)
75
- platforms.each do |platform|
76
- complete_platform(platform)
77
- end
78
- end
79
-
80
74
  def validate_deps(s)
81
75
  s.runtime_dependencies.each do |dep|
82
76
  next if dep.name == "bundler"
@@ -100,7 +94,7 @@ module Bundler
100
94
  end
101
95
 
102
96
  def delete(specs)
103
- specs.each {|spec| @specs.delete(spec) }
97
+ Array(specs).each {|spec| @specs.delete(spec) }
104
98
 
105
99
  reset!
106
100
  end
@@ -158,6 +152,12 @@ module Bundler
158
152
  @specs.detect {|spec| spec.name == name && spec.match_platform(platform) }
159
153
  end
160
154
 
155
+ def specs_compatible_with(other)
156
+ select do |spec|
157
+ other.valid?(spec)
158
+ end
159
+ end
160
+
161
161
  def delete_by_name(name)
162
162
  @specs.reject! {|spec| spec.name == name }
163
163
 
@@ -195,6 +195,10 @@ module Bundler
195
195
  lookup.keys
196
196
  end
197
197
 
198
+ def valid?(s)
199
+ s.matches_current_metadata? && valid_dependencies?(s)
200
+ end
201
+
198
202
  private
199
203
 
200
204
  def reset!
@@ -209,7 +213,7 @@ module Bundler
209
213
  spec = specs.first
210
214
  matching_specs = spec.source.specs.search([spec.name, spec.version])
211
215
  platform_spec = GemHelpers.select_best_platform_match(matching_specs, platform).find do |s|
212
- s.matches_current_metadata? && valid_dependencies?(s)
216
+ valid?(s)
213
217
  end
214
218
 
215
219
  if platform_spec
@@ -273,13 +277,11 @@ module Bundler
273
277
  specs_for_name = lookup[dep.name]
274
278
  return [] unless specs_for_name
275
279
 
276
- matching_specs = if dep.force_ruby_platform
277
- GemHelpers.force_ruby_platform(specs_for_name)
280
+ if platform
281
+ GemHelpers.select_best_platform_match(specs_for_name, platform, force_ruby: dep.force_ruby_platform)
278
282
  else
279
- GemHelpers.select_best_platform_match(specs_for_name, platform || Bundler.local_platform)
283
+ GemHelpers.select_best_local_platform_match(specs_for_name, force_ruby: dep.force_ruby_platform || dep.default_force_ruby_platform)
280
284
  end
281
- matching_specs.map!(&:materialize_for_installation).compact! if platform.nil?
282
- matching_specs
283
285
  end
284
286
 
285
287
  def tsort_each_child(s)
@@ -77,6 +77,14 @@ module Bundler
77
77
  stub.full_require_paths
78
78
  end
79
79
 
80
+ def require_paths
81
+ stub.require_paths
82
+ end
83
+
84
+ def base_dir=(path)
85
+ stub.base_dir = path
86
+ end
87
+
80
88
  def load_paths
81
89
  full_require_paths
82
90
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: false
2
2
 
3
3
  module Bundler
4
- VERSION = "2.5.15".freeze
4
+ VERSION = "2.5.17".freeze
5
5
 
6
6
  def self.bundler_major_version
7
7
  @bundler_major_version ||= VERSION.split(".").first.to_i
@@ -41,7 +41,7 @@ module Bundler
41
41
  HASH_REGEX = /
42
42
  ^
43
43
  ([ ]*) # indentations
44
- (.+) # key
44
+ ([^#]+) # key excludes comment char '#'
45
45
  (?::(?=(?:\s|$))) # : (without the lookahead the #key includes this when : is present in value)
46
46
  [ ]?
47
47
  (['"]?) # optional opening quote
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bundler
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.5.15
4
+ version: 2.5.17
5
5
  platform: ruby
6
6
  authors:
7
7
  - André Arko
@@ -22,7 +22,7 @@ authors:
22
22
  autorequire:
23
23
  bindir: exe
24
24
  cert_chain: []
25
- date: 2024-07-09 00:00:00.000000000 Z
25
+ date: 2024-08-01 00:00:00.000000000 Z
26
26
  dependencies: []
27
27
  description: Bundler manages an application's dependencies through its entire life,
28
28
  across many machines, systematically and repeatably
@@ -400,7 +400,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
400
400
  - !ruby/object:Gem::Version
401
401
  version: 3.2.3
402
402
  requirements: []
403
- rubygems_version: 3.5.15
403
+ rubygems_version: 3.5.17
404
404
  signing_key:
405
405
  specification_version: 4
406
406
  summary: The best way to manage your application's dependencies