rubygems-update 3.3.19 → 3.3.22

Sign up to get free protection for your applications and to get access to all the features.
Files changed (176) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +41 -0
  3. data/Manifest.txt +11 -1
  4. data/bin/update_rubygems +1 -1
  5. data/bundler/CHANGELOG.md +71 -0
  6. data/bundler/UPGRADING.md +11 -4
  7. data/bundler/bundler.gemspec +6 -8
  8. data/bundler/lib/bundler/build_metadata.rb +2 -2
  9. data/bundler/lib/bundler/cli/install.rb +5 -2
  10. data/bundler/lib/bundler/cli/outdated.rb +12 -3
  11. data/bundler/lib/bundler/cli/platform.rb +1 -1
  12. data/bundler/lib/bundler/cli.rb +7 -4
  13. data/bundler/lib/bundler/current_ruby.rb +14 -5
  14. data/bundler/lib/bundler/definition.rb +85 -33
  15. data/bundler/lib/bundler/dependency.rb +18 -85
  16. data/bundler/lib/bundler/endpoint_specification.rb +2 -13
  17. data/bundler/lib/bundler/feature_flag.rb +0 -1
  18. data/bundler/lib/bundler/fetcher.rb +6 -6
  19. data/bundler/lib/bundler/gem_helpers.rb +7 -1
  20. data/bundler/lib/bundler/gem_version_promoter.rb +8 -18
  21. data/bundler/lib/bundler/injector.rb +2 -1
  22. data/bundler/lib/bundler/inline.rb +1 -1
  23. data/bundler/lib/bundler/installer/standalone.rb +1 -1
  24. data/bundler/lib/bundler/installer.rb +14 -12
  25. data/bundler/lib/bundler/lazy_specification.rb +23 -25
  26. data/bundler/lib/bundler/lockfile_generator.rb +1 -1
  27. data/bundler/lib/bundler/man/bundle-add.1 +6 -2
  28. data/bundler/lib/bundler/man/bundle-add.1.ronn +4 -1
  29. data/bundler/lib/bundler/man/bundle-binstubs.1 +1 -1
  30. data/bundler/lib/bundler/man/bundle-cache.1 +7 -1
  31. data/bundler/lib/bundler/man/bundle-cache.1.ronn +7 -0
  32. data/bundler/lib/bundler/man/bundle-check.1 +1 -1
  33. data/bundler/lib/bundler/man/bundle-clean.1 +1 -1
  34. data/bundler/lib/bundler/man/bundle-config.1 +13 -4
  35. data/bundler/lib/bundler/man/bundle-config.1.ronn +7 -4
  36. data/bundler/lib/bundler/man/bundle-console.1 +53 -0
  37. data/bundler/lib/bundler/man/bundle-console.1.ronn +44 -0
  38. data/bundler/lib/bundler/man/bundle-doctor.1 +1 -1
  39. data/bundler/lib/bundler/man/bundle-exec.1 +1 -1
  40. data/bundler/lib/bundler/man/bundle-gem.1 +1 -1
  41. data/bundler/lib/bundler/man/bundle-help.1 +13 -0
  42. data/bundler/lib/bundler/man/bundle-help.1.ronn +12 -0
  43. data/bundler/lib/bundler/man/bundle-info.1 +1 -1
  44. data/bundler/lib/bundler/man/bundle-init.1 +1 -1
  45. data/bundler/lib/bundler/man/bundle-inject.1 +1 -1
  46. data/bundler/lib/bundler/man/bundle-install.1 +5 -1
  47. data/bundler/lib/bundler/man/bundle-install.1.ronn +6 -0
  48. data/bundler/lib/bundler/man/bundle-list.1 +1 -1
  49. data/bundler/lib/bundler/man/bundle-lock.1 +1 -1
  50. data/bundler/lib/bundler/man/bundle-open.1 +1 -1
  51. data/bundler/lib/bundler/man/bundle-outdated.1 +1 -1
  52. data/bundler/lib/bundler/man/bundle-platform.1 +16 -6
  53. data/bundler/lib/bundler/man/bundle-platform.1.ronn +14 -7
  54. data/bundler/lib/bundler/man/bundle-plugin.1 +81 -0
  55. data/bundler/lib/bundler/man/bundle-plugin.1.ronn +59 -0
  56. data/bundler/lib/bundler/man/bundle-pristine.1 +1 -1
  57. data/bundler/lib/bundler/man/bundle-remove.1 +1 -1
  58. data/bundler/lib/bundler/man/bundle-show.1 +1 -1
  59. data/bundler/lib/bundler/man/bundle-update.1 +1 -1
  60. data/bundler/lib/bundler/man/bundle-version.1 +35 -0
  61. data/bundler/lib/bundler/man/bundle-version.1.ronn +24 -0
  62. data/bundler/lib/bundler/man/bundle-viz.1 +1 -1
  63. data/bundler/lib/bundler/man/bundle.1 +13 -8
  64. data/bundler/lib/bundler/man/bundle.1.ronn +10 -5
  65. data/bundler/lib/bundler/man/gemfile.5 +8 -38
  66. data/bundler/lib/bundler/man/gemfile.5.ronn +9 -27
  67. data/bundler/lib/bundler/man/index.txt +4 -0
  68. data/bundler/lib/bundler/match_metadata.rb +13 -0
  69. data/bundler/lib/bundler/match_remote_metadata.rb +29 -0
  70. data/bundler/lib/bundler/plugin.rb +2 -0
  71. data/bundler/lib/bundler/remote_specification.rb +1 -7
  72. data/bundler/lib/bundler/resolver/base.rb +50 -0
  73. data/bundler/lib/bundler/resolver/spec_group.rb +11 -8
  74. data/bundler/lib/bundler/resolver.rb +94 -88
  75. data/bundler/lib/bundler/ruby_dsl.rb +1 -1
  76. data/bundler/lib/bundler/ruby_version.rb +5 -5
  77. data/bundler/lib/bundler/rubygems_ext.rb +52 -1
  78. data/bundler/lib/bundler/settings.rb +0 -1
  79. data/bundler/lib/bundler/source/metadata.rb +1 -1
  80. data/bundler/lib/bundler/source_list.rb +4 -0
  81. data/bundler/lib/bundler/spec_set.rb +41 -34
  82. data/bundler/lib/bundler/version.rb +1 -1
  83. data/bundler/lib/bundler.rb +3 -4
  84. data/lib/rubygems/available_set.rb +3 -3
  85. data/lib/rubygems/basic_specification.rb +2 -2
  86. data/lib/rubygems/command.rb +6 -6
  87. data/lib/rubygems/commands/cert_command.rb +1 -1
  88. data/lib/rubygems/commands/cleanup_command.rb +1 -1
  89. data/lib/rubygems/commands/contents_command.rb +1 -1
  90. data/lib/rubygems/commands/dependency_command.rb +4 -4
  91. data/lib/rubygems/commands/fetch_command.rb +2 -2
  92. data/lib/rubygems/commands/generate_index_command.rb +2 -2
  93. data/lib/rubygems/commands/install_command.rb +7 -7
  94. data/lib/rubygems/commands/pristine_command.rb +5 -5
  95. data/lib/rubygems/commands/setup_command.rb +4 -4
  96. data/lib/rubygems/commands/sources_command.rb +3 -3
  97. data/lib/rubygems/commands/specification_command.rb +2 -2
  98. data/lib/rubygems/commands/uninstall_command.rb +4 -4
  99. data/lib/rubygems/commands/update_command.rb +5 -5
  100. data/lib/rubygems/commands/which_command.rb +1 -1
  101. data/lib/rubygems/config_file.rb +7 -7
  102. data/lib/rubygems/core_ext/kernel_warn.rb +1 -1
  103. data/lib/rubygems/defaults.rb +1 -1
  104. data/lib/rubygems/dependency.rb +5 -5
  105. data/lib/rubygems/dependency_installer.rb +5 -5
  106. data/lib/rubygems/dependency_list.rb +4 -4
  107. data/lib/rubygems/doctor.rb +4 -4
  108. data/lib/rubygems/exceptions.rb +1 -1
  109. data/lib/rubygems/ext/ext_conf_builder.rb +2 -2
  110. data/lib/rubygems/gemcutter_utilities.rb +1 -1
  111. data/lib/rubygems/indexer.rb +3 -3
  112. data/lib/rubygems/installer.rb +5 -13
  113. data/lib/rubygems/name_tuple.rb +3 -3
  114. data/lib/rubygems/package/tar_header.rb +17 -17
  115. data/lib/rubygems/package/tar_writer.rb +1 -1
  116. data/lib/rubygems/package.rb +19 -8
  117. data/lib/rubygems/platform.rb +30 -19
  118. data/lib/rubygems/query_utils.rb +8 -8
  119. data/lib/rubygems/remote_fetcher.rb +3 -3
  120. data/lib/rubygems/request/connection_pools.rb +2 -2
  121. data/lib/rubygems/request/http_pool.rb +1 -1
  122. data/lib/rubygems/request.rb +1 -1
  123. data/lib/rubygems/request_set/gem_dependency_api.rb +3 -3
  124. data/lib/rubygems/request_set/lockfile/parser.rb +12 -12
  125. data/lib/rubygems/request_set/lockfile/tokenizer.rb +2 -2
  126. data/lib/rubygems/request_set.rb +3 -3
  127. data/lib/rubygems/requirement.rb +1 -1
  128. data/lib/rubygems/resolver/api_specification.rb +4 -4
  129. data/lib/rubygems/resolver/best_set.rb +3 -3
  130. data/lib/rubygems/resolver/conflict.rb +3 -3
  131. data/lib/rubygems/resolver/git_specification.rb +3 -3
  132. data/lib/rubygems/resolver/index_specification.rb +3 -2
  133. data/lib/rubygems/resolver/installed_specification.rb +2 -2
  134. data/lib/rubygems/resolver/installer_set.rb +7 -12
  135. data/lib/rubygems/resolver/lock_set.rb +1 -1
  136. data/lib/rubygems/resolver/lock_specification.rb +1 -1
  137. data/lib/rubygems/resolver/vendor_specification.rb +3 -3
  138. data/lib/rubygems/resolver.rb +4 -4
  139. data/lib/rubygems/security/policy.rb +6 -6
  140. data/lib/rubygems/security/signer.rb +1 -1
  141. data/lib/rubygems/security.rb +1 -1
  142. data/lib/rubygems/source/git.rb +4 -4
  143. data/lib/rubygems/source.rb +1 -1
  144. data/lib/rubygems/spec_fetcher.rb +1 -1
  145. data/lib/rubygems/specification.rb +26 -24
  146. data/lib/rubygems/specification_policy.rb +4 -4
  147. data/lib/rubygems/uninstaller.rb +4 -4
  148. data/lib/rubygems/user_interaction.rb +2 -2
  149. data/lib/rubygems/version.rb +12 -4
  150. data/lib/rubygems.rb +8 -8
  151. data/rubygems-update.gemspec +1 -1
  152. data/setup.rb +1 -1
  153. data/test/rubygems/helper.rb +5 -7
  154. data/test/rubygems/test_gem_commands_info_command.rb +26 -0
  155. data/test/rubygems/test_gem_config_file.rb +17 -5
  156. data/test/rubygems/test_gem_dependency_installer.rb +2 -2
  157. data/test/rubygems/test_gem_ext_cargo_builder/custom_name/Cargo.lock +4 -4
  158. data/test/rubygems/test_gem_ext_cargo_builder/custom_name/Cargo.toml +1 -1
  159. data/test/rubygems/test_gem_ext_cargo_builder/custom_name/build.rb +1 -1
  160. data/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.lock +4 -4
  161. data/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.toml +1 -1
  162. data/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/build.rb +1 -1
  163. data/test/rubygems/test_gem_installer.rb +6 -3
  164. data/test/rubygems/test_gem_package.rb +22 -0
  165. data/test/rubygems/test_gem_package_tar_reader.rb +1 -1
  166. data/test/rubygems/test_gem_platform.rb +73 -2
  167. data/test/rubygems/test_gem_requirement.rb +9 -3
  168. data/test/rubygems/test_gem_resolver.rb +37 -3
  169. data/test/rubygems/test_gem_resolver_index_specification.rb +1 -1
  170. data/test/rubygems/test_gem_resolver_installer_set.rb +44 -0
  171. data/test/rubygems/test_gem_specification.rb +11 -2
  172. data/test/rubygems/test_gem_version.rb +9 -2
  173. data/test/rubygems/test_require.rb +1 -1
  174. data/test/rubygems/utilities.rb +4 -4
  175. metadata +14 -4
  176. data/bundler/lib/bundler/incomplete_specification.rb +0 -12
