bundler 4.0.22 → 4.1.0.beta2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (200) hide show
  1. checksums.yaml +4 -4
  2. data/{lib/bundler/vendor/connection_pool/LICENSE → MIT.txt} +8 -6
  3. data/bundler.gemspec +23 -6
  4. data/lib/bundler/build_metadata.rb +2 -2
  5. data/lib/bundler/checksum.rb +40 -25
  6. data/lib/bundler/ci_detector.rb +1 -1
  7. data/lib/bundler/cli/add.rb +3 -4
  8. data/lib/bundler/cli/cache.rb +4 -0
  9. data/lib/bundler/cli/clean.rb +5 -0
  10. data/lib/bundler/cli/common.rb +41 -1
  11. data/lib/bundler/cli/config.rb +4 -2
  12. data/lib/bundler/cli/doctor/ssl.rb +4 -8
  13. data/lib/bundler/cli/gem.rb +0 -17
  14. data/lib/bundler/cli/info.rb +1 -1
  15. data/lib/bundler/cli/install.rb +4 -5
  16. data/lib/bundler/cli/lock.rb +15 -5
  17. data/lib/bundler/cli/open.rb +7 -1
  18. data/lib/bundler/cli/outdated.rb +16 -13
  19. data/lib/bundler/cli/pristine.rb +2 -1
  20. data/lib/bundler/cli/show.rb +5 -1
  21. data/lib/bundler/cli/update.rb +20 -11
  22. data/lib/bundler/cli.rb +15 -9
  23. data/lib/bundler/constants.rb +1 -1
  24. data/lib/bundler/definition.rb +102 -15
  25. data/lib/bundler/dependency.rb +4 -0
  26. data/lib/bundler/dsl.rb +137 -13
  27. data/lib/bundler/endpoint_specification.rb +51 -14
  28. data/lib/bundler/env.rb +7 -24
  29. data/lib/bundler/errors.rb +34 -5
  30. data/lib/bundler/fetcher/compact_index.rb +14 -5
  31. data/lib/bundler/fetcher/connection_pools.rb +150 -0
  32. data/lib/bundler/fetcher/downloader.rb +35 -16
  33. data/lib/bundler/fetcher.rb +8 -47
  34. data/lib/bundler/gem_helper.rb +1 -1
  35. data/lib/bundler/injector.rb +3 -3
  36. data/lib/bundler/inline.rb +44 -4
  37. data/lib/bundler/installer/parallel_installer.rb +27 -31
  38. data/lib/bundler/installer.rb +21 -7
  39. data/lib/bundler/lazy_specification.rb +45 -18
  40. data/lib/bundler/lockfile_generator.rb +24 -2
  41. data/lib/bundler/lockfile_parser.rb +44 -6
  42. data/lib/bundler/man/bundle-add.1 +7 -4
  43. data/lib/bundler/man/bundle-add.1.ronn +8 -4
  44. data/lib/bundler/man/bundle-binstubs.1 +1 -1
  45. data/lib/bundler/man/bundle-cache.1 +2 -2
  46. data/lib/bundler/man/bundle-cache.1.ronn +2 -2
  47. data/lib/bundler/man/bundle-check.1 +1 -1
  48. data/lib/bundler/man/bundle-clean.1 +1 -1
  49. data/lib/bundler/man/bundle-config.1 +38 -6
  50. data/lib/bundler/man/bundle-config.1.ronn +143 -10
  51. data/lib/bundler/man/bundle-console.1 +1 -1
  52. data/lib/bundler/man/bundle-doctor.1 +1 -1
  53. data/lib/bundler/man/bundle-env.1 +1 -1
  54. data/lib/bundler/man/bundle-exec.1 +1 -1
  55. data/lib/bundler/man/bundle-fund.1 +1 -1
  56. data/lib/bundler/man/bundle-gem.1 +1 -1
  57. data/lib/bundler/man/bundle-help.1 +1 -1
  58. data/lib/bundler/man/bundle-info.1 +5 -2
  59. data/lib/bundler/man/bundle-info.1.ronn +4 -0
  60. data/lib/bundler/man/bundle-init.1 +1 -1
  61. data/lib/bundler/man/bundle-install.1 +2 -2
  62. data/lib/bundler/man/bundle-install.1.ronn +4 -4
  63. data/lib/bundler/man/bundle-issue.1 +1 -1
  64. data/lib/bundler/man/bundle-licenses.1 +1 -1
  65. data/lib/bundler/man/bundle-list.1 +1 -1
  66. data/lib/bundler/man/bundle-lock.1 +2 -2
  67. data/lib/bundler/man/bundle-lock.1.ronn +3 -2
  68. data/lib/bundler/man/bundle-open.1 +5 -2
  69. data/lib/bundler/man/bundle-open.1.ronn +4 -1
  70. data/lib/bundler/man/bundle-outdated.1 +1 -1
  71. data/lib/bundler/man/bundle-platform.1 +1 -1
  72. data/lib/bundler/man/bundle-plugin.1 +1 -1
  73. data/lib/bundler/man/bundle-pristine.1 +1 -1
  74. data/lib/bundler/man/bundle-remove.1 +1 -1
  75. data/lib/bundler/man/bundle-show.1 +5 -2
  76. data/lib/bundler/man/bundle-show.1.ronn +4 -0
  77. data/lib/bundler/man/bundle-update.1 +2 -2
  78. data/lib/bundler/man/bundle-update.1.ronn +2 -2
  79. data/lib/bundler/man/bundle-version.1 +1 -1
  80. data/lib/bundler/man/bundle.1 +1 -1
  81. data/lib/bundler/man/gemfile.5 +77 -1
  82. data/lib/bundler/man/gemfile.5.ronn +104 -0
  83. data/lib/bundler/match_metadata.rb +20 -0
  84. data/lib/bundler/match_platform.rb +25 -2
  85. data/lib/bundler/match_remote_metadata.rb +21 -6
  86. data/lib/bundler/materialization.rb +5 -2
  87. data/lib/bundler/override.rb +97 -0
  88. data/lib/bundler/plugin/dsl.rb +3 -5
  89. data/lib/bundler/plugin/events.rb +55 -13
  90. data/lib/bundler/plugin/index.rb +87 -11
  91. data/lib/bundler/plugin/installer/path.rb +1 -1
  92. data/lib/bundler/plugin/installer.rb +13 -5
  93. data/lib/bundler/plugin.rb +58 -30
  94. data/lib/bundler/remote_specification.rb +6 -3
  95. data/lib/bundler/resolver/base.rb +2 -1
  96. data/lib/bundler/resolver/incompatibility.rb +1 -1
  97. data/lib/bundler/resolver.rb +97 -23
  98. data/lib/bundler/ruby_version.rb +0 -2
  99. data/lib/bundler/rubygems_ext.rb +71 -1
  100. data/lib/bundler/rubygems_gem_installer.rb +41 -2
  101. data/lib/bundler/rubygems_integration.rb +7 -2
  102. data/lib/bundler/runtime.rb +69 -2
  103. data/lib/bundler/settings.rb +383 -56
  104. data/lib/bundler/shared_helpers.rb +2 -1
  105. data/lib/bundler/source/git/git_proxy.rb +31 -2
  106. data/lib/bundler/source/git.rb +49 -13
  107. data/lib/bundler/source/path/installer.rb +1 -1
  108. data/lib/bundler/source/rubygems/remote.rb +10 -5
  109. data/lib/bundler/source/rubygems.rb +48 -12
  110. data/lib/bundler/source/rubygems_aggregate.rb +1 -1
  111. data/lib/bundler/source_map.rb +7 -3
  112. data/lib/bundler/spec_set.rb +23 -7
  113. data/lib/bundler/stub_specification.rb +2 -1
  114. data/lib/bundler/templates/newgem/Gemfile.tt +4 -4
  115. data/lib/bundler/templates/newgem/newgem.gemspec.tt +3 -3
  116. data/lib/bundler/templates/newgem/spec/newgem_spec.rb.tt +1 -1
  117. data/lib/bundler/templates/newgem/test/minitest/test_newgem.rb.tt +1 -1
  118. data/lib/bundler/ui/shell.rb +0 -4
  119. data/lib/bundler/ui/silent.rb +0 -4
  120. data/lib/bundler/vendor/thor/lib/thor/actions/inject_into_file.rb +35 -2
  121. data/lib/bundler/vendor/thor/lib/thor/base.rb +2 -1
  122. data/lib/bundler/vendor/thor/lib/thor/shell/basic.rb +14 -6
  123. data/lib/bundler/vendor/thor/lib/thor/shell/color.rb +2 -0
  124. data/lib/bundler/vendor/thor/lib/thor/version.rb +1 -1
  125. data/lib/bundler/vendor/thor/lib/thor.rb +34 -1
  126. data/lib/bundler/vendored_pub_grub.rb +5 -2
  127. data/lib/bundler/vendored_securerandom.rb +11 -8
  128. data/lib/bundler/vendored_uri.rb +14 -14
  129. data/lib/bundler/version.rb +1 -1
  130. data/lib/bundler/worker.rb +3 -2
  131. data/lib/bundler.rb +1 -1
  132. data/lib/rubygems/compact_index_client/cache.rb +122 -0
  133. data/lib/rubygems/compact_index_client/cache_file.rb +147 -0
  134. data/lib/rubygems/compact_index_client/http_fetcher.rb +90 -0
  135. data/lib/rubygems/compact_index_client/parser.rb +90 -0
  136. data/lib/rubygems/compact_index_client/updater.rb +113 -0
  137. data/lib/rubygems/compact_index_client.rb +111 -0
  138. data/lib/rubygems/cooldown_settings.rb +57 -0
  139. data/lib/rubygems/credential_store/native/linux.rb +97 -0
  140. data/lib/rubygems/credential_store/native/macos.rb +88 -0
  141. data/lib/rubygems/credential_store/native/windows.rb +130 -0
  142. data/lib/rubygems/credential_store.rb +332 -0
  143. data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/assignment.rb +1 -1
  144. data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/basic_package_source.rb +7 -7
  145. data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/failure_writer.rb +1 -1
  146. data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/incompatibility.rb +4 -4
  147. data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/package.rb +1 -1
  148. data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/partial_solution.rb +1 -1
  149. data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/rubygems.rb +3 -3
  150. data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/solve_failure.rb +1 -1
  151. data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/static_package_source.rb +3 -3
  152. data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/strategy.rb +2 -2
  153. data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/term.rb +1 -1
  154. data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/version.rb +1 -1
  155. data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/version_constraint.rb +3 -3
  156. data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/version_range.rb +1 -1
  157. data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/version_solver.rb +2 -2
  158. data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/version_union.rb +1 -1
  159. data/lib/rubygems/vendor/pub_grub/lib/pub_grub.rb +57 -0
  160. data/lib/{bundler → rubygems}/vendor/securerandom/lib/securerandom.rb +10 -6
  161. data/lib/{bundler → rubygems}/vendor/uri/lib/uri/common.rb +119 -119
  162. data/lib/{bundler → rubygems}/vendor/uri/lib/uri/file.rb +13 -13
  163. data/lib/{bundler → rubygems}/vendor/uri/lib/uri/ftp.rb +24 -24
  164. data/lib/{bundler → rubygems}/vendor/uri/lib/uri/generic.rb +132 -132
  165. data/lib/{bundler → rubygems}/vendor/uri/lib/uri/http.rb +18 -18
  166. data/lib/{bundler → rubygems}/vendor/uri/lib/uri/https.rb +4 -4
  167. data/lib/{bundler → rubygems}/vendor/uri/lib/uri/ldap.rb +14 -14
  168. data/lib/{bundler → rubygems}/vendor/uri/lib/uri/ldaps.rb +4 -4
  169. data/lib/{bundler → rubygems}/vendor/uri/lib/uri/mailto.rb +21 -21
  170. data/lib/{bundler → rubygems}/vendor/uri/lib/uri/rfc2396_parser.rb +39 -39
  171. data/lib/{bundler → rubygems}/vendor/uri/lib/uri/rfc3986_parser.rb +14 -14
  172. data/lib/{bundler → rubygems}/vendor/uri/lib/uri/version.rb +1 -1
  173. data/lib/{bundler → rubygems}/vendor/uri/lib/uri/ws.rb +12 -12
  174. data/lib/{bundler → rubygems}/vendor/uri/lib/uri/wss.rb +4 -4
  175. data/lib/{bundler → rubygems}/vendor/uri/lib/uri.rb +35 -31
  176. data/lib/rubygems/yaml_serializer.rb +880 -0
  177. metadata +391 -381
  178. data/CHANGELOG.md +0 -5801
  179. data/LICENSE.md +0 -22
  180. data/README.md +0 -58
  181. data/lib/bundler/compact_index_client/cache.rb +0 -107
  182. data/lib/bundler/compact_index_client/cache_file.rb +0 -148
  183. data/lib/bundler/compact_index_client/parser.rb +0 -87
  184. data/lib/bundler/compact_index_client/updater.rb +0 -105
  185. data/lib/bundler/compact_index_client.rb +0 -92
  186. data/lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb +0 -227
  187. data/lib/bundler/vendor/connection_pool/lib/connection_pool/version.rb +0 -3
  188. data/lib/bundler/vendor/connection_pool/lib/connection_pool/wrapper.rb +0 -56
  189. data/lib/bundler/vendor/connection_pool/lib/connection_pool.rb +0 -230
  190. data/lib/bundler/vendor/net-http-persistent/README.rdoc +0 -82
  191. data/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/connection.rb +0 -41
  192. data/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/pool.rb +0 -65
  193. data/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/timed_stack_multi.rb +0 -80
  194. data/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb +0 -1153
  195. data/lib/bundler/vendor/pub_grub/lib/pub_grub.rb +0 -31
  196. data/lib/bundler/vendored_persistent.rb +0 -11
  197. data/lib/bundler/yaml_serializer.rb +0 -98
  198. /data/lib/{bundler → rubygems}/vendor/pub_grub/LICENSE.txt +0 -0
  199. /data/lib/{bundler → rubygems}/vendor/securerandom/COPYING +0 -0
  200. /data/lib/{bundler → rubygems}/vendor/uri/COPYING +0 -0
