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
@@ -69,7 +69,6 @@ module Bundler
69
69
  @sources = sources
70
70
  @unlock = unlock
71
71
  @optional_groups = optional_groups
72
- @remote = false
73
72
  @prefer_local = false
74
73
  @specs = nil
75
74
  @ruby_version = ruby_version
@@ -82,7 +81,7 @@ module Bundler
82
81
  @resolved_bundler_version = nil
83
82
 
84
83
  @locked_ruby_version = nil
85
- @new_platform = nil
84
+ @new_platforms = []
86
85
  @removed_platform = nil
87
86
 
88
87
  if lockfile_exists?
@@ -92,11 +91,12 @@ module Bundler
92
91
  @platforms = @locked_platforms.dup
93
92
  @locked_bundler_version = @locked_gems.bundler_version
94
93
  @locked_ruby_version = @locked_gems.ruby_version
94
+ @originally_locked_deps = @locked_gems.dependencies
95
95
  @originally_locked_specs = SpecSet.new(@locked_gems.specs)
96
96
  @locked_checksums = @locked_gems.checksums
97
97
 
98
98
  if unlock != true
99
- @locked_deps = @locked_gems.dependencies
99
+ @locked_deps = @originally_locked_deps
100
100
  @locked_specs = @originally_locked_specs
101
101
  @locked_sources = @locked_gems.sources
102
102
  else
@@ -111,6 +111,7 @@ module Bundler
111
111
  @locked_gems = nil
112
112
  @locked_deps = {}
113
113
  @locked_specs = SpecSet.new([])
114
+ @originally_locked_deps = {}
114
115
  @originally_locked_specs = @locked_specs
115
116
  @locked_sources = []
116
117
  @locked_platforms = []
@@ -130,7 +131,7 @@ module Bundler
130
131
  @sources.merged_gem_lockfile_sections!(locked_gem_sources.first)
131
132
  end
132
133
 
133
- @unlock[:sources] ||= []
134
+ @sources_to_unlock = @unlock.delete(:sources) || []
134
135
  @unlock[:ruby] ||= if @ruby_version && locked_ruby_version_object
135
136
  @ruby_version.diff(locked_ruby_version_object)
136
137
  end
@@ -142,11 +143,13 @@ module Bundler
142
143
  @path_changes = converge_paths
143
144
  @source_changes = converge_sources
144
145
 
146
+ @explicit_unlocks = @unlock.delete(:gems) || []
147
+
145
148
  if @unlock[:conservative]
146
- @unlock[:gems] ||= @dependencies.map(&:name)
149
+ @gems_to_unlock = @explicit_unlocks.any? ? @explicit_unlocks : @dependencies.map(&:name)
147
150
  else
148
- eager_unlock = (@unlock[:gems] || []).map {|name| Dependency.new(name, ">= 0") }
149
- @unlock[:gems] = @locked_specs.for(eager_unlock, false, platforms).map(&:name).uniq
151
+ eager_unlock = @explicit_unlocks.map {|name| Dependency.new(name, ">= 0") }
152
+ @gems_to_unlock = @locked_specs.for(eager_unlock, false, platforms).map(&:name).uniq
150
153
  end
151
154
 
152
155
  @dependency_changes = converge_dependencies
@@ -160,37 +163,24 @@ module Bundler
160
163
  end
161
164
 
162
165
  def resolve_only_locally!
163
- @remote = false
164
166
  sources.local_only!
165
167
  resolve
166
168
  end
167
169
 
168
170
  def resolve_with_cache!
171
+ sources.local!
169
172
  sources.cached!
170
173
  resolve
171
174
  end
172
175
 
173
176
  def resolve_remotely!
174
- @remote = true
177
+ sources.cached!
175
178
  sources.remote!
176
179
  resolve
177
180
  end
178
181
 
