bundler 2.5.5 → 2.5.16

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 (107) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +171 -0
  3. data/lib/bundler/build_metadata.rb +2 -2
  4. data/lib/bundler/cli/binstubs.rb +1 -1
  5. data/lib/bundler/cli/fund.rb +1 -1
  6. data/lib/bundler/cli/gem.rb +8 -15
  7. data/lib/bundler/cli/install.rb +1 -1
  8. data/lib/bundler/cli/lock.rb +5 -4
  9. data/lib/bundler/cli/plugin.rb +3 -2
  10. data/lib/bundler/cli.rb +14 -31
  11. data/lib/bundler/compact_index_client/cache.rb +47 -72
  12. data/lib/bundler/compact_index_client/parser.rb +84 -0
  13. data/lib/bundler/compact_index_client.rb +51 -80
  14. data/lib/bundler/constants.rb +8 -1
  15. data/lib/bundler/definition.rb +168 -99
  16. data/lib/bundler/dependency.rb +2 -1
  17. data/lib/bundler/dsl.rb +16 -1
  18. data/lib/bundler/endpoint_specification.rb +11 -0
  19. data/lib/bundler/env.rb +1 -1
  20. data/lib/bundler/environment_preserver.rb +5 -23
  21. data/lib/bundler/errors.rb +14 -0
  22. data/lib/bundler/fetcher/compact_index.rb +15 -24
  23. data/lib/bundler/fetcher/downloader.rb +1 -1
  24. data/lib/bundler/fetcher.rb +2 -2
  25. data/lib/bundler/gem_helper.rb +1 -1
  26. data/lib/bundler/gem_helpers.rb +14 -7
  27. data/lib/bundler/gem_version_promoter.rb +42 -38
  28. data/lib/bundler/injector.rb +4 -6
  29. data/lib/bundler/installer/gem_installer.rb +0 -1
  30. data/lib/bundler/installer/standalone.rb +0 -3
  31. data/lib/bundler/installer.rb +11 -13
  32. data/lib/bundler/lazy_specification.rb +1 -0
  33. data/lib/bundler/man/bundle-add.1 +1 -1
  34. data/lib/bundler/man/bundle-binstubs.1 +1 -1
  35. data/lib/bundler/man/bundle-cache.1 +1 -1
  36. data/lib/bundler/man/bundle-check.1 +3 -1
  37. data/lib/bundler/man/bundle-check.1.ronn +3 -0
  38. data/lib/bundler/man/bundle-clean.1 +1 -1
  39. data/lib/bundler/man/bundle-config.1 +2 -4
  40. data/lib/bundler/man/bundle-config.1.ronn +1 -4
  41. data/lib/bundler/man/bundle-console.1 +1 -1
  42. data/lib/bundler/man/bundle-doctor.1 +1 -1
  43. data/lib/bundler/man/bundle-exec.1 +1 -1
  44. data/lib/bundler/man/bundle-gem.1 +7 -1
  45. data/lib/bundler/man/bundle-gem.1.ronn +11 -0
  46. data/lib/bundler/man/bundle-help.1 +1 -1
  47. data/lib/bundler/man/bundle-info.1 +1 -1
  48. data/lib/bundler/man/bundle-init.1 +1 -1
  49. data/lib/bundler/man/bundle-inject.1 +1 -1
  50. data/lib/bundler/man/bundle-install.1 +3 -3
  51. data/lib/bundler/man/bundle-install.1.ronn +2 -2
  52. data/lib/bundler/man/bundle-list.1 +1 -1
  53. data/lib/bundler/man/bundle-lock.1 +1 -1
  54. data/lib/bundler/man/bundle-open.1 +1 -1
  55. data/lib/bundler/man/bundle-outdated.1 +1 -1
  56. data/lib/bundler/man/bundle-platform.1 +1 -1
  57. data/lib/bundler/man/bundle-plugin.1 +7 -4
  58. data/lib/bundler/man/bundle-plugin.1.ronn +7 -3
  59. data/lib/bundler/man/bundle-pristine.1 +1 -1
  60. data/lib/bundler/man/bundle-remove.1 +1 -1
  61. data/lib/bundler/man/bundle-show.1 +1 -1
  62. data/lib/bundler/man/bundle-update.1 +1 -1
  63. data/lib/bundler/man/bundle-version.1 +1 -1
  64. data/lib/bundler/man/bundle-viz.1 +1 -1
  65. data/lib/bundler/man/bundle.1 +1 -1
  66. data/lib/bundler/man/gemfile.5 +3 -3
  67. data/lib/bundler/man/gemfile.5.ronn +2 -2
  68. data/lib/bundler/mirror.rb +3 -3
  69. data/lib/bundler/plugin/api/source.rb +2 -2
  70. data/lib/bundler/plugin/installer/path.rb +18 -0
  71. data/lib/bundler/plugin/installer.rb +36 -16
  72. data/lib/bundler/plugin/source_list.rb +4 -4
  73. data/lib/bundler/resolver/base.rb +4 -0
  74. data/lib/bundler/resolver/candidate.rb +5 -17
  75. data/lib/bundler/resolver/package.rb +4 -0
  76. data/lib/bundler/resolver/spec_group.rb +20 -2
  77. data/lib/bundler/resolver.rb +72 -33
  78. data/lib/bundler/rubygems_ext.rb +98 -10
  79. data/lib/bundler/rubygems_gem_installer.rb +35 -2
  80. data/lib/bundler/rubygems_integration.rb +16 -2
  81. data/lib/bundler/runtime.rb +2 -2
  82. data/lib/bundler/self_manager.rb +22 -2
  83. data/lib/bundler/settings.rb +26 -20
  84. data/lib/bundler/setup.rb +6 -0
  85. data/lib/bundler/shared_helpers.rb +6 -4
  86. data/lib/bundler/source/git/git_proxy.rb +9 -1
  87. data/lib/bundler/source/git.rb +15 -1
  88. data/lib/bundler/source/metadata.rb +2 -0
  89. data/lib/bundler/source/path.rb +0 -13
  90. data/lib/bundler/source/rubygems/remote.rb +1 -1
  91. data/lib/bundler/source/rubygems.rb +33 -32
  92. data/lib/bundler/source_list.rb +26 -2
  93. data/lib/bundler/spec_set.rb +15 -13
  94. data/lib/bundler/stub_specification.rb +8 -0
  95. data/lib/bundler/templates/newgem/CODE_OF_CONDUCT.md.tt +77 -29
  96. data/lib/bundler/templates/newgem/newgem.gemspec.tt +4 -3
  97. data/lib/bundler/templates/newgem/rubocop.yml.tt +0 -5
  98. data/lib/bundler/uri_credentials_filter.rb +2 -2
  99. data/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb +22 -22
  100. data/lib/bundler/vendor/pub_grub/lib/pub_grub/static_package_source.rb +1 -0
  101. data/lib/bundler/vendored_net_http.rb +20 -5
  102. data/lib/bundler/vendored_timeout.rb +7 -3
  103. data/lib/bundler/vendored_uri.rb +18 -1
  104. data/lib/bundler/version.rb +1 -1
  105. data/lib/bundler/yaml_serializer.rb +11 -6
  106. data/lib/bundler.rb +29 -3
  107. metadata +5 -3