@@ -70,7 +70,10 @@ module Bundler
70
70
 
71
71
  @cached_dependencies = Hash.new do |dependencies, package|
72
72
  dependencies[package] = Hash.new do |versions, version|
73
- versions[version] = to_dependency_hash(version.dependencies.reject {|d| d.name == package.name }, @packages)
73
+ deps = version.dependencies.reject {|d| d.name == package.name }
74
+ deps = Override.rewrite_dependencies(@base.overrides, package.name, deps)
75
+ deps = apply_metadata_overrides(deps, package.name)
76
+ versions[version] = to_dependency_hash(deps, @packages)
74
77
  end
75
78
  end
76
79
 
@@ -83,13 +86,15 @@ module Bundler
83
86
  end
84
87
 
85
88
  def solve_versions(root:, logger:)
86
- solver = PubGrub::VersionSolver.new(source: self, root: root, strategy: Strategy.new(self), logger: logger)
89
+ solver = Gem::PubGrub::VersionSolver.new(source: self, root: root, strategy: Strategy.new(self), logger: logger)
87
90
  result = solver.solve
88
91
  resolved_specs = result.flat_map {|package, version| version.to_specs(package, @most_specific_locked_platform) }
92
+ check_replaced_gems(resolved_specs)
93
+ Override.attach(resolved_specs, @base.overrides)
89
94
  spec_set = SpecSet.new(resolved_specs).specs_with_additional_variants_from(@base.locked_specs)