179
- def resolution_mode=(options)
180
- if options["local"]
181
- @remote = false
182
- else
183
- @remote = true
184
- @prefer_local = options["prefer-local"]
185
- end
186
- end
187
-
188
- def setup_sources_for_resolve
189
- if @remote == false
190
- sources.cached!
191
- else
192
- sources.remote!
193
- end
182
+ def prefer_local!
183
+ @prefer_local = true
194
184
  end
195
185
 
196
186
  # For given dependency list returns a SpecSet with Gemspec of all the required
@@ -225,7 +215,6 @@ module Bundler
225
215
  @resolver = nil
226
216
  @resolution_packages = nil
227
217
  @specs = nil
228
- @gem_version_promoter = nil
229
218
 
230
219
  Bundler.ui.debug "The definition is missing dependencies, failed to resolve & materialize locally (#{e})"
231
220
  true
@@ -307,7 +296,12 @@ module Bundler
307
296
  end
308
297
  end
309
298
  else
310
- Bundler.ui.debug "Found changes from the lockfile, re-resolving dependencies because #{change_reason}"
299
+ if lockfile_exists?
300
+ Bundler.ui.debug "Found changes from the lockfile, re-resolving dependencies because #{change_reason}"
301
+ else
302
+ Bundler.ui.debug "Resolving dependencies because there's no lockfile"
303
+ end
304
+
311
305
  start_resolution
312
306
  end
313
307
  end
@@ -320,38 +314,26 @@ module Bundler
320
314
  dependencies.map(&:groups).flatten.uniq
321
315
  end
322
316
 
323
- def lock(file, preserve_unknown_sections = false)
324
- return if Definition.no_lock
325
-
326
- contents = to_lock
327
-
328
- # Convert to \r\n if the existing lock has them
329
- # i.e., Windows with `git config core.autocrlf=true`
330
- contents.gsub!(/\n/, "\r\n") if @lockfile_contents.match?("\r\n")
331
-
332
- if @locked_bundler_version
333
- locked_major = @locked_bundler_version.segments.first
334
- current_major = bundler_version_to_lock.segments.first
335
-
336
- updating_major = locked_major < current_major
337
- end
317
+ def lock(file_or_preserve_unknown_sections = false, preserve_unknown_sections_or_unused = false)
318
+ if [true, false, nil].include?(file_or_preserve_unknown_sections)
319
+ target_lockfile = lockfile || Bundler.default_lockfile
320
+ preserve_unknown_sections = file_or_preserve_unknown_sections
321
+ else
322
+ target_lockfile = file_or_preserve_unknown_sections
323
+ preserve_unknown_sections = preserve_unknown_sections_or_unused
338
324
 
339
- preserve_unknown_sections ||= !updating_major && (Bundler.frozen_bundle? || !(unlocking? || @unlocking_bundler))
325
+ suggestion = if target_lockfile == lockfile
326
+ "To fix this warning, remove it from the `Definition#lock` call."
327
+ else
328
+ "Instead, instantiate a new definition passing `#{target_lockfile}`, and call `lock` without a file argument on that definition"
329
+ end
340
330
 
341
- if file && File.exist?(file) && lockfiles_equal?(@lockfile_contents, contents, preserve_unknown_sections)
342
- return if Bundler.frozen_bundle?
343
- SharedHelpers.filesystem_access(file) { FileUtils.touch(file) }
344
- return
345
- end
331
+ msg = "`Definition#lock` was passed a target file argument. #{suggestion}"
346
332
 
347
- if Bundler.frozen_bundle?
348
- Bundler.ui.error "Cannot write a changed lockfile while frozen."
349
- return
333
+ Bundler::SharedHelpers.major_deprecation 2, msg
350
334
  end
351
335
 
352
- SharedHelpers.filesystem_access(file) do |p|
353
- File.open(p, "wb") {|f| f.puts(contents) }
354
- end
336
+ write_lock(target_lockfile, preserve_unknown_sections)
355
337
  end
356
338
 
357
339
  def locked_ruby_version
@@ -385,6 +367,10 @@ module Bundler
385
367
  end
386
368
 
