bundler 2.5.5 → 2.5.16

Sign up to get free protection for your applications and to get access to all the features.
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