90
95
  @cooldown_skipped = cooldown_skipped_summary(spec_set)
91
96
  spec_set
92
- rescue PubGrub::SolveFailure => e
97
+ rescue Gem::PubGrub::SolveFailure => e
93
98
  incompatibility = e.incompatibility
94
99
 
95
100
  names_to_unlock, names_to_allow_prereleases_for, names_to_allow_remote_specs_for, extended_explanation = find_names_to_relax(incompatibility)
@@ -128,9 +133,47 @@ module Bundler
128
133
  explanation << extended_explanation
129
134
  end
130
135
 
136
+ override_summary = override_diagnostic_summary
137
+ explanation << override_summary if override_summary
138
+
131
139
  raise SolveFailure.new(explanation)
132
140
  end
133
141
 
142
+ # A replacement is only useful when it provides the files of the gem it
143
+ # replaces, so the two cannot be loaded side by side.
144
+ def check_replaced_gems(specs)
145
+ names = specs.map(&:name)
146
+
147
+ @base.overrides.each do |override|
148
+ next unless override.from && override.operation
149
+ next unless names.include?(override.target) && names.include?(override.operation)
150
+ next unless specs.any? {|s| s.name == override.from && s.dependencies.any? {|d| d.name == override.target } }
151
+
152
+ dependents = specs.select do |spec|
153
+ Override.rewrite_dependencies(@base.overrides, spec.name, spec.dependencies).any? {|d| d.name == override.target }
154
+ end.map(&:name).uniq
155
+
156
+ lines = ["#{override} would leave both #{override.target} and #{override.operation} in the bundle because #{override.target} is still required by:"]
157
+ lines << " the Gemfile" if @base.requirements.any? {|d| d.name == override.target }
158
+ lines.concat(dependents.map {|name| " #{name}" })
159
+ if dependents.any?
160
+ lines << "Replace it for each of them, for example:"
161
+ lines << " #{Override.new(override.target, :to, override.operation, from: dependents.first)}"
162
+ end
163
+ raise GemfileError, lines.join("\n")
164
+ end
165
+ end
166
+
167
+ def override_diagnostic_summary
168
+ return nil if @base.overrides.empty?
169
+
170
+ lines = ["Bundler applied the following overrides while resolving:"]
171
+ @base.overrides.each do |override|
172
+ lines << " #{override}"
173
+ end
174
+ "\n\n#{lines.join("\n")}"
175
+ end
176
+
134
177
  def find_names_to_relax(incompatibility)