@@ -97,14 +97,17 @@ module Bundler
97
97
  def metadata_dependencies(platform)
98
98
  spec = @specs[platform].first
99
99
  return [] if spec.is_a?(LazySpecification)
100
- dependencies = []
101
- unless spec.required_ruby_version.none?
102
- dependencies << DepProxy.get_proxy(Dependency.new("Ruby\0", spec.required_ruby_version), platform)
103
- end
104
- unless spec.required_rubygems_version.none?
105
- dependencies << DepProxy.get_proxy(Dependency.new("RubyGems\0", spec.required_rubygems_version), platform)
106
- end
107
- dependencies
100
+
101
+ [
102
+ metadata_dependency("Ruby", spec.required_ruby_version, platform),
103
+ metadata_dependency("RubyGems", spec.required_rubygems_version, platform),
104
+ ].compact
105
+ end
106
+
107
+ def metadata_dependency(name, requirement, platform)
108
+ return if requirement.nil? || requirement.none?
109
+
110
+ DepProxy.get_proxy(Dependency.new("#{name}\0", requirement), platform)
108
111
  end
109
112
  end
110
113
  end
@@ -3,6 +3,7 @@
3
3
  module Bundler
4
4
  class Resolver
5
5
  require_relative "vendored_molinillo"
6
+ require_relative "resolver/base"
6
7
  require_relative "resolver/spec_group"