387
369
  def ensure_equivalent_gemfile_and_lockfile(explicit_flag = false)
370
+ return unless Bundler.frozen_bundle?
371
+
372
+ raise ProductionError, "Frozen mode is set, but there's no lockfile" unless lockfile_exists?
373
+
388
374
  added = []
389
375
  deleted = []
390
376
  changed = []
@@ -413,7 +399,7 @@ module Bundler
413
399
  changed << "* #{name} from `#{lockfile_source_name}` to `#{gemfile_source_name}`"
414
400
  end
415
401
 
416
- reason = change_reason
402
+ reason = nothing_changed? ? "some dependencies were deleted from your gemfile" : change_reason
417
403
  msg = String.new
418
404
  msg << "#{reason.capitalize.strip}, but the lockfile can't be updated because frozen mode is set"
419
405
  msg << "\n\nYou have added to the Gemfile:\n" << added.join("\n") if added.any?
@@ -471,8 +457,10 @@ module Bundler
471
457
  end
472
458
 
473
459
  def add_platform(platform)
474
- @new_platform ||= !@platforms.include?(platform)
475
- @platforms |= [platform]
460
+ return if @platforms.include?(platform)
461
+
462
+ @new_platforms << platform
463
+ @platforms << platform
476
464
  end
477
465
 
478
466
  def remove_platform(platform)
@@ -492,9 +480,11 @@ module Bundler
492
480
  private :sources
493
481
 
494
482
  def nothing_changed?
483
+ return false unless lockfile_exists?
484
+
495
485
  !@source_changes &&
496
486
  !@dependency_changes &&
497
- !@new_platform &&
487
+ @new_platforms.empty? &&
498
488
  !@path_changes &&
499
489
  !@local_changes &&
500
490
  !@missing_lockfile_dep &&
@@ -518,7 +508,45 @@ module Bundler
518
508
  end
519
509
 
520
510
  def lockfile_exists?
521
- lockfile && File.exist?(lockfile)
511
+ file_exists?(lockfile)
512
+ end
513
+
514
+ def file_exists?(file)
515
+ file && File.exist?(file)
516
+ end
517
+
518
+ def write_lock(file, preserve_unknown_sections)
519
+ return if Definition.no_lock
520
+
521
+ contents = to_lock
522
+
523
+ # Convert to \r\n if the existing lock has them
524
+ # i.e., Windows with `git config core.autocrlf=true`
525
+ contents.gsub!(/\n/, "\r\n") if @lockfile_contents.match?("\r\n")
526
+
527
+ if @locked_bundler_version
528
+ locked_major = @locked_bundler_version.segments.first
529
+ current_major = bundler_version_to_lock.segments.first
530
+
531
+ updating_major = locked_major < current_major
532
+ end
533
+
534
+ preserve_unknown_sections ||= !updating_major && (Bundler.frozen_bundle? || !(unlocking? || @unlocking_bundler))
535
+
536
+ if file_exists?(file) && lockfiles_equal?(@lockfile_contents, contents, preserve_unknown_sections)
537
+ return if Bundler.frozen_bundle?
538
+ SharedHelpers.filesystem_access(file) { FileUtils.touch(file) }
539
+ return
540
+ end
541
+
542
+ if Bundler.frozen_bundle?
543
+ Bundler.ui.error "Cannot write a changed lockfile while frozen."
544
+ return
545
+ end
546
+
547
+ SharedHelpers.filesystem_access(file) do |p|
548
+ File.open(p, "wb") {|f| f.puts(contents) }
549
+ end
522
550
  end
523
551
 
524
552
  def resolver
@@ -539,9 +567,11 @@ module Bundler
539
567
  def resolution_packages
540
568
  @resolution_packages ||= begin
541
569
  last_resolve = converge_locked_specs