135
178
  names_to_unlock = []
136
179
  names_to_allow_prereleases_for = []
@@ -153,7 +196,7 @@ module Bundler
153
196
  names_to_allow_remote_specs_for << name
154
197
  end
155
198
 
156
- no_versions_incompat = [cause.incompatibility, cause.satisfier].find {|incompat| incompat.cause.is_a?(PubGrub::Incompatibility::NoVersions) }
199
+ no_versions_incompat = [cause.incompatibility, cause.satisfier].find {|incompat| incompat.cause.is_a?(Gem::PubGrub::Incompatibility::NoVersions) }
157
200
  next unless no_versions_incompat
158
201
 
159
202
  extended_explanation = no_versions_incompat.extended_explanation
@@ -165,12 +208,12 @@ module Bundler
165
208
 
166
209
  def parse_dependency(package, dependency)
167
210
  range = if repository_for(package).is_a?(Source::Gemspec)
168
- PubGrub::VersionRange.any
211
+ Gem::PubGrub::VersionRange.any
169
212
  else
170
213
  requirement_to_range(dependency)
171
214
  end
172
215
 
173
- PubGrub::VersionConstraint.new(package, range: range)
216
+ Gem::PubGrub::VersionConstraint.new(package, range: range)
174
217
  end
175
218
 
176
219
  def versions_for(package, range = VersionRange.any)
@@ -178,7 +221,7 @@ module Bundler
178
221
  end
179
222
 
180
223
  def no_versions_incompatibility_for(package, unsatisfied_term)
181
- cause = PubGrub::Incompatibility::NoVersions.new(unsatisfied_term)
224
+ cause = Gem::PubGrub::Incompatibility::NoVersions.new(unsatisfied_term)
182
225
  name = package.name
183
226
  constraint = unsatisfied_term.constraint
184
227
  constraint_string = constraint.constraint_string