@@ -50,26 +50,26 @@ module Bundler
50
50
  specs[name] = matches.sort_by {|s| [s.version, s.platform.to_s] }
51
51
  end
52
52
 
53
+ @all_versions = Hash.new do |candidates, package|
54
+ candidates[package] = all_versions_for(package)
55
+ end
56
+
53
57
  @sorted_versions = Hash.new do |candidates, package|
54
- candidates[package] = if package.root?
55
- [root_version]
56
- else
57
- all_versions_for(package).sort
58
- end
58
+ candidates[package] = filtered_versions_for(package).sort
59
59
  end
60
60
 
61
+ @sorted_versions[root] = [root_version]
62
+
61
63
  root_dependencies = prepare_dependencies(@requirements, @packages)
62
64
 
63
65
  @cached_dependencies = Hash.new do |dependencies, package|
64
- dependencies[package] = if package.root?
65
- { root_version => root_dependencies }
66
- else
67
- Hash.new do |versions, version|
68
- versions[version] = to_dependency_hash(version.dependencies.reject {|d| d.name == package.name }, @packages)
69
- end
66
+ dependencies[package] = Hash.new do |versions, version|
67
+ versions[version] = to_dependency_hash(version.dependencies.reject {|d| d.name == package.name }, @packages)
70
68
  end