542
- remove_invalid_platforms!(current_dependencies)
543
- packages = Resolver::Base.new(source_requirements, expanded_dependencies, last_resolve, @platforms, locked_specs: @originally_locked_specs, unlock: @unlock[:gems], prerelease: gem_version_promoter.pre?)
544
- additional_base_requirements_for_resolve(packages, last_resolve)
570
+ remove_invalid_platforms!
571
+ packages = Resolver::Base.new(source_requirements, expanded_dependencies, last_resolve, @platforms, locked_specs: @originally_locked_specs, unlock: @gems_to_unlock, prerelease: gem_version_promoter.pre?)
572
+ packages = additional_base_requirements_to_prevent_downgrades(packages, last_resolve)
573
+ packages = additional_base_requirements_to_force_updates(packages)
574
+ packages
545
575
  end
546
576
  end
547
577
 
@@ -556,7 +586,7 @@ module Bundler
556
586
  if missing_specs.any?
557
587
  missing_specs.each do |s|
558
588
  locked_gem = @locked_specs[s.name].last
559
- next if locked_gem.nil? || locked_gem.version != s.version || !@remote
589
+ next if locked_gem.nil? || locked_gem.version != s.version || sources.local_mode?
560
590
  raise GemNotFound, "Your bundle is locked to #{locked_gem} from #{locked_gem.source}, but that version can " \
561
591
  "no longer be found in that source. That means the author of #{locked_gem} has removed it. " \
562
592
  "You'll need to update your bundle to a version other than #{locked_gem} that hasn't been " \
@@ -575,7 +605,7 @@ module Bundler
575
605
  break if incomplete_specs.empty?
576
606
 
577
607
  Bundler.ui.debug("The lockfile does not have all gems needed for the current platform though, Bundler will still re-resolve dependencies")
578
- setup_sources_for_resolve
608
+ sources.remote!
579
609
  resolution_packages.delete(incomplete_specs)
580
610
  @resolve = start_resolution
581
611
  specs = resolve.materialize(dependencies)
@@ -597,12 +627,22 @@ module Bundler
597
627
  end
598
628
 
599
629
  def start_resolution
630
+ local_platform_needed_for_resolvability = @most_specific_non_local_locked_ruby_platform && !@platforms.include?(local_platform)
631
+ @platforms << local_platform if local_platform_needed_for_resolvability
632
+
600
633
  result = SpecSet.new(resolver.start)
601
634
 
602
635
  @resolved_bundler_version = result.find {|spec| spec.name == "bundler" }&.version
603
- @platforms = result.add_extra_platforms!(platforms) if should_add_extra_platforms?
604
636
 
605
- result.complete_platforms!(platforms)
637
+ if @most_specific_non_local_locked_ruby_platform
638
+ if spec_set_incomplete_for_platform?(result, @most_specific_non_local_locked_ruby_platform)
639
+ @platforms.delete(@most_specific_non_local_locked_ruby_platform)
640
+ elsif local_platform_needed_for_resolvability
641
+ @platforms.delete(local_platform)
642
+ end
643
+ end
644
+
645
+ @platforms = result.add_extra_platforms!(platforms) if should_add_extra_platforms?
606
646
 
607
647
  SpecSet.new(result.for(dependencies, false, @platforms))
608
648
  end
@@ -624,13 +664,6 @@ module Bundler
624
664
  end
625
665
  end
626
666
 
627
- def current_ruby_platform_locked?
628
- return false unless generic_local_platform_is_ruby?
629
- return false if Bundler.settings[:force_ruby_platform] && !@platforms.include?(Gem::Platform::RUBY)
630
-
631
- current_platform_locked?
632
- end
633
-
634
667
  def current_platform_locked?
635
668
  @platforms.any? do |bundle_platform|
636
669
  MatchPlatform.platforms_match?(bundle_platform, local_platform)
@@ -638,27 +671,41 @@ module Bundler
638
671
  end
639
672
 
640
673
  def add_current_platform
641
- return if current_ruby_platform_locked?
674
+ @most_specific_non_local_locked_ruby_platform = find_most_specific_non_local_locked_ruby_platform
675
+ return if @most_specific_non_local_locked_ruby_platform
642
676
 