@@ -239,24 +282,24 @@ module Bundler
239
282
  sorted_versions[high]
240
283
  end
241
284
 
242
- range = PubGrub::VersionRange.new(min: low, max: high, include_min: !low.nil?)
285
+ range = Gem::PubGrub::VersionRange.new(min: low, max: high, include_min: !low.nil?)
243
286
 
244
- self_constraint = PubGrub::VersionConstraint.new(package, range: range)
287
+ self_constraint = Gem::PubGrub::VersionConstraint.new(package, range: range)
245
288
 
246
- dep_term = PubGrub::Term.new(dep_constraint, false)
247
- self_term = PubGrub::Term.new(self_constraint, true)
289
+ dep_term = Gem::PubGrub::Term.new(dep_constraint, false)
290
+ self_term = Gem::PubGrub::Term.new(self_constraint, true)
248
291
 
249
292
  custom_explanation = if dep_package.meta? && package.root?
250
293
  "current #{dep_package} version is #{dep_constraint.constraint_string}"
251
294
  end
252
295
 
253
- PubGrub::Incompatibility.new([self_term, dep_term], cause: :dependency, custom_explanation: custom_explanation)
296
+ Gem::PubGrub::Incompatibility.new([self_term, dep_term], cause: :dependency, custom_explanation: custom_explanation)
254
297
  end
255
298
  end
256
299
 
257
300
  def all_versions_for(package)
258
301
  name = package.name
259
- results = (@base[name] + filter_specs(@all_specs[name], package)).uniq {|spec| [spec.version.hash, spec.platform] }
302
+ results = (@base[name] + filter_specs(@all_specs[name], package)).uniq {|spec| [spec.version.hash, spec.platform, spec.content_address] }
260
303
 
261
304
  if name == "bundler" && !bundler_pinned_to_current_version?
262
305
  bundler_spec = Gem.loaded_specs["bundler"]
@@ -294,11 +337,15 @@ module Bundler
294
337
  next groups if package.force_ruby_platform?
295
338
  end
296
339
 
297
- platform_group = Resolver::SpecGroup.new(platform_specs.flatten.uniq)
340
+ platform_specs = platform_specs.flatten.uniq
341
+ platform_group = Resolver::SpecGroup.new((platform_specs + ruby_specs).uniq)
298
342
  next groups if platform_group == ruby_group
299
343
 
300
344
  groups << Resolver::Candidate.new(version, group: platform_group, priority: 1)
301
345
 
346
+ platform_only_group = Resolver::SpecGroup.new(platform_specs)
347
+ groups << Resolver::Candidate.new(version, group: platform_only_group, priority: 0) unless platform_only_group == platform_group
348
+
302
349
  groups
303
350
  end
304
351
  end
@@ -446,9 +493,9 @@ module Bundler
446
493
  def cooldown_excluded?(spec)
447
494
  return false unless spec.respond_to?(:created_at) && spec.created_at
448
495
  return false unless spec.respond_to?(:remote) && spec.remote
449
- return false if locked_by_lockfile?(spec)
450
496
  days = spec.remote.effective_cooldown
451
497
  return false if days.nil? || days <= 0
498
+ return false if locked_by_lockfile?(spec)
452
499
  (cooldown_now - spec.created_at) < (days * 86_400)
453
500
  end
454
501
 
@@ -602,19 +649,19 @@ module Bundler
602
649
  when "~>"
603
650
  name = "~> #{ver}"
604
651
  bump = Resolver::Candidate.new(version.bump.to_s + ".A")
605
- PubGrub::VersionRange.new(name: name, min: ver, max: bump, include_min: true)
652
+ Gem::PubGrub::VersionRange.new(name: name, min: ver, max: bump, include_min: true)
606
653
  when ">"
607
- PubGrub::VersionRange.new(min: platform_ver)
654
+ Gem::PubGrub::VersionRange.new(min: platform_ver)
608
655
  when ">="
609
- PubGrub::VersionRange.new(min: ver, include_min: true)
656
+ Gem::PubGrub::VersionRange.new(min: ver, include_min: true)
610
657
  when "<"
611
- PubGrub::VersionRange.new(max: ver)
658
+ Gem::PubGrub::VersionRange.new(max: ver)
612
659
  when "<="
613
- PubGrub::VersionRange.new(max: platform_ver, include_max: true)
660
+ Gem::PubGrub::VersionRange.new(max: platform_ver, include_max: true)
614
661
  when "="
615
- PubGrub::VersionRange.new(min: ver, max: platform_ver, include_min: true, include_max: true)
662
+ Gem::PubGrub::VersionRange.new(min: ver, max: platform_ver, include_min: true, include_max: true)
616
663
  when "!="
617
- PubGrub::VersionRange.new(min: ver, max: platform_ver, include_min: true, include_max: true).invert
664
+ Gem::PubGrub::VersionRange.new(min: ver, max: platform_ver, include_min: true, include_max: true).invert
618
665
  else
619
666
  raise "bad version specifier: #{op}"
620
667
  end
@@ -624,7 +671,7 @@ module Bundler
624
671
  end
625
672
 