71
69
  end
72
70
 
71
+ @cached_dependencies[root] = { root_version => root_dependencies }
72
+
73
73
  logger = Bundler::UI::Shell.new
74
74
  logger.level = debug? ? "debug" : "warn"
75
75
 
@@ -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
 
@@ -156,9 +157,15 @@ module Bundler
156
157
  end
157
158
 
158
159
  def versions_for(package, range=VersionRange.any)
159
- versions = range.select_versions(@sorted_versions[package])
160
+ versions = select_sorted_versions(package, range)
160
161
 
161
- sort_versions(package, versions)
162
+ # Conditional avoids (among other things) calling
163
+ # sort_versions_by_preferred with the root package
164
+ if versions.size > 1
165
+ sort_versions_by_preferred(package, versions)
166
+ else
167
+ versions
168
+ end
162
169
  end
163
170
 
164
171
  def no_versions_incompatibility_for(package, unsatisfied_term)
@@ -247,8 +254,8 @@ module Bundler
247
254
  locked_requirement = base_requirements[name]
248
255
  results = filter_matching_specs(results, locked_requirement) if locked_requirement
249
256
 
250
- versions = results.group_by(&:version).reduce([]) do |groups, (version, specs)|
251
- platform_specs = package.platforms.map {|platform| select_best_platform_match(specs, platform) }
257
+ results.group_by(&:version).reduce([]) do |groups, (version, specs)|
258
+ platform_specs = package.platform_specs(specs)
252
259
 
253
260
  # If package is a top-level dependency,
254
261
  # candidate is only valid if there are matching versions for all resolution platforms.
@@ -263,19 +270,25 @@ module Bundler
263
270
  next groups if platform_specs.all?(&:empty?)
264
271
  end
265
272
 
266
- platform_specs.flatten!
267
-
268
273
  ruby_specs = select_best_platform_match(specs, Gem::Platform::RUBY)
269
- groups << Resolver::Candidate.new(version, specs: ruby_specs) if ruby_specs.any?
274
+ ruby_group = Resolver::SpecGroup.new(ruby_specs)
270
275
 
271
- next groups if platform_specs == ruby_specs || package.force_ruby_platform?
276
+ unless ruby_group.empty?
277
+ platform_specs.each do |specs|
278
+ ruby_group.merge(Resolver::SpecGroup.new(specs))
279
+ end
272
280
 
273
- groups << Resolver::Candidate.new(version, specs: platform_specs)
281
+ groups << Resolver::Candidate.new(version, group: ruby_group, priority: -1)
282
+ next groups if package.force_ruby_platform?
283
+ end
284
+
285
+ platform_group = Resolver::SpecGroup.new(platform_specs.flatten.uniq)
286
+ next groups if platform_group == ruby_group
287
+
288
+ groups << Resolver::Candidate.new(version, group: platform_group, priority: 1)
274
289
 
275
290
  groups
276
291
  end
277
-
278
- sort_versions(package, versions)
279
292
  end
280
293
 
281
294
  def source_for(name)
@@ -334,6 +347,21 @@ module Bundler
334
347
 
335
348
  private
336
349
 
350
+ def filtered_versions_for(package)
351
+ @gem_version_promoter.filter_versions(package, @all_versions[package])
352
+ end
353
+
354
+ def raise_all_versions_filtered_out!(package)
355
+ level = @gem_version_promoter.level
356
+ name = package.name
357
+ locked_version = package.locked_version
358
+ requirement = package.dependency
359
+
360
+ raise GemNotFound,
361
+ "#{name} is locked to #{locked_version}, while Gemfile is requesting #{requirement}. " \
362
+ "--strict --#{level} was specified, but there are no #{level} level upgrades from #{locked_version} satisfying #{requirement}, so version solving has failed"
363
+ end
364
+
337
365
  def filter_matching_specs(specs, requirements)
338
366
  Array(requirements).flat_map do |requirement|