643
677
  add_platform(local_platform)
644
678
  end
645
679
 
680
+ def find_most_specific_non_local_locked_ruby_platform
681
+ return unless generic_local_platform_is_ruby? && current_platform_locked?
682
+
683
+ most_specific_locked_ruby_platform = most_specific_locked_platform
684
+ return unless most_specific_locked_ruby_platform != local_platform
685
+
686
+ most_specific_locked_ruby_platform
687
+ end
688
+
646
689
  def change_reason
647
690
  if unlocking?
648
- unlock_reason = @unlock.reject {|_k, v| Array(v).empty? }.map do |k, v|
649
- if v == true
650
- k.to_s
651
- else
652
- v = Array(v)
653
- "#{k}: (#{v.join(", ")})"
654
- end
655
- end.join(", ")
691
+ unlock_targets = if @gems_to_unlock.any?
692
+ ["gems", @gems_to_unlock]
693
+ elsif @sources_to_unlock.any?
694
+ ["sources", @sources_to_unlock]
695
+ end
696
+
697
+ unlock_reason = if unlock_targets
698
+ "#{unlock_targets.first}: (#{unlock_targets.last.join(", ")})"
699
+ else
700
+ @unlock[:ruby] ? "ruby" : ""
701
+ end
702
+
656
703
  return "bundler is unlocking #{unlock_reason}"
657
704
  end