7
8
 
8
9
  include GemHelpers
@@ -19,43 +20,54 @@ module Bundler
19
20
  # collection of gemspecs is returned. Otherwise, nil is returned.
20
21
  def self.resolve(requirements, source_requirements = {}, base = [], gem_version_promoter = GemVersionPromoter.new, additional_base_requirements = [], platforms = nil)
21
22
  base = SpecSet.new(base) unless base.is_a?(SpecSet)
22
- metadata_requirements, regular_requirements = requirements.partition {|dep| dep.name.end_with?("\0") }
23
- resolver = new(source_requirements, base, gem_version_promoter, additional_base_requirements, platforms, metadata_requirements)
24
- result = resolver.start(requirements)
25
- SpecSet.new(SpecSet.new(result).for(regular_requirements, false, platforms))
23
+ resolver = new(source_requirements, base, gem_version_promoter, additional_base_requirements, platforms)
24
+ resolver.start(requirements)
26
25
  end
27
26
 
28
- def initialize(source_requirements, base, gem_version_promoter, additional_base_requirements, platforms, metadata_requirements)
27
+ def initialize(source_requirements, base, gem_version_promoter, additional_base_requirements, platforms)
29
28
  @source_requirements = source_requirements
30
- @metadata_requirements = metadata_requirements
29
+ @base = Resolver::Base.new(base, additional_base_requirements)
31
30
  @resolver = Molinillo::Resolver.new(self, self)