339
367
  specs.select {| spec| requirement_satisfied_by?(requirement, spec) }
@@ -357,12 +385,8 @@ module Bundler
357
385
  requirement.satisfied_by?(spec.version) || spec.source.is_a?(Source::Gemspec)
358
386
  end
359
387
 
360
- def sort_versions(package, versions)
361
- if versions.size > 1
362
- @gem_version_promoter.sort_versions(package, versions).reverse
363
- else
364
- versions
365
- end
388
+ def sort_versions_by_preferred(package, versions)
389
+ @gem_version_promoter.sort_versions(package, versions)
366
390
  end
367
391
 
368
392
  def repository_for(package)
@@ -379,12 +403,19 @@ module Bundler
379
403
 
380
404
  next [dep_package, dep_constraint] if name == "bundler"
381
405
 
382
- versions = versions_for(dep_package, dep_constraint.range)
406
+ dep_range = dep_constraint.range
407
+ versions = select_sorted_versions(dep_package, dep_range)
383
408
  if versions.empty? && dep_package.ignores_prereleases?
409
+ @all_versions.delete(dep_package)
384
410
  @sorted_versions.delete(dep_package)
385
411
  dep_package.consider_prereleases!
386
- versions = versions_for(dep_package, dep_constraint.range)
412
+ versions = select_sorted_versions(dep_package, dep_range)
413
+ end
414
+
415
+ if versions.empty? && select_all_versions(dep_package, dep_range).any?
416
+ raise_all_versions_filtered_out!(dep_package)
387
417
  end
418
+
388
419
  next [dep_package, dep_constraint] unless versions.empty?
389
420
 
390
421
  next unless dep_package.current_platform?
@@ -393,6 +424,14 @@ module Bundler
393
424
  end.compact.to_h
394
425
  end
395
426
 
427
+ def select_sorted_versions(package, range)
428
+ range.select_versions(@sorted_versions[package])
429
+ end
430
+
431
+ def select_all_versions(package, range)
432
+ range.select_versions(@all_versions[package])
433
+ end
434
+
396
435
  def other_specs_matching_message(specs, requirement)
397
436
  message = String.new("The source contains the following gems matching '#{requirement}':\n")
398
437
  message << specs.map {|s| " * #{s.full_name}" }.join("\n")
@@ -401,8 +440,8 @@ module Bundler
401
440
 
402
441
  def requirement_to_range(requirement)
403
442
  ranges = requirement.requirements.map do |(op, version)|
404
- ver = Resolver::Candidate.new(version).generic!
405
- 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)
406
445
 
407
446
  case op
408
447
  when "~>"
@@ -1,11 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "pathname"
4
-
5
3
  require "rubygems" unless defined?(Gem)
6
4
 
7
- require "rubygems/specification"
8
-
9
5
  # We can't let `Gem::Source` be autoloaded in the `Gem::Specification#source`
10
6
  # redefinition below, so we need to load it upfront. The reason is that if
11
7
  # Bundler monkeypatches are loaded before RubyGems activates an executable (for
@@ -17,10 +13,6 @@ require "rubygems/specification"
17
13
  # `Gem::Source` from the redefined `Gem::Specification#source`.
18
14
  require "rubygems/source"
19
15
 
20
- require_relative "match_metadata"
21
- require_relative "force_platform"
22
- require_relative "match_platform"
23
-
24
16
  # Cherry-pick fixes to `Gem.ruby_version` to be useful for modern Bundler
25
17
  # versions and ignore patchlevels
26
18
  # (https://github.com/rubygems/rubygems/pull/5472,
@@ -31,7 +23,52 @@ unless Gem.ruby_version.to_s == RUBY_VERSION || RUBY_PATCHLEVEL == -1
31
23
  end
32
24
 
33
25
  module Gem