658
705
  [
659
706
  [@source_changes, "the list of sources changed"],
660
707
  [@dependency_changes, "the dependencies in your gemfile changed"],
661
- [@new_platform, "you added a new platform to your gemfile"],
708
+ [@new_platforms.any?, "you added a new platform to your gemfile"],
662
709
  [@path_changes, "the gemspecs for path gems changed"],
663
710
  [@local_changes, "the gemspecs for git local gems changed"],
664
711
  [@missing_lockfile_dep, "your lock file is missing \"#{@missing_lockfile_dep}\""],
@@ -707,7 +754,7 @@ module Bundler
707
754
  spec = @dependencies.find {|s| s.name == k }
708
755
  source = spec&.source
709
756
  if source&.respond_to?(:local_override!)
710
- source.unlock! if @unlock[:gems].include?(spec.name)
757
+ source.unlock! if @gems_to_unlock.include?(spec.name)
711
758
  locals << [source, source.local_override!(v)]
712
759
  end
713
760
  end
@@ -715,7 +762,7 @@ module Bundler
715
762
  sources_with_changes = locals.select do |source, changed|
716
763
  changed || specs_changed?(source)
717
764
  end.map(&:first)
718
- !sources_with_changes.each {|source| @unlock[:sources] << source.name }.empty?
765
+ !sources_with_changes.each {|source| @sources_to_unlock << source.name }.empty?
719
766
  end
720
767
 
721
768
  def check_lockfile
@@ -792,7 +839,7 @@ module Bundler
792
839
  # gem), unlock it. For git sources, this means to unlock the revision, which
793
840
  # will cause the `ref` used to be the most recent for the branch (or master) if
794
841
  # an explicit `ref` is not used.
795
- if source.respond_to?(:unlock!) && @unlock[:sources].include?(source.name)
842
+ if source.respond_to?(:unlock!) && @sources_to_unlock.include?(source.name)
796
843
  source.unlock!
797
844
  changes = true
798
845
  end
@@ -809,9 +856,7 @@ module Bundler
809
856
  dep.source = sources.get(dep.source)
810
857
  end
811
858
 
812
- next if unlocking?
813
-
814
- unless locked_dep = @locked_deps[dep.name]
859
+ unless locked_dep = @originally_locked_deps[dep.name]
815
860
  changes = true
816
861
  next
817
862
  end
@@ -838,7 +883,7 @@ module Bundler
838
883
  def converge_locked_specs
839
884
  converged = converge_specs(@locked_specs)
840
885
 
841
- resolve = SpecSet.new(converged.reject {|s| @unlock[:gems].include?(s.name) })
886
+ resolve = SpecSet.new(converged.reject {|s| @gems_to_unlock.include?(s.name) })
842
887
 
843
888
  diff = nil
844
889
 
@@ -871,7 +916,7 @@ module Bundler
871
916
 
872
917
  @specs_that_changed_sources << s if gemfile_source != lockfile_source
873
918
  deps << dep if !dep.source || lockfile_source.include?(dep.source)
874
- @unlock[:gems] << name if lockfile_source.include?(dep.source) && lockfile_source != gemfile_source
919
+ @gems_to_unlock << name if lockfile_source.include?(dep.source) && lockfile_source != gemfile_source
875
920
 
876
921
  # Replace the locked dependency's source with the equivalent source from the Gemfile
877
922
  s.source = gemfile_source
@@ -880,7 +925,7 @@ module Bundler
880
925
  s.source = default_source unless sources.get(lockfile_source)
881
926
  end
882
927
 
883
- next if @unlock[:sources].include?(s.source.name)
928
+ next if @sources_to_unlock.include?(s.source.name)
884
929
 
885
930
  # Path sources have special logic
886
931
  if s.source.instance_of?(Source::Path) || s.source.instance_of?(Source::Gemspec)
@@ -902,12 +947,12 @@ module Bundler
902
947
  else
903
948
  # If the spec is no longer in the path source, unlock it. This
904
949
  # commonly happens if the version changed in the gemspec
905
- @unlock[:gems] << name
950
+ @gems_to_unlock << name
906
951
  end
907
952
  end
908
953
 
909
954
  if dep.nil? && requested_dependencies.find {|d| name == d.name }
910
- @unlock[:gems] << s.name
955
+ @gems_to_unlock << s.name
911
956
  else
912
957
  converged << s
913
958
  end
@@ -934,7 +979,7 @@ module Bundler
934
979
  else
935
980
  { default: Source::RubygemsAggregate.new(sources, source_map) }.merge(source_map.direct_requirements)
936
981
  end
937
- source_requirements.merge!(source_map.locked_requirements) unless @remote
982
+ source_requirements.merge!(source_map.locked_requirements) if nothing_changed?
938
983
  metadata_dependencies.each do |dep|
939
984
  source_requirements[dep.name] = sources.metadata_source
940
985
  end
@@ -984,7 +1029,7 @@ module Bundler
984
1029
  current == proposed
985
1030
  end
986
1031
 
987
- def additional_base_requirements_for_resolve(resolution_packages, last_resolve)
1032
+ def additional_base_requirements_to_prevent_downgrades(resolution_packages, last_resolve)
988
1033
  return resolution_packages unless @locked_gems && !sources.expired_sources?(@locked_gems.sources)
989
1034
  converge_specs(@originally_locked_specs - last_resolve).each do |locked_spec|
990
1035
  next if locked_spec.source.is_a?(Source::Path)
@@ -993,21 +1038,45 @@ module Bundler
993
1038
  resolution_packages
994
1039
  end
995
1040
 
996
- def remove_invalid_platforms!(dependencies)
1041
+ def additional_base_requirements_to_force_updates(resolution_packages)
1042
+ return resolution_packages if @explicit_unlocks.empty?
1043
+ full_update = dup_for_full_unlock.resolve
1044
+ @explicit_unlocks.each do |name|
1045
+ version = full_update[name].first&.version
1046
+ resolution_packages.base_requirements[name] = Gem::Requirement.new("= #{version}") if version
1047
+ end
1048
+ resolution_packages
1049
+ end
1050
+
1051
+ def dup_for_full_unlock
1052
+ unlocked_definition = self.class.new(@lockfile, @dependencies, @sources, true, @ruby_version, @optional_groups, @gemfiles)
1053
+ unlocked_definition.gem_version_promoter.tap do |gvp|
1054
+ gvp.level = gem_version_promoter.level
1055
+ gvp.strict = gem_version_promoter.strict
1056
+ gvp.pre = gem_version_promoter.pre
1057
+ end
1058
+ unlocked_definition
1059
+ end
1060
+
1061
+ def remove_invalid_platforms!
997
1062
  return if Bundler.frozen_bundle?
998
1063
 
999
1064
  platforms.reverse_each do |platform|
1000
1065
  next if local_platform == platform ||
1001
- (@new_platform && platforms.last == platform) ||
1066
+ @new_platforms.include?(platform) ||
1002
1067
  @path_changes ||
1003
1068
  @dependency_changes ||
1004
- !@originally_locked_specs.incomplete_for_platform?(dependencies, platform)
1069
+ @locked_spec_with_invalid_deps ||
1070
+ !spec_set_incomplete_for_platform?(@originally_locked_specs, platform)
1005
1071
 
1006
1072
  remove_platform(platform)
1007
- add_current_platform if platform == Gem::Platform::RUBY
1008
1073
  end
1009
1074
  end
1010
1075
 
1076
+ def spec_set_incomplete_for_platform?(spec_set, platform)
1077
+ spec_set.incomplete_for_platform?(current_dependencies, platform)
1078
+ end
1079
+
1011
1080
  def source_map
1012
1081
  @source_map ||= SourceMap.new(sources, dependencies, @locked_specs)
1013
1082
  end
@@ -7,7 +7,7 @@ require_relative "rubygems_ext"
7
7
  module Bundler
8
8
  class Dependency < Gem::Dependency
9
9
  attr_reader :autorequire
10
- attr_reader :groups, :platforms, :gemfile, :path, :git, :github, :branch, :ref
10
+ attr_reader :groups, :platforms, :gemfile, :path, :git, :github, :branch, :ref, :glob
11
11
 
12
12
  ALL_RUBY_VERSIONS = (18..27).to_a.concat((30..34).to_a).freeze
13
13
  PLATFORM_MAP = {
@@ -39,6 +39,7 @@ module Bundler
39
39
  @github = options["github"]
40
40
  @branch = options["branch"]
41
41
  @ref = options["ref"]
42
+ @glob = options["glob"]
42
43
  @platforms = Array(options["platforms"])
43
44
  @env = options["env"]
44
45
  @should_include = options.fetch("should_include", true)
data/lib/bundler/dsl.rb CHANGED
@@ -19,6 +19,7 @@ module Bundler
19
19
  platform platforms type source install_if gemfile force_ruby_platform].freeze
20
20
 
21
21
  GITHUB_PULL_REQUEST_URL = %r{\Ahttps://github\.com/([A-Za-z0-9_\-\.]+/[A-Za-z0-9_\-\.]+)/pull/(\d+)\z}
22
+ GITLAB_MERGE_REQUEST_URL = %r{\Ahttps://gitlab\.com/([A-Za-z0-9_\-\./]+)/-/merge_requests/(\d+)\z}
22
23
 
23
24
  attr_reader :gemspecs, :gemfile
24
25
  attr_accessor :dependencies
@@ -46,7 +47,7 @@ module Bundler
46
47
  @gemfile = expanded_gemfile_path
47
48
  @gemfiles << expanded_gemfile_path
48
49
  contents ||= Bundler.read_file(@gemfile.to_s)
49
- instance_eval(contents, gemfile.to_s, 1)
50
+ instance_eval(contents, @gemfile.to_s, 1)
50
51
  rescue Exception => e # rubocop:disable Lint/RescueException
51
52
  message = "There was an error " \
52
53
  "#{e.is_a?(GemfileEvalError) ? "evaluating" : "parsing"} " \
@@ -308,6 +309,20 @@ module Bundler
308
309
  repo_name ||= user_name
309
310
  "https://#{user_name}@bitbucket.org/#{user_name}/#{repo_name}.git"
310
311
  end
312
+
313
+ git_source(:gitlab) do |repo_name|
314
+ if repo_name =~ GITLAB_MERGE_REQUEST_URL
315
+ {
316
+ "git" => "https://gitlab.com/#{$1}.git",
317
+ "branch" => nil,
318
+ "ref" => "refs/merge-requests/#{$2}/head",
319
+ "tag" => nil,
320
+ }
321
+ else
322
+ repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?("/")
323
+ "https://gitlab.com/#{repo_name}.git"
324
+ end
325
+ end
311
326
  end
312
327
 
313
328
  def with_source(source)
@@ -92,6 +92,17 @@ module Bundler
92
92
  end
93
93
  end
94
94
 
95
+ # needed for `bundle fund`
96
+ def metadata
97
+ if @remote_specification
98
+ @remote_specification.metadata
99
+ elsif _local_specification
100
+ _local_specification.metadata
101
+ else
102
+ super
103
+ end
104
+ end
105
+
95
106
  def _local_specification
96
107
  return unless @loaded_from && File.exist?(local_specification_path)
97
108
  eval(File.read(local_specification_path), nil, local_specification_path).tap do |spec|
data/lib/bundler/env.rb CHANGED
@@ -120,7 +120,7 @@ module Bundler
120
120
  specs = Bundler.rubygems.find_name(name)
121
121
  out << [" #{name}", "(#{specs.map(&:version).join(",")})"] unless specs.empty?
122
122
  end
123
- if (exe = caller.last.split(":").first)&.match? %r{(exe|bin)/bundler?\z}
123
+ if (exe = caller_locations.last.absolute_path)&.match? %r{(exe|bin)/bundler?\z}
124
124
  shebang = File.read(exe).lines.first
125
125
  shebang.sub!(/^#!\s*/, "")
126
126
  unless shebang.start_with?(Gem.ruby, "/usr/bin/env ruby")
@@ -19,14 +19,7 @@ module Bundler
19
19
  BUNDLER_PREFIX = "BUNDLER_ORIG_"
20
20
 
21
21
  def self.from_env
22
- new(env_to_hash(ENV), BUNDLER_KEYS)
23
- end
24
-
25
- def self.env_to_hash(env)
26
- to_hash = env.to_hash
27
- return to_hash unless Gem.win_platform?
28
-
29
- to_hash.each_with_object({}) {|(k,v), a| a[k.upcase] = v }
22
+ new(ENV.to_hash, BUNDLER_KEYS)
30
23
  end
31
24
 
32
25
  # @param env [Hash]
@@ -39,18 +32,7 @@ module Bundler
39
32
 
40
33
  # Replaces `ENV` with the bundler environment variables backed up
41
34
  def replace_with_backup
42
- unless Gem.win_platform?
43
- ENV.replace(backup)
44
- return
45
- end
46
-
47
- # Fallback logic for Windows below to workaround
48
- # https://bugs.ruby-lang.org/issues/16798. Can be dropped once all
49
- # supported rubies include the fix for that.
50
-
51
- ENV.clear
52
-
53
- backup.each {|k, v| ENV[k] = v }
35
+ ENV.replace(backup)
54
36
  end
55
37
 
56
38
  # @return [Hash]
@@ -58,9 +40,9 @@ module Bundler
58
40
  env = @original.clone
59
41
  @keys.each do |key|
60
42
  value = env[key]
61
- if !value.nil? && !value.empty?
43
+ if !value.nil?
62
44
  env[@prefix + key] ||= value
63
- elsif value.nil?
45
+ else
64
46
  env[@prefix + key] ||= INTENTIONALLY_NIL
65
47
  end
66
48
  end
@@ -72,7 +54,7 @@ module Bundler
72
54
  env = @original.clone
73
55
  @keys.each do |key|
74
56
  value_original = env[@prefix + key]
75
- next if value_original.nil? || value_original.empty?
57
+ next if value_original.nil?
76
58
  if value_original == INTENTIONALLY_NIL
77
59
  env.delete(key)
78
60
  else