626
673
  def to_dependency_hash(dependencies, packages)
627
- dependencies.inject({}) do |deps, dep|
674
+ apply_overrides(dependencies).inject({}) do |deps, dep|
628
675
  package = packages[dep.name]
629
676
 
630
677
  current_req = deps[package]
@@ -640,6 +687,33 @@ module Bundler
640
687
  end
641
688
  end
642
689
 
690
+ def apply_overrides(dependencies)
691
+ return dependencies if @base.overrides.empty?
692
+
693
+ dependencies.map do |dep|
694
+ override = Override.find_for(@base.overrides, dep.name, :version)
695
+ next dep unless override
696
+ Gem::Dependency.new(dep.name, override.apply_to(dep.requirement))
697
+ end
698
+ end
699
+
700
+ METADATA_DEP_FIELD = {
701
+ "Ruby\0" => :required_ruby_version,
702
+ "RubyGems\0" => :required_rubygems_version,
703
+ }.freeze
704
+
705
+ def apply_metadata_overrides(dependencies, name)
706
+ return dependencies if @base.overrides.empty?
707
+
708
+ dependencies.map do |dep|
709
+ field = METADATA_DEP_FIELD[dep.name]
710
+ next dep unless field
711
+ override = Override.find_for(@base.overrides, name, field)
712
+ next dep unless override
713
+ Gem::Dependency.new(dep.name, override.apply_to(dep.requirement))
714
+ end
715
+ end
716
+
643
717
  def bundler_not_found_message(conflict_dependencies)
644
718
  candidate_specs = filter_matching_specs(default_bundler_source.specs.search("bundler"), conflict_dependencies)
645
719
 
@@ -96,8 +96,6 @@ module Bundler
96
96
  [:version, versions_string(versions), versions_string(other.versions)]
97
97
  elsif @input_engine && !matches?(engine_versions, other.engine_gem_version)
98
98
  [:engine_version, versions_string(engine_versions), versions_string(other.engine_versions)]
99
- elsif patchlevel && (!patchlevel.is_a?(String) || !other.patchlevel.is_a?(String) || !matches?(patchlevel, other.patchlevel))
100
- [:patchlevel, patchlevel, other.patchlevel]
101
99
  end
102
100
  end
103
101
 
@@ -13,7 +13,53 @@ require "rubygems" unless defined?(Gem)
13
13
  # `Gem::Source` from the redefined `Gem::Specification#source`.
14
14
  require "rubygems/source"
15
15
 
16
+ # Can be removed once RubyGems 4.0.0 support is dropped
17
+ unless Gem::BasicSpecification.method_defined?(:content_address)
18
+ Gem::BasicSpecification.attr_accessor :content_address
19
+ end
20
+
21
+ # Can be removed once RubyGems 4.0.0 support is dropped
22
+ unless Gem::NameTuple.method_defined?(:content_address)
23
+ Gem::NameTuple.attr_reader :content_address
24
+ end
25
+
16
26
  module Gem
27
+ # Can be removed once RubyGems 4.0.0 support is dropped
28
+ unless defined?(Gem::ContentAddress)
29
+ module ContentAddress
30
+ def self.match?(token)
31
+ false
32
+ end
33
+
34
+ def self.eligible?(spec, validate_ruby_abi: true)
35
+ false
36
+ end
37
+
38
+ def self.content_addressed?(spec, validate_ruby_abi: true)
39
+ false
40
+ end
41
+
42
+ def self.content_addressed_row?(suffix, platform, required_ruby_version = nil, validate_ruby_abi: true)
43
+ false
44
+ end
45
+ end
46
+ end
47
+
48
+ # Can be removed once RubyGems 4.0.0 support is dropped
49
+ class SpecificationRecord
50
+ unless respond_to?(:specification_dir_for)
51
+ def self.specification_dir_for(spec, base_dir)
52
+ File.join(base_dir, "specifications")
53
+ end
54
+ end
55
+
56
+ unless respond_to?(:dirs_from)
57
+ def self.dirs_from(paths)
58
+ paths.map {|path| File.join(path, "specifications") }
59
+ end
60
+ end
61
+ end
62
+
17
63
  # Can be removed once RubyGems 3.5.11 support is dropped
18
64
  unless Gem.respond_to?(:freebsd_platform?)
19
65
  def self.freebsd_platform?
@@ -235,6 +281,20 @@ module Gem
235
281
  end
236
282
  end
237
283
 
284
+ alias_method :rg_build_info_dir, :build_info_dir
285
+ def build_info_dir
286
+ # A git checkout's build logs belong with that checkout's extension build.
287
+ # base_dir points at the directory holding every checkout, so logs keyed by
288
+ # full_name would collide between revisions of the same gem and would sit
289
+ # outside anything `bundle clean` prunes. extension_dir is unique per
290
+ # revision and goes away with the checkout.
291
+ if source.respond_to?(:extension_dir_name)
292
+ extension_dir
293
+ else
294
+ rg_build_info_dir
295
+ end
296
+ end
297
+
238
298
  # Can be removed once RubyGems 3.5.21 support is dropped