26
+ # Can be removed once RubyGems 3.5.11 support is dropped
27
+ unless Gem.respond_to?(:freebsd_platform?)
28
+ def self.freebsd_platform?
29
+ RbConfig::CONFIG["host_os"].to_s.include?("bsd")
30
+ end
31
+ end
32
+
33
+ # Can be removed once RubyGems 3.5.14 support is dropped
34
+ unless Gem.respond_to?(:open_file_with_flock)
35
+ def self.open_file_with_flock(path, &block)
36
+ flags = File.exist?(path) ? "r+" : "a+"
37
+
38
+ File.open(path, flags) do |io|
39
+ begin
40
+ io.flock(File::LOCK_EX)
41
+ rescue Errno::ENOSYS, Errno::ENOTSUP
42
+ end
43
+ yield io
44
+ rescue Errno::ENOLCK # NFS
45
+ if Thread.main != Thread.current
46
+ raise
47
+ else
48
+ File.open(path, flags, &block)
49
+ end
50
+ end
51
+ end
52
+ end
53
+
54
+ require "rubygems/specification"
55
+
56
+ # Can be removed once RubyGems 3.5.14 support is dropped
57
+ VALIDATES_FOR_RESOLUTION = Specification.new.respond_to?(:validate_for_resolution).freeze
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
+
34
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
+
69
+ require_relative "match_metadata"
70
+ require_relative "match_platform"
71
+
35
72
  include ::Bundler::MatchMetadata
36
73
  include ::Bundler::MatchPlatform
37
74
 
@@ -48,7 +85,7 @@ module Gem
48
85
 
49
86
  def full_gem_path
50
87
  if source.respond_to?(:root)
51
- Pathname.new(loaded_from).dirname.expand_path(source.root).to_s
88
+ File.expand_path(File.dirname(loaded_from), source.root)
52
89
  else
53
90
  rg_full_gem_path
54
91
  end
@@ -127,6 +164,33 @@ module Gem
127
164
  !default_gem? && !File.directory?(full_gem_path)
128
165
  end
129
166
 
167
+ unless VALIDATES_FOR_RESOLUTION
168
+ def validate_for_resolution
169
+ SpecificationPolicy.new(self).validate_for_resolution
170
+ end
171
+ end
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
+
130
194
  private
131
195
 
132
196
  def dependencies_to_gemfile(dependencies, group = nil)
@@ -146,7 +210,31 @@ module Gem
146
210
  end
147
211
  end
148
212
 
213
+ unless VALIDATES_FOR_RESOLUTION
214
+ class SpecificationPolicy
215
+ def validate_for_resolution
216
+ validate_required!
217
+ end
218
+ end
219
+ end
220
+
221
+ module BetterPermissionError
222
+ def data
223
+ super
224
+ rescue Errno::EACCES
225
+ raise Bundler::PermissionError.new(loaded_from, :read)
226
+ end
227
+ end
228
+
229
+ require "rubygems/stub_specification"
230
+
231
+ class StubSpecification
232
+ prepend BetterPermissionError
233
+ end
234
+
149
235
  class Dependency
236
+ require_relative "force_platform"
237
+
150
238
  include ::Bundler::ForcePlatform
151
239
 
152
240
  attr_accessor :source, :groups
@@ -221,7 +309,7 @@ module Gem
221
309
 
222
310
  # cpu
223
311
  ([nil,"universal"].include?(@cpu) || [nil, "universal"].include?(other.cpu) || @cpu == other.cpu ||
224
- (@cpu == "arm" && other.cpu.start_with?("arm"))) &&
312
+ (@cpu == "arm" && other.cpu.start_with?("armv"))) &&
225
313
 
226
314
  # os
227
315
  @os == other.os &&
@@ -29,7 +29,10 @@ module Bundler
29
29
  write_build_info_file
30
30
  run_post_build_hooks
31
31
 
32
- generate_bin
32
+ SharedHelpers.filesystem_access(bin_dir, :write) do
33
+ generate_bin
34
+ end
35
+
33
36
  generate_plugins
34
37
 
35
38
  write_spec
@@ -45,7 +48,17 @@ module Bundler
45
48
  spec
46
49
  end
47
50
 
48
- def pre_install_checks
51
+ if Bundler.rubygems.provides?("< 3.5")
52
+ def pre_install_checks
53
+ super
54
+ rescue Gem::FilePermissionError
55
+ # Ignore permission checks in RubyGems. Instead, go on, and try to write
56
+ # for real. We properly handle permission errors when they happen.
57
+ nil
58
+ end
59
+ end
60
+
61
+ def ensure_writable_dir(dir)
49
62
  super