31
+ @results_for = {}
32
32
  @search_for = {}
33
- @base_dg = Molinillo::DependencyGraph.new
34
- @base = base.materialized_for_resolution do |ls|
35
- dep = Dependency.new(ls.name, ls.version)
36
- @base_dg.add_vertex(ls.name, DepProxy.get_proxy(dep, ls.platform), true)
37
- end
38
- additional_base_requirements.each {|d| @base_dg.add_vertex(d.name, d) }
39
- @platforms = platforms.reject {|p| p != Gem::Platform::RUBY && (platforms - [p]).any? {|pl| generic(pl) == p } }
33
+ @platforms = platforms
40
34
  @resolving_only_for_ruby = platforms == [Gem::Platform::RUBY]
41
35
  @gem_version_promoter = gem_version_promoter
42
- @use_gvp = Bundler.feature_flag.use_gem_version_promoter_for_major_updates? || !@gem_version_promoter.major?
43
36
  end
44
37
 
45
- def start(requirements)
38
+ def start(requirements, exclude_specs: [])
39
+ @metadata_requirements, regular_requirements = requirements.partition {|dep| dep.name.end_with?("\0") }
40
+
41
+ exclude_specs.each do |spec|
42
+ remove_from_candidates(spec)
43
+ end
44
+
46
45
  @gem_version_promoter.prerelease_specified = @prerelease_specified = {}
47
46
  requirements.each {|dep| @prerelease_specified[dep.name] ||= dep.prerelease? }
48
47
 
49
48
  verify_gemfile_dependencies_are_found!(requirements)
50
- dg = @resolver.resolve(requirements, @base_dg)
51
- dg.
49
+ result = @resolver.resolve(requirements).
52
50
  map(&:payload).
53
51
  reject {|sg| sg.name.end_with?("\0") }.
54
52
  map(&:to_specs).
55
53
  flatten
54
+
55
+ SpecSet.new(SpecSet.new(result).for(regular_requirements, false, @platforms))
56
56
  rescue Molinillo::VersionConflict => e
57
+ conflicts = e.conflicts
58
+
59
+ deps_to_unlock = conflicts.values.inject([]) do |deps, conflict|
60
+ deps |= conflict.requirement_trees.flatten.map {|req| base_requirements[req.name] }.compact
61
+ end
62
+
63
+ if deps_to_unlock.any?
64
+ @base.unlock_deps(deps_to_unlock)
65
+ reset_spec_cache
66
+ retry
67
+ end
68
+
57
69
  message = version_conflict_message(e)
58
- raise VersionConflict.new(e.conflicts.keys.uniq, message)
70
+ raise VersionConflict.new(conflicts.keys.uniq, message)
59
71
  rescue Molinillo::CircularDependencyError => e
60
72
  names = e.dependencies.sort_by(&:name).map {|d| "gem '#{d.name}'" }
61
73
  raise CyclicDependencyError, "Your bundle requires gems that depend" \
@@ -110,31 +122,22 @@ module Bundler
110
122
  dependency = dependency_proxy.dep
111
123
  name = dependency.name
112
124
  @search_for[dependency_proxy] ||= begin
113
- results = results_for(dependency) + @base[name].select {|spec| requirement_satisfied_by?(dependency, nil, spec) }
114
-
115
- if vertex = @base_dg.vertex_named(name)
116
- locked_requirement = vertex.payload.requirement
117
- end
125
+ locked_results = @base[name].select {|spec| requirement_satisfied_by?(dependency, nil, spec) }
126
+ locked_requirement = base_requirements[name]
127
+ results = results_for(dependency) + locked_results
128
+ results = results.select {|spec| requirement_satisfied_by?(locked_requirement, nil, spec) } if locked_requirement
118
129
 
119
- if !@prerelease_specified[name] && (!@use_gvp || locked_requirement.nil?)
130
+ if !@prerelease_specified[name] && locked_results.empty?
120
131
  # Move prereleases to the beginning of the list, so they're considered
121
132
  # last during resolution.
122
133
  pre, results = results.partition {|spec| spec.version.prerelease? }
123
134
  results = pre + results
124
135
  end
125
136
 
126
- spec_groups = if results.any?
127
- nested = []
128
- results.each do |spec|
129
- version, specs = nested.last
130
- if version == spec.version
131
- specs << spec
132
- else
133
- nested << [spec.version, [spec]]
134
- end
135
- end
136
- nested.reduce([]) do |groups, (version, specs)|
137
- next groups if locked_requirement && !locked_requirement.satisfied_by?(version)
137
+ if results.any?
138
+ results = @gem_version_promoter.sort_versions(dependency, results)
139
+
140
+ results.group_by(&:version).reduce([]) do |groups, (_, specs)|
138
141
  next groups unless specs.any? {|spec| spec.match_platform(platform) }
139
142
 
140
143
  specs_by_platform = Hash.new do |current_specs, current_platform|
@@ -157,13 +160,6 @@ module Bundler
157
160
  else
158
161
  []
159
162
  end
160
- # GVP handles major itself, but it's still a bit risky to trust it with it
161
- # until we get it settled with new behavior. For 2.x it can take over all cases.
162
- if !@use_gvp
163
- spec_groups
164
- else
165
- @gem_version_promoter.sort_versions(dependency, spec_groups)
166
- end
167
163
  end