239
299
  remove_method :gem_dir if method_defined?(:gem_dir, false)
240
300
 
@@ -417,7 +477,8 @@ module Gem
417
477
  unless Gem::NameTuple.new("a", Gem::Version.new("1"), Gem::Platform.new("x86_64-linux")).platform.is_a?(String)
418
478
  alias_method :initialize_with_platform, :initialize
419
479
 
420
- def initialize(name, version, platform = Gem::Platform::RUBY)
480
+ def initialize(name, version, platform = Gem::Platform::RUBY, content_address = nil)
481
+ @content_address = content_address
421
482
  if Gem::Platform === platform
422
483
  initialize_with_platform(name, version, platform.to_s)
423
484
  else
@@ -426,6 +487,15 @@ module Gem
426
487
  end
427
488
  end
428
489
 
490
+ unless instance_method(:initialize).parameters.any? {|kind, name| kind == :key && name == :content_address }
491
+ alias_method :initialize_without_content_address, :initialize
492
+
493
+ def initialize(name, version, platform = Gem::Platform::RUBY, content_address: nil)
494
+ initialize_without_content_address(name, version, platform)
495
+ @content_address = content_address
496
+ end
497
+ end
498
+
429
499
  def lock_name
430
500
  if platform == Gem::Platform::RUBY
431
501
  "#{name} (#{version})"
@@ -4,6 +4,11 @@ require "rubygems/installer"
4
4
 
5
5
  module Bundler
6
6
  class RubyGemsGemInstaller < Gem::Installer
7
+ # Can be removed once RubyGems 4.0.0 support is dropped
8
+ unless private_method_defined?(:assign_content_address)
9
+ private def assign_content_address; end
10
+ end
11
+
7
12
  # Cap how many jobserver slots a single gem's `make` may grab so that one
8
13
  # gem with many recipes doesn't starve the others sharing the pool. Beyond
9
14
  # a handful of jobs the extra parallelism rarely pays off in practice.
@@ -14,6 +19,8 @@ module Bundler
14
19
  end
15
20
 
16
21
  def install
22
+ assign_content_address
23
+
17
24
  pre_install_checks
18
25
 
19
26
  run_pre_install_hooks
@@ -32,7 +39,11 @@ module Bundler
32
39
  extract_files
33
40
  end
34
41
 
35
- build_extensions if spec.extensions.any?
42
+ if options[:build_extension] == false
43
+ warn_skipped_extensions
44
+ elsif spec.extensions.any?
45
+ build_extensions
46
+ end
36
47
  write_build_info_file
37
48
  run_post_build_hooks
38
49
 
@@ -40,7 +51,12 @@ module Bundler
40
51
  generate_bin
41
52
  end
42
53
 
43
- generate_plugins
54
+ if options[:install_plugin] == false
55
+ remove_stale_plugins
56
+ warn_skipped_plugins
57
+ else
58
+ generate_plugins
59
+ end
44
60
 
45
61
  write_spec
46
62
 
@@ -85,6 +101,29 @@ module Bundler
85
101
  end
86
102
  end
87
103
 
104
+ # Reimplemented from RubyGems, since RubyGems older than 4.1 doesn't
105
+ # provide it
106
+ def remove_stale_plugins
107
+ return unless spec.plugins.empty?
108
+
109
+ ensure_writable_dir @plugins_dir
110
+ remove_plugins_for(spec, @plugins_dir)
111
+ end
112
+
113
+ def warn_skipped_extensions
114
+ return if spec.extensions.empty?
115
+
116
+ Bundler.ui.warn "#{spec.full_name} contains native extensions that were not built.\n" \
117
+ "To build extensions, unset no_build_extension and run `bundle pristine #{spec.name}`."
118
+ end
119
+
120
+ def warn_skipped_plugins
121
+ return if spec.plugins.empty?
122
+
123
+ Bundler.ui.warn "#{spec.full_name} contains plugins that were not installed.\n" \
124
+ "To install plugins, unset no_install_plugin and run `bundle pristine #{spec.name}`."
125
+ end
126
+
88
127
  if Bundler.rubygems.provides?("< 3.5.19")
89
128
  def generate_bin_script(filename, bindir)
90
129
  bin_script_path = File.join bindir, formatted_program_filename(filename)
@@ -111,7 +111,7 @@ module Bundler
111
111
 
112
112
  def spec_cache_dirs
113
113
  @spec_cache_dirs ||= begin
114
- dirs = gem_path.map {|dir| File.join(dir, "specifications") }
114
+ dirs = gem_path.flat_map {|dir| Gem::SpecificationRecord.dirs_from([dir]) }
115
115
  dirs << Gem.spec_cache_dir
116
116
  dirs.uniq.select {|dir| File.directory? dir }
117
117
  end
@@ -144,7 +144,12 @@ module Bundler
144
144
 
145
145
  def spec_from_gem(path)
146
146
  require "rubygems/package"
147
- Gem::Package.new(path).spec
147
+ package = Gem::Package.new(path)
148
+ spec = package.spec
149
+ if package.respond_to?(:content_address)
150
+ spec.content_address = package.content_address
151
+ end
152
+ spec
148
153
  end