50
63
  rescue Gem::FilePermissionError
51
64
  # Ignore permission checks in RubyGems. Instead, go on, and try to write
@@ -68,6 +81,26 @@ module Bundler
68
81
  end
69
82
  end
70
83
 
84
+ if Bundler.rubygems.provides?("< 3.5.15")
85
+ def generate_bin_script(filename, bindir)
86
+ bin_script_path = File.join bindir, formatted_program_filename(filename)
87
+
88
+ Gem.open_file_with_flock("#{bin_script_path}.lock") do
89
+ require "fileutils"
90
+ FileUtils.rm_f bin_script_path # prior install may have been --no-wrappers
91
+
92
+ File.open(bin_script_path, "wb", 0o755) do |file|
93
+ file.write app_script_text(filename)
94
+ file.chmod(options[:prog_mode] || 0o755)
95
+ end
96
+ end
97
+
98
+ verbose bin_script_path
99
+
100
+ generate_windows_script filename, bindir
101
+ end
102
+ end
103
+
71
104
  def build_extensions
72
105
  extension_cache_path = options[:bundler_extension_cache_path]
73
106
  extension_dir = spec.extension_dir
@@ -48,7 +48,7 @@ module Bundler
48
48
  end
49
49
 
50
50
  def validate(spec)
51
- Bundler.ui.silence { spec.validate(false) }
51
+ Bundler.ui.silence { spec.validate_for_resolution }
52
52
  rescue Gem::InvalidSpecificationException => e
53
53
  error_message = "The gemspec at #{spec.loaded_from} is not valid. Please fix this gemspec.\n" \
54
54
  "The validation error was '#{e.message}'\n"
@@ -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
 
@@ -469,11 +469,25 @@ module Bundler
469
469
  end
470
470
 
471
471
  def all_specs
472
+ SharedHelpers.major_deprecation 2, "Bundler.rubygems.all_specs has been removed in favor of Bundler.rubygems.installed_specs"
473
+
472
474
  Gem::Specification.stubs.map do |stub|
473
475
  StubSpecification.from_stub(stub)
474
476
  end
475
477
  end
476
478
 
479
+ def installed_specs
480
+ Gem::Specification.stubs.reject(&:default_gem?).map do |stub|
481
+ StubSpecification.from_stub(stub)
482
+ end
483
+ end
484
+
485
+ def default_specs
486
+ Gem::Specification.default_stubs.map do |stub|
487
+ StubSpecification.from_stub(stub)
488
+ end
489
+ end
490
+
477
491
  def find_bundler(version)
478
492
  find_name("bundler").find {|s| s.version.to_s == version }
479
493
  end
@@ -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
@@ -95,7 +95,7 @@ module Bundler
95
95
 
96
96
  def lock(opts = {})
97
97
  return if @definition.no_resolve_needed?
98
- @definition.lock(Bundler.default_lockfile, opts[:preserve_unknown_sections])
98
+ @definition.lock(opts[:preserve_unknown_sections])
99
99
  end
100
100
 
101
101
  alias_method :gems, :specs
@@ -70,8 +70,23 @@ module Bundler
70
70
  configured_gem_home = ENV["GEM_HOME"]
71
71
  configured_gem_path = ENV["GEM_PATH"]
72
72
 
73
- cmd = [$PROGRAM_NAME, *ARGV]
74
- cmd.unshift(Gem.ruby) unless File.executable?($PROGRAM_NAME)
73
+ # Bundler specs need some stuff to be required before Bundler starts
74
+ # running, for example, for faking the compact index API. However, these
75
+ # flags are lost when we reexec to a different version of Bundler. In the
76
+ # future, we may be able to properly reconstruct the original Ruby
77
+ # invocation (see https://bugs.ruby-lang.org/issues/6648), but for now
78
+ # there's no way to do it, so we need to be explicit about how to re-exec.
79
+ # This may be a feature end users request at some point, but maybe by that
80
+ # time, we have builtin tools to do. So for now, we use an undocumented
81
+ # ENV variable only for our specs.
82
+ bundler_spec_original_cmd = ENV["BUNDLER_SPEC_ORIGINAL_CMD"]
83
+ if bundler_spec_original_cmd
84
+ require "shellwords"
85
+ cmd = [*Shellwords.shellsplit(bundler_spec_original_cmd), *ARGV]
86
+ else
87
+ cmd = [$PROGRAM_NAME, *ARGV]
88
+ cmd.unshift(Gem.ruby) unless File.executable?($PROGRAM_NAME)
89
+ end
75
90
 