168
164
  end
169
165
 
@@ -176,7 +172,7 @@ module Bundler
176
172
  end
177
173
 
178
174
  def results_for(dependency)
179
- index_for(dependency).search(dependency)
175
+ @results_for[dependency] ||= index_for(dependency).search(dependency)
180
176
  end
181
177
 
182
178
  def name_for(dependency)
@@ -189,12 +185,6 @@ module Bundler
189
185
  "Gemfile"
190
186
  end
191
187
 
192
- def name_for_locking_dependency_source
193
- Bundler.default_lockfile.basename.to_s
194
- rescue StandardError
195
- "Gemfile.lock"
196
- end
197
-
198
188
  def requirement_satisfied_by?(requirement, activated, spec)
199
189
  requirement.matches_spec?(spec) || spec.source.is_a?(Source::Gemspec)
200
190
  end
@@ -208,7 +198,7 @@ module Bundler
208
198
  name = name_for(dependency)
209
199
  vertex = activated.vertex_named(name)
210
200
  [
211
- @base_dg.vertex_named(name) ? 0 : 1,
201
+ @base[name].any? ? 0 : 1,
212
202
  vertex.payload ? 0 : 1,
213
203
  vertex.root? ? 0 : 1,
214
204
  amount_constrained(dependency),
@@ -227,6 +217,27 @@ module Bundler
227
217
 
228
218
  private
229
219
 
220
+ def base_requirements
221
+ @base.base_requirements
222
+ end
223
+
224
+ def remove_from_candidates(spec)
225
+ @base.delete(spec)
226
+
227
+ @results_for.keys.each do |dep|
228
+ next unless dep.name == spec.name
229
+
230
+ @results_for[dep].reject {|s| s.name == spec.name && s.version == spec.version }
231
+ end
232
+
233
+ reset_spec_cache
234
+ end
235
+
236
+ def reset_spec_cache
237
+ @search_for = {}
238
+ @gem_version_promoter.reset
239
+ end
240
+
230
241
  # returns an integer \in (-\infty, 0]
231
242
  # a number closer to 0 means the dependency is less constraining
232
243
  #
@@ -316,18 +327,6 @@ module Bundler
316
327
 
317
328
  e.message_with_trees(
318
329
  :full_message_for_conflict => lambda do |name, conflict|
319
- o = if name.end_with?("\0")
320
- String.new("Bundler found conflicting requirements for the #{name} version:")
321
- else
322
- String.new("Bundler could not find compatible versions for gem \"#{name}\":")
323
- end
324
- o << %(\n)
325
- if conflict.locked_requirement
326
- o << %( In snapshot (#{name_for_locking_dependency_source}):\n)
327
- o << %( #{SharedHelpers.pretty_dependency(conflict.locked_requirement)}\n)
328
- o << %(\n)
329
- end
330
- o << %( In #{name_for_explicit_dependency_source}:\n)
331
330
  trees = conflict.requirement_trees
332
331
 
333
332
  # called first, because we want to reduce the amount of work required to find maximal empty sets
@@ -346,30 +345,41 @@ module Bundler
346
345
  trees.sort_by! {|t| t.reverse.map(&:name) }
347
346
  end
348
347
 
349
- o << trees.map do |tree|
350
- t = "".dup
351
- depth = 2
348
+ if trees.size > 1 || name == "bundler"
349
+ o = if name.end_with?("\0")
350
+ String.new("Bundler found conflicting requirements for the #{name} version:")
351
+ else
352
+ String.new("Bundler could not find compatible versions for gem \"#{name}\":")
353
+ end
354
+ o << %(\n)
355
+ o << %( In #{name_for_explicit_dependency_source}:\n)
356
+ o << trees.map do |tree|
357
+ t = "".dup
358
+ depth = 2
352
359
 
353
- base_tree = tree.first
354
- base_tree_name = base_tree.name
360
+ base_tree = tree.first
361
+ base_tree_name = base_tree.name
355
362
 
356
- if base_tree_name.end_with?("\0")
357
- t = nil
358
- else
359
- tree.each do |req|
360
- t << " " * depth << SharedHelpers.pretty_dependency(req)
361
- unless tree.last == req
362
- if spec = conflict.activated_by_name[req.name]
363
- t << %( was resolved to #{spec.version}, which)
363
+ if base_tree_name.end_with?("\0")
364
+ t = nil
365
+ else
366
+ tree.each do |req|
367
+ t << " " * depth << SharedHelpers.pretty_dependency(req)
368
+ unless tree.last == req
369
+ if spec = conflict.activated_by_name[req.name]
370
+ t << %( was resolved to #{spec.version}, which)
371
+ end
372
+ t << %( depends on)
364
373
  end
365
- t << %( depends on)
374
+ t << %(\n)
375
+ depth += 1
366
376
  end
367
- t << %(\n)
368
- depth += 1
369
377
  end
370
- end
371
- t
372
- end.compact.join("\n")
378
+ t
379
+ end.compact.join("\n")
380
+ else
381
+ o = String.new
382
+ end
373
383
 
374
384
  if name == "bundler"
375
385
  o << %(\n Current Bundler version:\n bundler (#{Bundler::VERSION}))
@@ -393,17 +403,13 @@ module Bundler
393
403
  end
394
404
  elsif name.end_with?("\0")
395
405
  o << %(\n Current #{name} version:\n #{SharedHelpers.pretty_dependency(@metadata_requirements.find {|req| req.name == name })}\n\n)
396
- elsif conflict.locked_requirement
397
- o << "\n"
398
- o << %(Deleting your #{name_for_locking_dependency_source} file and running `bundle install` will rebuild your snapshot from scratch, using only\n)
399
- o << %(the gems in your Gemfile, which may resolve the conflict.\n)
400
406
  elsif !conflict.existing
401
407
  o << "\n"
402
408
 
403
409
  relevant_source = conflict.requirement.source || source_for(name)
404
410
 
405
- extra_message = if conflict.requirement_trees.first.size > 1
406
- ", which is required by gem '#{SharedHelpers.pretty_dependency(conflict.requirement_trees.first[-2])}',"
411
+ extra_message = if trees.first.size > 1
412
+ ", which is required by gem '#{SharedHelpers.pretty_dependency(trees.first[-2])}',"
407
413
  else
408
414
  ""
409
415
  end
@@ -9,7 +9,7 @@ module Bundler
9
9
  raise GemfileError, "Please define :engine" if options[:engine_version] && options[:engine].nil?
10
10
 
11
11
  if options[:engine] == "ruby" && options[:engine_version] &&
12
- ruby_version != Array(options[:engine_version])
12
+ ruby_version != Array(options[:engine_version])
13
13
  raise GemfileEvalError, "ruby_version must match the :engine_version for MRI"
14
14
  end
15
15
  @ruby_version = RubyVersion.new(ruby_version, options[:patchlevel], options[:engine], options[:engine_version])
@@ -32,12 +32,12 @@ module Bundler
32
32
  @engine = engine && engine.to_s || "ruby"
33
33
  @engine_versions = (engine_version && Array(engine_version)) || @versions
34
34
  @engine_gem_version = Gem::Requirement.create(@engine_versions.first).requirements.first.last
35
- @patchlevel = patchlevel
35
+ @patchlevel = patchlevel || (@gem_version.prerelease? ? "-1" : nil)
36
36
  end
37
37
 
38
38
  def to_s(versions = self.versions)
39
39
  output = String.new("ruby #{versions_string(versions)}")
40
- output << "p#{patchlevel}" if patchlevel
40
+ output << "p#{patchlevel}" if patchlevel && patchlevel != "-1"
41
41
  output << " (#{engine} #{versions_string(engine_versions)})" unless engine == "ruby"
42
42
 
43
43
  output
@@ -46,7 +46,7 @@ module Bundler
46
46
  # @private
47
47
  PATTERN = /
48
48
  ruby\s
49
- ([\d.]+) # ruby version
49
+ (\d+\.\d+\.\d+(?:\.\S+)?) # ruby version
50
50
  (?:p(-?\d+))? # optional patchlevel
51
51
  (?:\s\((\S+)\s(.+)\))? # optional engine info
52
52
  /xo.freeze
@@ -103,8 +103,8 @@ module Bundler
103
103
 
104
104
  def self.system
105
105
  ruby_engine = RUBY_ENGINE.dup
106
- ruby_version = RUBY_VERSION.dup
107
- ruby_engine_version = RUBY_ENGINE_VERSION.dup
106
+ ruby_version = Gem.ruby_version.to_s
107
+ ruby_engine_version = RUBY_ENGINE == "ruby" ? ruby_version : RUBY_ENGINE_VERSION.dup
108
108
  patchlevel = RUBY_PATCHLEVEL.to_s
109
109
 
110
110
  @ruby_version ||= RubyVersion.new(ruby_version, patchlevel, ruby_engine, ruby_engine_version)
@@ -15,10 +15,21 @@ require "rubygems/specification"
15
15
  # `Gem::Source` from the redefined `Gem::Specification#source`.
16
16
  require "rubygems/source"
17
17
 
18
+ require_relative "match_metadata"
18
19
  require_relative "match_platform"
19
20
 
21
+ # Cherry-pick fixes to `Gem.ruby_version` to be useful for modern Bundler
22
+ # versions and ignore patchlevels
23
+ # (https://github.com/rubygems/rubygems/pull/5472,
24
+ # https://github.com/rubygems/rubygems/pull/5486). May be removed once RubyGems
25
+ # 3.3.12 support is dropped.
26
+ unless Gem.ruby_version.to_s == RUBY_VERSION || RUBY_PATCHLEVEL == -1
27
+ Gem.instance_variable_set(:@ruby_version, Gem::Version.new(RUBY_VERSION))
28
+ end
29
+
20
30
  module Gem
21
31
  class Specification
32
+ include ::Bundler::MatchMetadata
22
33
  include ::Bundler::MatchPlatform
23
34
 
24
35
  attr_accessor :remote, :location, :relative_loaded_from
@@ -146,6 +157,10 @@ module Gem
146
157
 
147
158
  alias_method :eql?, :==
148
159
 
160
+ def force_ruby_platform
161
+ false
162
+ end
163
+
149
164
  def encode_with(coder)
150
165
  to_yaml_properties.each do |ivar|
151
166
  coder[ivar.to_s.sub(/^@/, "")] = instance_variable_get(ivar)
@@ -222,6 +237,35 @@ module Gem
222
237
  MINGW = Gem::Platform.new("x86-mingw32")
223
238
  X64_MINGW = [Gem::Platform.new("x64-mingw32"),
224
239
  Gem::Platform.new("x64-mingw-ucrt")].freeze
240
+ WINDOWS = [MSWIN, MSWIN64, MINGW, X64_MINGW].flatten.freeze
241
+ X64_LINUX = Gem::Platform.new("x86_64-linux")
242
+ X64_LINUX_MUSL = Gem::Platform.new("x86_64-linux-musl")
243
+
244
+ if X64_LINUX === X64_LINUX_MUSL
245
+ remove_method :===
246
+
247
+ def ===(other)
248
+ return nil unless Gem::Platform === other
249
+
250
+ # universal-mingw32 matches x64-mingw-ucrt
251
+ return true if (@cpu == "universal" || other.cpu == "universal") &&
252
+ @os.start_with?("mingw") && other.os.start_with?("mingw")
253
+
254
+ # cpu
255
+ ([nil,"universal"].include?(@cpu) || [nil, "universal"].include?(other.cpu) || @cpu == other.cpu ||
256
+ (@cpu == "arm" && other.cpu.start_with?("arm"))) &&
257
+
258
+ # os
259
+ @os == other.os &&
260
+
261
+ # version
262
+ (
263
+ (@os != "linux" && (@version.nil? || other.version.nil?)) ||
264
+ (@os == "linux" && (other.version == "gnu#{@version}" || other.version == "musl#{@version}" || @version == "gnu#{other.version}")) ||
265
+ @version == other.version
266
+ )
267
+ end
268
+ end
225
269
  end
226
270
 
227
271
  Platform.singleton_class.module_eval do
@@ -233,14 +277,21 @@ module Gem
233
277
  def match_gem?(platform, gem_name)
234
278
  match_platforms?(platform, Gem.platforms)
235
279
  end
280
+ end
281
+
282
+ match_platforms_defined = Gem::Platform.respond_to?(:match_platforms?, true)
283
+
284
+ if !match_platforms_defined || Gem::Platform.send(:match_platforms?, Gem::Platform::X64_LINUX_MUSL, [Gem::Platform::X64_LINUX])
236
285
 
237
286
  private
238
287
 
288
+ remove_method :match_platforms? if match_platforms_defined
289
+
239
290
  def match_platforms?(platform, platforms)
240
291
  platforms.any? do |local_platform|
241
292
  platform.nil? ||
242
293
  local_platform == platform ||
243
- (local_platform != Gem::Platform::RUBY && local_platform =~ platform)
294
+ (local_platform != Gem::Platform::RUBY && platform =~ local_platform)
244
295
  end
245
296
  end
246
297
  end
@@ -45,7 +45,6 @@ module Bundler
45
45
  silence_root_warning
46
46
  suppress_install_using_messages
47
47
  update_requires_all_flag
48
- use_gem_version_promoter_for_major_updates
49
48
  ].freeze
50
49
 
51
50
  NUMBER_KEYS = %w[
@@ -5,7 +5,7 @@ module Bundler
5
5
  class Metadata < Source
6
6
  def specs
7
7
  @specs ||= Index.build do |idx|
8
- idx << Gem::Specification.new("Ruby\0", RubyVersion.system.gem_version)
8
+ idx << Gem::Specification.new("Ruby\0", Gem.ruby_version)
9
9
  idx << Gem::Specification.new("RubyGems\0", Gem::VERSION) do |s|
10
10
  s.required_rubygems_version = Gem::Requirement.default
11
11
  end
@@ -101,6 +101,10 @@ module Bundler
101
101
  source_list_for(source).find {|s| equivalent_source?(source, s) }
102
102
  end
103
103
 
104
+ def get_with_fallback(source)
105
+ get(source) || default_source
106
+ end
107
+
104
108
  def lock_sources
105
109
  lock_other_sources + lock_rubygems_sources
106
110
  end
@@ -7,20 +7,28 @@ module Bundler
7
7
  include Enumerable
8
8
  include TSort
9
9
 
10
- def initialize(specs)
10
+ attr_reader :incomplete_specs
11
+
12
+ def initialize(specs, incomplete_specs = [])
11
13
  @specs = specs
14
+ @incomplete_specs = incomplete_specs
12
15
  end
13
16
 
14
17
  def for(dependencies, check = false, platforms = [nil])
15
18
  handled = ["bundler"].product(platforms).map {|k| [k, true] }.to_h
16
- deps = dependencies.product(platforms).map {|dep, platform| [dep.name, platform && dep.force_ruby_platform ? Gem::Platform::RUBY : platform] }
19
+ deps = dependencies.product(platforms)
17
20
  specs = []
18
21
 
19
22
  loop do
20
23
  break unless dep = deps.shift
21
- next if handled.key?(dep)
22
24
 
23
- handled[dep] = true
25
+ name = dep[0].name
26
+ platform = dep[1]
27
+
28
+ key = [name, platform]
29
+ next if handled.key?(key)
30
+
31
+ handled[key] = true
24
32
 
25
33
  specs_for_dep = specs_for_dependency(*dep)
26
34
  if specs_for_dep.any?
@@ -28,17 +36,13 @@ module Bundler
28
36
 
29
37
  specs_for_dep.first.dependencies.each do |d|
30
38
  next if d.type == :development
31
- deps << [d.name, dep[1]]
39
+ deps << [d, dep[1]]
32
40
  end
33
41
  elsif check
34
- specs << IncompleteSpecification.new(*dep)
42
+ @incomplete_specs += lookup[name]
35
43
  end
36
44
  end
37
45
 
38
- if spec = lookup["bundler"].first
39
- specs << spec
40
- end
41
-
42
46
  specs
43
47
  end
44
48
 
@@ -53,6 +57,12 @@ module Bundler
53
57
  @sorted = nil
54
58
  end
55
59
 
60
+ def delete(spec)
61
+ @specs.delete(spec)
62
+ @lookup = nil
63
+ @sorted = nil
64
+ end
65
+
56
66
  def sort!
57
67
  self
58
68
  end
@@ -66,14 +76,9 @@ module Bundler
66
76
  end
67
77
 
68
78
  def materialize(deps)
69
- materialized = self.for(deps, true).uniq
79
+ materialized = self.for(deps, true)
70
80
 
71
- materialized.map! do |s|
72
- next s unless s.is_a?(LazySpecification)
73
- s.source.local!
74
- s.materialize_for_installation || s
75
- end
76
- SpecSet.new(materialized)
81
+ SpecSet.new(materialized, incomplete_specs)
77
82
  end
78
83
 
79
84
  # Materialize for all the specs in the spec set, regardless of what platform they're for
@@ -82,7 +87,6 @@ module Bundler
82
87
  def materialized_for_all_platforms
83
88
  @specs.map do |s|
84
89
  next s unless s.is_a?(LazySpecification)
85
- s.source.local!
86
90
  s.source.remote!
87
91
  spec = s.materialize_for_installation
88
92
  raise GemNotFound, "Could not find #{s.full_name} in any of the sources" unless spec
@@ -90,23 +94,16 @@ module Bundler
90
94
  end
91
95
  end
92
96
 
93
- def materialized_for_resolution
94
- materialized = @specs.map do |s|
95
- spec = s.materialize_for_resolution
96
- yield spec if spec
97
- spec
98
- end.compact
99
- SpecSet.new(materialized)
97
+ def incomplete_ruby_specs?(deps)
98
+ self.for(deps, true, [Gem::Platform::RUBY])
99
+
100
+ @incomplete_specs.any?
100
101
  end
101
102
 
102
103
  def missing_specs
103
104
  @specs.select {|s| s.is_a?(LazySpecification) }
104
105
  end
105
106
 
106
- def incomplete_specs
107
- @specs.select {|s| s.is_a?(IncompleteSpecification) }
108
- end
109
-
110
107
  def merge(set)
111
108
  arr = sorted.dup
112
109
  set.each do |set_spec|
@@ -117,10 +114,20 @@ module Bundler
117
114
  SpecSet.new(arr)
118
115
  end
119
116
 
117
+ def -(other)
118
+ SpecSet.new(to_a - other.to_a)
119
+ end
120
+
120
121
  def find_by_name_and_platform(name, platform)
121
122
  @specs.detect {|spec| spec.name == name && spec.match_platform(platform) }
122
123
  end
123
124
 
125
+ def delete_by_name_and_version(name, version)
126
+ @specs.reject! {|spec| spec.name == name && spec.version == version }
127
+ @lookup = nil
128
+ @sorted = nil
129
+ end
130
+
124
131
  def what_required(spec)
125
132
  unless req = find {|s| s.dependencies.any? {|d| d.type == :runtime && d.name == spec.name } }
126
133
  return [spec]
@@ -181,13 +188,13 @@ module Bundler
181
188
  @specs.sort_by(&:name).each {|s| yield s }
182
189
  end
183
190
 
184
- def specs_for_dependency(name, platform)
185
- specs_for_name = lookup[name]
191
+ def specs_for_dependency(dep, platform)
192
+ specs_for_name = lookup[dep.name]
186
193
  if platform.nil?
187
- GemHelpers.select_best_platform_match(specs_for_name.select {|s| Gem::Platform.match_spec?(s) }, Bundler.local_platform)
194
+ matching_specs = specs_for_name.map {|s| s.materialize_for_installation if Gem::Platform.match_spec?(s) }.compact
195
+ GemHelpers.sort_best_platform_match(matching_specs, Bundler.local_platform)
188
196
  else
189
- specs_for_name_and_platform = GemHelpers.select_best_platform_match(specs_for_name, platform)
190
- specs_for_name_and_platform.any? ? specs_for_name_and_platform : specs_for_name
197
+ GemHelpers.select_best_platform_match(specs_for_name, dep.force_ruby_platform ? Gem::Platform::RUBY : platform)
191
198
  end
192
199
  end
193
200
 
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: false
2
2
 
3
3
  module Bundler
4
- VERSION = "2.3.19".freeze
4
+ VERSION = "2.3.22".freeze
5
5
 
6
6
  def self.bundler_major_version
7
7
  @bundler_major_version ||= VERSION.split(".").first.to_i