149
154
 
150
155
  def build_gem(gem_dir, spec)
@@ -4,6 +4,8 @@ module Bundler
4
4
  class Runtime
5
5
  include SharedHelpers
6
6
 
7
+ PRUNE_CATEGORIES = [:cache, :git].freeze
8
+
7
9
  def initialize(root, definition)
8
10
  @root = root
9
11
  @definition = definition
@@ -146,7 +148,7 @@ module Bundler
146
148
  FileUtils.touch(File.expand_path("../.bundlecache", git_dir))
147
149
  end
148
150
 
149
- prune_cache(cache_path) unless Bundler.settings[:no_prune]
151
+ prune_cache(cache_path) unless Bundler.settings[:keep_outdated_cache]
150
152
  end
151
153
 
152
154
  def prune_cache(cache_path)
@@ -164,7 +166,9 @@ module Bundler
164
166
  git_cache_dirs = SharedHelpers.glob_files_in_dir("cache/bundler/git/*", Gem.dir)
165
167
  gem_dirs = SharedHelpers.glob_files_in_dir("gems/*", Gem.dir)
166
168
  gem_files = SharedHelpers.glob_files_in_dir("cache/*.gem", Gem.dir)
167
- gemspec_files = SharedHelpers.glob_files_in_dir("specifications/*.gemspec", Gem.dir)
169
+ gemspec_files = Gem::SpecificationRecord.dirs_from([Gem.dir]).flat_map do |dir|
170
+ SharedHelpers.glob_files_in_dir("*.gemspec", dir)
171
+ end
168
172
  extension_dirs = SharedHelpers.glob_files_in_dir("extensions/*/*/*", Gem.dir) + SharedHelpers.glob_files_in_dir("bundler/gems/extensions/*/*/*", Gem.dir)
169
173
  spec_gem_paths = []
170
174
  # need to keep git sources around
@@ -229,8 +233,71 @@ module Bundler
229
233
  output
230
234
  end
231
235
 
236
+ # Removes the artifacts Bundler keeps for its own bookkeeping and can rebuild
237
+ # from the lockfile. Gem contents are never touched.
238
+ def prune(categories)
239
+ categories = expand_prune_categories(categories)
240
+ return if categories.empty?
241
+
242
+ # Without a bundle path the cache is shared with RubyGems, so it holds gem
243
+ # files Bundler never put there.
244
+ if Bundler.use_system_gems?
245
+ Bundler.ui.warn "The `prune` setting was ignored because this bundle installs into the system gem " \
246
+ "directory, which Bundler shares with RubyGems. Run " \
247
+ "`bundle config set --local path vendor/bundle` to prune.", wrap: true
248
+ return
249
+ end
250
+
251
+ # Git metadata first, because resolving a checkout's install path can need
252
+ # the mirror that pruning the cache removes.
253
+ prune_git_metadata if categories.include?(:git)
254
+ prune_download_cache if categories.include?(:cache)
255
+ end
256
+
232
257
  private
233
258
 
259
+ # Anything that is not a category name is read as a boolean with Bundler's
260
+ # usual vocabulary, so `BUNDLE_PRUNE=1` selects every category and keeps
261
+ # doing so as categories are added. That way a tool can set the flag without
262
+ # tracking this list.
263
+ def expand_prune_categories(categories)
264
+ Array(categories).flat_map do |category|
265
+ name = category.to_s
266
+ next name.to_sym if PRUNE_CATEGORIES.include?(name.to_sym)
267
+
268
+ Settings.to_bool(name) ? PRUNE_CATEGORIES : []
269
+ end.uniq
270
+ end
271
+
272
+ def prune_download_cache
273
+ cache_path = File.join(Bundler.bundle_path, "cache")
274
+ return unless File.exist?(cache_path)
275
+
276
+ Bundler.ui.info "Removing the download cache at #{cache_path}"
277
+ SharedHelpers.filesystem_access(cache_path) do |p|
278
+ FileUtils.rm_rf(p)
279
+ end
280
+ end
281
+
282
+ def prune_git_metadata
283
+ owned = "#{Bundler.install_path}#{File::SEPARATOR}"
284
+ git_dirs = @definition.sources.git_sources.reject(&:local?).filter_map do |source|
285
+ install_path = source.install_path.to_s
286
+ next unless install_path.start_with?(owned)
287
+
288
+ git_dir = File.join(install_path, ".git")
289
+ git_dir if File.exist?(git_dir)
290
+ end
291
+ return if git_dirs.empty?
292
+
293
+ Bundler.ui.info "Removing git metadata from checked out git gems"
294
+ git_dirs.each do |git_dir|
295
+ SharedHelpers.filesystem_access(git_dir) do |p|
296
+ FileUtils.rm_rf(p)
297
+ end
298
+ end
299
+ end
300
+
234
301
  def prune_gem_cache(resolve, cache_path)
235
302
  cached = SharedHelpers.glob_files_in_dir("*.gem", cache_path.to_s)
236
303