76
91
  Bundler.with_original_env do
77
92
  Kernel.exec(
@@ -92,6 +107,7 @@ module Bundler
92
107
  def autoswitching_applies?
93
108
  ENV["BUNDLER_VERSION"].nil? &&
94
109
  Bundler.rubygems.supports_bundler_trampolining? &&
110
+ ruby_can_restart_with_same_arguments? &&
95
111
  SharedHelpers.in_bundle? &&
96
112
  lockfile_version
97
113
  end
@@ -151,6 +167,10 @@ module Bundler
151
167
  !version.to_s.end_with?(".dev")
152
168
  end
153
169
 
170
+ def ruby_can_restart_with_same_arguments?
171
+ $PROGRAM_NAME != "-e"
172
+ end
173
+
154
174
  def updating?
155
175
  "update".start_with?(ARGV.first || " ") && ARGV[1..-1].any? {|a| a.start_with?("--bundler") }
156
176
  end
@@ -7,7 +7,6 @@ module Bundler
7
7
  autoload :Validator, File.expand_path("settings/validator", __dir__)
8
8
 
9
9
  BOOL_KEYS = %w[
10
- allow_deployment_source_credential_changes
11
10
  allow_offline_install
12
11
  auto_clean_without_path
13
12
  auto_install
@@ -104,6 +103,7 @@ module Bundler
104
103
  def initialize(root = nil)
105
104
  @root = root
106
105
  @local_config = load_config(local_config_file)
106
+ @local_root = root || Pathname.new(".bundle").expand_path
107
107
 
108
108
  @env_config = ENV.to_h
109
109
  @env_config.select! {|key, _value| key.start_with?("BUNDLE_") }
@@ -143,7 +143,7 @@ module Bundler
143
143
  end
144
144
 
145
145
  def set_local(key, value)
146
- local_config_file || raise(GemfileNotFound, "Could not locate Gemfile")
146
+ local_config_file = @local_root.join("config")
147
147
 
148
148
  set_key(key, value, @local_config, local_config_file)
149
149
  end
@@ -189,7 +189,7 @@ module Bundler
189
189
  def mirror_for(uri)
190
190
  if uri.is_a?(String)
191
191
  require_relative "vendored_uri"
192
- uri = Bundler::URI(uri)
192
+ uri = Gem::URI(uri)
193
193
  end
194
194
 
195
195
  gem_mirrors.for(uri.to_s).uri
@@ -492,16 +492,23 @@ module Bundler
492
492
  valid_file = file.exist? && !file.size.zero?
493
493
  return {} unless valid_file
494
494
  serializer_class.load(file.read).inject({}) do |config, (k, v)|
495
- if k.include?("-")
496
- Bundler.ui.warn "Your #{file} config includes `#{k}`, which contains the dash character (`-`).\n" \
497
- "This is deprecated, because configuration through `ENV` should be possible, but `ENV` keys cannot include dashes.\n" \
498
- "Please edit #{file} and replace any dashes in configuration keys with a triple underscore (`___`)."
495
+ k = k.dup
496
+ k << "/" if /https?:/i.match?(k) && !k.end_with?("/", "__#{FALLBACK_TIMEOUT_URI_OPTION.upcase}")
497
+ k.gsub!(".", "__")
499
498
 
500
- # string hash keys are frozen
501
- k = k.gsub("-", "___")
499
+ unless k.start_with?("#")
500
+ if k.include?("-")
501
+ Bundler.ui.warn "Your #{file} config includes `#{k}`, which contains the dash character (`-`).\n" \
502
+ "This is deprecated, because configuration through `ENV` should be possible, but `ENV` keys cannot include dashes.\n" \
503
+ "Please edit #{file} and replace any dashes in configuration keys with a triple underscore (`___`)."
504
+
505
+ # string hash keys are frozen
506
+ k = k.gsub("-", "___")
507
+ end
508
+
509
+ config[k] = v
502
510
  end
503
511
 
504
- config[k] = v
505
512
  config
506
513
  end
507
514
  end
@@ -516,26 +523,25 @@ module Bundler
516
523
  YAMLSerializer
517
524
  end
518
525
 
519
- PER_URI_OPTIONS = %w[
520
- fallback_timeout
521
- ].freeze
526
+ FALLBACK_TIMEOUT_URI_OPTION = "fallback_timeout"
522
527
 
523
528
  NORMALIZE_URI_OPTIONS_PATTERN =
524
529
  /
525
530
  \A
526
531
  (\w+\.)? # optional prefix key
527
532
  (https?.*?) # URI
528
- (\.#{Regexp.union(PER_URI_OPTIONS)})? # optional suffix key
533
+ (\.#{FALLBACK_TIMEOUT_URI_OPTION})? # optional suffix key
529
534
  \z
530
535
  /ix
531
536
 
532
537
  def self.key_for(key)
533
- key = normalize_uri(key).to_s if key.is_a?(String) && key.start_with?("http", "mirror.http")
534
- key = key_to_s(key).gsub(".", "__")
538
+ key = key_to_s(key)
539
+ key = normalize_uri(key) if key.start_with?("http", "mirror.http")
540
+ key = key.gsub(".", "__")
535
541
  key.gsub!("-", "___")
536
542
  key.upcase!
537
543
 
538
- key.prepend("BUNDLE_")
544
+ key.gsub(/\A([ #]*)/, '\1BUNDLE_')
539
545
  end
540
546
 
541
547
  # TODO: duplicates Rubygems#normalize_uri
@@ -549,7 +555,7 @@ module Bundler
549
555
  end
550
556
  uri = URINormalizer.normalize_suffix(uri)
551
557
  require_relative "vendored_uri"
552
- uri = Bundler::URI(uri)
558
+ uri = Gem::URI(uri)
553
559
  unless uri.absolute?
554
560
  raise ArgumentError, format("Gem sources must be absolute. You provided '%s'.", uri)
555
561
  end
@@ -564,7 +570,7 @@ module Bundler
564
570
  key
565
571
  when Symbol
566
572
  key.name
567
- when Bundler::URI::HTTP
573
+ when Gem::URI::HTTP
568
574
  key.to_s
569
575
  else
570
576
  raise ArgumentError, "Invalid key: #{key.inspect}"
@@ -577,7 +583,7 @@ module Bundler
577
583
  key
578
584
  when Symbol
579
585
  key.to_s
580
- when Bundler::URI::HTTP
586
+ when Gem::URI::HTTP
581
587
  key.to_s
582
588
  else
583
589
  raise ArgumentError, "Invalid key: #{key.inspect}"
data/lib/bundler/setup.rb CHANGED
@@ -5,6 +5,12 @@ require_relative "shared_helpers"
5
5
  if Bundler::SharedHelpers.in_bundle?
6
6
  require_relative "../bundler"
7
7
 
8
+ # autoswitch to locked Bundler version if available
9
+ Bundler.auto_switch
10
+
11
+ # try to auto_install first before we get to the `Bundler.ui.silence`, so user knows what is happening
12
+ Bundler.auto_install
13
+
8
14
  if STDOUT.tty? || ENV["BUNDLER_FORCE_TTY"]
9
15
  begin
10
16
  Bundler.ui.silence { Bundler.setup }
@@ -1,14 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "pathname"
4
- require "rbconfig"
5
-
6
3
  require_relative "version"
7
- require_relative "constants"
8
4
  require_relative "rubygems_integration"
9
5
  require_relative "current_ruby"
10
6
 
7
+ autoload :Pathname, "pathname"
8
+
11
9
  module Bundler
10
+ autoload :WINDOWS, File.expand_path("constants", __dir__)
11
+ autoload :FREEBSD, File.expand_path("constants", __dir__)
12
+ autoload :NULL, File.expand_path("constants", __dir__)
13
+
12
14
  module SharedHelpers
13
15
  def root
14
16
  gemfile = find_gemfile