bundler 2.2.26 → 2.3.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (140) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +166 -1
  3. data/README.md +1 -1
  4. data/exe/bundle +7 -8
  5. data/lib/bundler/.document +1 -0
  6. data/lib/bundler/build_metadata.rb +2 -2
  7. data/lib/bundler/cli/check.rb +1 -1
  8. data/lib/bundler/cli/doctor.rb +3 -2
  9. data/lib/bundler/cli/gem.rb +88 -9
  10. data/lib/bundler/cli/info.rb +16 -4
  11. data/lib/bundler/cli/install.rb +2 -3
  12. data/lib/bundler/cli/issue.rb +4 -3
  13. data/lib/bundler/cli/remove.rb +1 -2
  14. data/lib/bundler/cli/update.rb +2 -2
  15. data/lib/bundler/cli.rb +10 -1
  16. data/lib/bundler/compact_index_client/updater.rb +0 -5
  17. data/lib/bundler/compact_index_client.rb +2 -2
  18. data/lib/bundler/definition.rb +77 -124
  19. data/lib/bundler/dependency.rb +5 -7
  20. data/lib/bundler/digest.rb +71 -0
  21. data/lib/bundler/dsl.rb +18 -30
  22. data/lib/bundler/endpoint_specification.rb +0 -8
  23. data/lib/bundler/environment_preserver.rb +4 -1
  24. data/lib/bundler/errors.rb +18 -2
  25. data/lib/bundler/fetcher/compact_index.rb +9 -4
  26. data/lib/bundler/fetcher.rb +4 -6
  27. data/lib/bundler/friendly_errors.rb +5 -30
  28. data/lib/bundler/gem_helper.rb +6 -17
  29. data/lib/bundler/injector.rb +10 -1
  30. data/lib/bundler/installer/gem_installer.rb +1 -6
  31. data/lib/bundler/installer.rb +1 -5
  32. data/lib/bundler/lazy_specification.rb +17 -1
  33. data/lib/bundler/lockfile_parser.rb +10 -12
  34. data/lib/bundler/man/bundle-add.1 +10 -2
  35. data/lib/bundler/man/bundle-add.1.ronn +7 -1
  36. data/lib/bundler/man/bundle-binstubs.1 +1 -1
  37. data/lib/bundler/man/bundle-cache.1 +1 -1
  38. data/lib/bundler/man/bundle-check.1 +1 -1
  39. data/lib/bundler/man/bundle-clean.1 +1 -1
  40. data/lib/bundler/man/bundle-config.1 +5 -5
  41. data/lib/bundler/man/bundle-config.1.ronn +5 -5
  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 +14 -1
  45. data/lib/bundler/man/bundle-gem.1.ronn +16 -0
  46. data/lib/bundler/man/bundle-info.1 +1 -1
  47. data/lib/bundler/man/bundle-init.1 +1 -1
  48. data/lib/bundler/man/bundle-inject.1 +1 -1
  49. data/lib/bundler/man/bundle-install.1 +2 -2
  50. data/lib/bundler/man/bundle-install.1.ronn +2 -2
  51. data/lib/bundler/man/bundle-list.1 +1 -1
  52. data/lib/bundler/man/bundle-lock.1 +1 -1
  53. data/lib/bundler/man/bundle-open.1 +1 -1
  54. data/lib/bundler/man/bundle-outdated.1 +1 -1
  55. data/lib/bundler/man/bundle-platform.1 +1 -1
  56. data/lib/bundler/man/bundle-pristine.1 +1 -1
  57. data/lib/bundler/man/bundle-remove.1 +1 -1
  58. data/lib/bundler/man/bundle-show.1 +1 -1
  59. data/lib/bundler/man/bundle-update.1 +2 -2
  60. data/lib/bundler/man/bundle-update.1.ronn +2 -1
  61. data/lib/bundler/man/bundle-viz.1 +1 -1
  62. data/lib/bundler/man/bundle.1 +1 -1
  63. data/lib/bundler/man/gemfile.5 +28 -2
  64. data/lib/bundler/man/gemfile.5.ronn +9 -1
  65. data/lib/bundler/plugin/api/source.rb +1 -0
  66. data/lib/bundler/plugin/installer.rb +3 -1
  67. data/lib/bundler/plugin.rb +23 -6
  68. data/lib/bundler/process_lock.rb +1 -1
  69. data/lib/bundler/psyched_yaml.rb +1 -13
  70. data/lib/bundler/resolver.rb +34 -31
  71. data/lib/bundler/ruby_version.rb +1 -1
  72. data/lib/bundler/rubygems_ext.rb +6 -0
  73. data/lib/bundler/rubygems_gem_installer.rb +21 -5
  74. data/lib/bundler/rubygems_integration.rb +39 -57
  75. data/lib/bundler/runtime.rb +2 -2
  76. data/lib/bundler/self_manager.rb +94 -0
  77. data/lib/bundler/settings.rb +10 -1
  78. data/lib/bundler/shared_helpers.rb +4 -12
  79. data/lib/bundler/source/git/git_proxy.rb +7 -4
  80. data/lib/bundler/source/git.rb +22 -4
  81. data/lib/bundler/source/metadata.rb +1 -1
  82. data/lib/bundler/source/rubygems.rb +60 -85
  83. data/lib/bundler/source/rubygems_aggregate.rb +1 -1
  84. data/lib/bundler/source.rb +3 -1
  85. data/lib/bundler/source_list.rb +11 -29
  86. data/lib/bundler/spec_set.rb +2 -2
  87. data/lib/bundler/templates/Executable.bundler +1 -1
  88. data/lib/bundler/templates/Gemfile +0 -2
  89. data/lib/bundler/templates/gems.rb +0 -3
  90. data/lib/bundler/templates/newgem/Gemfile.tt +5 -2
  91. data/lib/bundler/templates/newgem/Rakefile.tt +15 -2
  92. data/lib/bundler/templates/newgem/github/workflows/main.yml.tt +4 -3
  93. data/lib/bundler/templates/newgem/newgem.gemspec.tt +14 -14
  94. data/lib/bundler/templates/newgem/sig/newgem.rbs.tt +8 -0
  95. data/lib/bundler/templates/newgem/standard.yml.tt +2 -0
  96. data/lib/bundler/templates/newgem/test/minitest/{newgem_test.rb.tt → test_newgem.rb.tt} +1 -1
  97. data/lib/bundler/ui/shell.rb +1 -1
  98. data/lib/bundler/vendor/.document +1 -0
  99. data/lib/bundler/vendor/connection_pool/LICENSE +20 -0
  100. data/lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb +19 -21
  101. data/lib/bundler/vendor/connection_pool/lib/connection_pool/version.rb +1 -1
  102. data/lib/bundler/vendor/connection_pool/lib/connection_pool/wrapper.rb +57 -0
  103. data/lib/bundler/vendor/connection_pool/lib/connection_pool.rb +39 -74
  104. data/lib/bundler/vendor/fileutils/LICENSE.txt +22 -0
  105. data/lib/bundler/vendor/molinillo/LICENSE +9 -0
  106. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph.rb +2 -2
  107. data/lib/bundler/vendor/net-http-persistent/README.rdoc +82 -0
  108. data/lib/bundler/vendor/thor/LICENSE.md +20 -0
  109. data/lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb +6 -6
  110. data/lib/bundler/vendor/thor/lib/thor/actions/inject_into_file.rb +5 -3
  111. data/lib/bundler/vendor/thor/lib/thor/actions.rb +6 -2
  112. data/lib/bundler/vendor/thor/lib/thor/core_ext/hash_with_indifferent_access.rb +6 -0
  113. data/lib/bundler/vendor/thor/lib/thor/error.rb +9 -4
  114. data/lib/bundler/vendor/thor/lib/thor/parser/options.rb +19 -1
  115. data/lib/bundler/vendor/thor/lib/thor/shell/basic.rb +22 -4
  116. data/lib/bundler/vendor/thor/lib/thor/shell.rb +1 -1
  117. data/lib/bundler/vendor/thor/lib/thor/util.rb +1 -1
  118. data/lib/bundler/vendor/tsort/LICENSE.txt +22 -0
  119. data/lib/bundler/vendor/tsort/lib/tsort.rb +453 -0
  120. data/lib/bundler/vendor/uri/LICENSE.txt +22 -0
  121. data/lib/bundler/vendor/uri/lib/uri/common.rb +17 -80
  122. data/lib/bundler/vendor/uri/lib/uri/ftp.rb +0 -1
  123. data/lib/bundler/vendor/uri/lib/uri/generic.rb +5 -6
  124. data/lib/bundler/vendor/uri/lib/uri/http.rb +0 -1
  125. data/lib/bundler/vendor/uri/lib/uri/https.rb +0 -1
  126. data/lib/bundler/vendor/uri/lib/uri/ldap.rb +1 -1
  127. data/lib/bundler/vendor/uri/lib/uri/mailto.rb +0 -1
  128. data/lib/bundler/vendor/uri/lib/uri/rfc2396_parser.rb +1 -14
  129. data/lib/bundler/vendor/uri/lib/uri/rfc3986_parser.rb +1 -12
  130. data/lib/bundler/vendor/uri/lib/uri/version.rb +1 -1
  131. data/lib/bundler/vendor/uri/lib/uri/ws.rb +84 -0
  132. data/lib/bundler/vendor/uri/lib/uri/wss.rb +22 -0
  133. data/lib/bundler/vendor/uri/lib/uri.rb +0 -1
  134. data/lib/bundler/vendored_tsort.rb +4 -0
  135. data/lib/bundler/version.rb +1 -1
  136. data/lib/bundler/worker.rb +2 -2
  137. data/lib/bundler.rb +22 -21
  138. metadata +25 -9
  139. data/lib/bundler/gemdeps.rb +0 -29
  140. data/lib/bundler/vendor/connection_pool/lib/connection_pool/monotonic_time.rb +0 -66
@@ -6,6 +6,11 @@ module Bundler
6
6
  class Definition
7
7
  include GemHelpers
8
8
 
9
+ class << self
10
+ # Do not create or modify a lockfile (Makes #lock a noop)
11
+ attr_accessor :no_lock
12
+ end
13
+
9
14
  attr_reader(
10
15
  :dependencies,
11
16
  :locked_deps,
@@ -73,7 +78,6 @@ module Bundler
73
78
  @lockfile_contents = String.new
74
79
  @locked_bundler_version = nil
75
80
  @locked_ruby_version = nil
76
- @locked_specs_incomplete_for_platform = false
77
81
  @new_platform = nil
78
82
 
79
83
  if lockfile && File.exist?(lockfile)
@@ -139,6 +143,8 @@ module Bundler
139
143
  @dependency_changes = converge_dependencies
140
144
  @local_changes = converge_locals
141
145
 
146
+ @locked_specs_incomplete_for_platform = !@locked_specs.for(requested_dependencies & expand_dependencies(locked_dependencies), true, true)
147
+
142
148
  @requires = compute_requires
143
149
  end
144
150
 
@@ -157,8 +163,10 @@ module Bundler
157
163
  end
158
164
  end
159
165
 
160
- def multisource_allowed?
161
- @multisource_allowed
166
+ def resolve_only_locally!
167
+ @remote = false
168
+ sources.local_only!
169
+ resolve
162
170
  end
163
171
 
164
172
  def resolve_with_cache!
@@ -222,17 +230,22 @@ module Bundler
222
230
  end
223
231
  end
224
232
 
233
+ def locked_dependencies
234
+ @locked_deps.values
235
+ end
236
+
225
237
  def specs_for(groups)
226
- groups = requested_groups if groups.empty?
238
+ return specs if groups.empty?
227
239
  deps = dependencies_for(groups)
228
- materialize(expand_dependencies(deps))
240
+ materialize(deps)
229
241
  end
230
242
 
231
243
  def dependencies_for(groups)
232
244
  groups.map!(&:to_sym)
233
- current_dependencies.reject do |d|
245
+ deps = current_dependencies.reject do |d|
234
246
  (d.groups & groups).empty?
235
247
  end
248
+ expand_dependencies(deps)
236
249
  end
237
250
 
238
251
  # Resolve all the dependencies specified in Gemfile. It ensures that
@@ -267,6 +280,8 @@ module Bundler
267
280
  end
268
281
 
269
282
  def lock(file, preserve_unknown_sections = false)
283
+ return if Definition.no_lock
284
+
270
285
  contents = to_lock
271
286
 
272
287
  # Convert to \r\n if the existing lock has them
@@ -277,10 +292,7 @@ module Bundler
277
292
  locked_major = @locked_bundler_version.segments.first
278
293
  current_major = Gem::Version.create(Bundler::VERSION).segments.first
279
294
 
280
- if updating_major = locked_major < current_major
281
- Bundler.ui.warn "Warning: the lockfile is being updated to Bundler #{current_major}, " \
282
- "after which you will be unable to return to Bundler #{@locked_bundler_version.segments.first}."
283
- end
295
+ updating_major = locked_major < current_major
284
296
  end
285
297
 
286
298
  preserve_unknown_sections ||= !updating_major && (Bundler.frozen_bundle? || !(unlocking? || @unlocking_bundler))
@@ -356,44 +368,31 @@ module Bundler
356
368
  added.concat new_platforms.map {|p| "* platform: #{p}" }
357
369
  deleted.concat deleted_platforms.map {|p| "* platform: #{p}" }
358
370
 
359
- gemfile_sources = sources.lock_sources
360
-
361
- new_sources = gemfile_sources - @locked_sources
362
- deleted_sources = @locked_sources - gemfile_sources
371
+ new_deps = @dependencies - locked_dependencies
372
+ deleted_deps = locked_dependencies - @dependencies
363
373
 
364
- new_deps = @dependencies - @locked_deps.values
365
- deleted_deps = @locked_deps.values - @dependencies
374
+ added.concat new_deps.map {|d| "* #{pretty_dep(d)}" } if new_deps.any?
375
+ deleted.concat deleted_deps.map {|d| "* #{pretty_dep(d)}" } if deleted_deps.any?
366
376
 
367
- # Check if it is possible that the source is only changed thing
368
- if (new_deps.empty? && deleted_deps.empty?) && (!new_sources.empty? && !deleted_sources.empty?)
369
- new_sources.reject! {|source| (source.path? && source.path.exist?) || equivalent_rubygems_remotes?(source) }
370
- deleted_sources.reject! {|source| (source.path? && source.path.exist?) || equivalent_rubygems_remotes?(source) }
371
- end
377
+ both_sources = Hash.new {|h, k| h[k] = [] }
378
+ @dependencies.each {|d| both_sources[d.name][0] = d }
372
379
 
373
- if @locked_sources != gemfile_sources
374
- if new_sources.any?
375
- added.concat new_sources.map {|source| "* source: #{source}" }
376
- end
380
+ locked_dependencies.each do |d|
381
+ next if !Bundler.feature_flag.bundler_3_mode? && @locked_specs[d.name].empty?
377
382
 
378
- if deleted_sources.any?
379
- deleted.concat deleted_sources.map {|source| "* source: #{source}" }
380
- end
383
+ both_sources[d.name][1] = d
381
384
  end
382
385
 
383
- added.concat new_deps.map {|d| "* #{pretty_dep(d)}" } if new_deps.any?
384
- if deleted_deps.any?
385
- deleted.concat deleted_deps.map {|d| "* #{pretty_dep(d)}" }
386
- end
386
+ both_sources.each do |name, (dep, lock_dep)|
387
+ next if dep.nil? || lock_dep.nil?
387
388
 
388
- both_sources = Hash.new {|h, k| h[k] = [] }
389
- @dependencies.each {|d| both_sources[d.name][0] = d }
390
- @locked_deps.each {|name, d| both_sources[name][1] = d.source }
389
+ gemfile_source = dep.source || sources.default_source
390
+ lock_source = lock_dep.source || sources.default_source
391
+ next if lock_source.include?(gemfile_source)
391
392
 
392
- both_sources.each do |name, (dep, lock_source)|
393
- next if lock_source.nil? || (dep && lock_source.can_lock?(dep))
394
- gemfile_source_name = (dep && dep.source) || "no specified source"
395
- lockfile_source_name = lock_source
396
- changed << "* #{name} from `#{gemfile_source_name}` to `#{lockfile_source_name}`"
393
+ gemfile_source_name = dep.source ? gemfile_source.identifier : "no specified source"
394
+ lockfile_source_name = lock_dep.source ? lock_source.identifier : "no specified source"
395
+ changed << "* #{name} from `#{lockfile_source_name}` to `#{gemfile_source_name}`"
397
396
  end
398
397
 
399
398
  reason = change_reason
@@ -554,7 +553,7 @@ module Bundler
554
553
 
555
554
  def dependencies_for_source_changed?(source, locked_source = source)
556
555
  deps_for_source = @dependencies.select {|s| s.source == source }
557
- locked_deps_for_source = @locked_deps.values.select {|dep| dep.source == locked_source }
556
+ locked_deps_for_source = locked_dependencies.select {|dep| dep.source == locked_source }
558
557
 
559
558
  deps_for_source.uniq.sort != locked_deps_for_source.sort
560
559
  end
@@ -637,25 +636,14 @@ module Bundler
637
636
  end
638
637
 
639
638
  def converge_dependencies
640
- frozen = Bundler.frozen_bundle?
641
- (@dependencies + @locked_deps.values).each do |dep|
642
- locked_source = @locked_deps[dep.name]
643
- # This is to make sure that if bundler is installing in deployment mode and
644
- # after locked_source and sources don't match, we still use locked_source.
645
- if frozen && !locked_source.nil? &&
646
- locked_source.respond_to?(:source) && locked_source.source.instance_of?(Source::Path) && locked_source.source.path.exist?
647
- dep.source = locked_source.source
648
- elsif dep.source
639
+ changes = false
640
+
641
+ @dependencies.each do |dep|
642
+ if dep.source
649
643
  dep.source = sources.get(dep.source)
650
644
  end
651
- end
652
645
 
653
- changes = false
654
- # We want to know if all match, but don't want to check all entries
655
- # This means we need to return false if any dependency doesn't match
656
- # the lock or doesn't exist in the lock.
657
- @dependencies.each do |dependency|
658
- unless locked_dep = @locked_deps[dependency.name]
646
+ unless locked_dep = @locked_deps[dep.name]
659
647
  changes = true
660
648
  next
661
649
  end
@@ -666,11 +654,11 @@ module Bundler
666
654
  # directive, the lockfile dependencies and resolved dependencies end up
667
655
  # with a mismatch on #type. Work around that by setting the type on the
668
656
  # dep from the lockfile.
669
- locked_dep.instance_variable_set(:@type, dependency.type)
657
+ locked_dep.instance_variable_set(:@type, dep.type)
670
658
 
671
659
  # We already know the name matches from the hash lookup
672
660
  # so we only need to check the requirement now
673
- changes ||= dependency.requirement != locked_dep.requirement
661
+ changes ||= dep.requirement != locked_dep.requirement
674
662
  end
675
663
 
676
664
  changes
@@ -680,39 +668,36 @@ module Bundler
680
668
  # commonly happen if the Gemfile has changed since the lockfile was last
681
669
  # generated
682
670
  def converge_locked_specs
683
- deps = []
671
+ resolve = converge_specs(@locked_specs)
684
672
 
685
- # Build a list of dependencies that are the same in the Gemfile
686
- # and Gemfile.lock. If the Gemfile modified a dependency, but
687
- # the gem in the Gemfile.lock still satisfies it, this is fine
688
- # too.
689
- @dependencies.each do |dep|
690
- locked_dep = @locked_deps[dep.name]
691
-
692
- # If the locked_dep doesn't match the dependency we're looking for then we ignore the locked_dep
693
- locked_dep = nil unless locked_dep == dep
673
+ diff = nil
694
674
 
695
- if in_locked_deps?(dep, locked_dep) || satisfies_locked_spec?(dep)
696
- deps << dep
697
- elsif dep.source.is_a?(Source::Path) && dep.current_platform? && (!locked_dep || dep.source != locked_dep.source)
698
- @locked_specs.each do |s|
699
- @unlock[:gems] << s.name if s.source == dep.source
700
- end
675
+ # Now, we unlock any sources that do not have anymore gems pinned to it
676
+ sources.all_sources.each do |source|
677
+ next unless source.respond_to?(:unlock!)
701
678
 
702
- dep.source.unlock! if dep.source.respond_to?(:unlock!)
703
- dep.source.specs.each {|s| @unlock[:gems] << s.name }
679
+ unless resolve.any? {|s| s.source == source }
680
+ diff ||= @locked_specs.to_a - resolve.to_a
681
+ source.unlock! if diff.any? {|s| s.source == source }
704
682
  end
705
683
  end
706
684
 
685
+ resolve
686
+ end
687
+
688
+ def converge_specs(specs)
689
+ deps = []
707
690
  converged = []
708
- @locked_specs.each do |s|
691
+ specs.each do |s|
709
692
  # Replace the locked dependency's source with the equivalent source from the Gemfile
710
693
  dep = @dependencies.find {|d| s.satisfies?(d) }
711
- s.source = (dep && dep.source) || sources.get(s.source) unless multisource_allowed?
712
694
 
713
- # Don't add a spec to the list if its source is expired. For example,
714
- # if you change a Git gem to RubyGems.
715
- next if s.source.nil?
695
+ if dep && (!dep.source || s.source.include?(dep.source))
696
+ deps << dep
697
+ end
698
+
699
+ s.source = (dep && dep.source) || sources.get(s.source) || sources.default_source unless Bundler.frozen_bundle?
700
+
716
701
  next if @unlock[:sources].include?(s.source.name)
717
702
 
718
703
  # If the spec is from a path source and it doesn't exist anymore
@@ -725,7 +710,7 @@ module Bundler
725
710
  rescue PathError, GitError
726
711
  # if we won't need the source (according to the lockfile),
727
712
  # don't error if the path/git source isn't available
728
- next if @locked_specs.
713
+ next if specs.
729
714
  for(requested_dependencies, false, true).
730
715
  none? {|locked_spec| locked_spec.source == s.source }
731
716
 
@@ -741,36 +726,15 @@ module Bundler
741
726
  s.dependencies.replace(new_spec.dependencies)
742
727
  end
743
728
 
744
- converged << s
745
- end
746
-
747
- resolve = SpecSet.new(converged)
748
- @locked_specs_incomplete_for_platform = !resolve.for(expand_dependencies(requested_dependencies & deps), true, true)
749
- resolve = SpecSet.new(resolve.for(expand_dependencies(deps, true), false, false).reject{|s| @unlock[:gems].include?(s.name) })
750
- diff = nil
751
-
752
- # Now, we unlock any sources that do not have anymore gems pinned to it
753
- sources.all_sources.each do |source|
754
- next unless source.respond_to?(:unlock!)
755
-
756
- unless resolve.any? {|s| s.source == source }
757
- diff ||= @locked_specs.to_a - resolve.to_a
758
- source.unlock! if diff.any? {|s| s.source == source }
729
+ if dep.nil? && requested_dependencies.find {|d| s.name == d.name }
730
+ @unlock[:gems] << s.name
731
+ else
732
+ converged << s
759
733
  end
760
734
  end
761
735
 
762
- resolve
763
- end
764
-
765
- def in_locked_deps?(dep, locked_dep)
766
- # Because the lockfile can't link a dep to a specific remote, we need to
767
- # treat sources as equivalent anytime the locked dep has all the remotes
768
- # that the Gemfile dep does.
769
- locked_dep && locked_dep.source && dep.source && locked_dep.source.include?(dep.source)
770
- end
771
-
772
- def satisfies_locked_spec?(dep)
773
- @locked_specs[dep].any? {|s| s.satisfies?(dep) && (!dep.source || s.source.include?(dep.source)) }
736
+ resolve = SpecSet.new(converged)
737
+ SpecSet.new(resolve.for(expand_dependencies(deps, true), false, false).reject{|s| @unlock[:gems].include?(s.name) })
774
738
  end
775
739
 
776
740
  def metadata_dependencies
@@ -863,22 +827,11 @@ module Bundler
863
827
 
864
828
  def additional_base_requirements_for_resolve
865
829
  return [] unless @locked_gems && unlocking? && !sources.expired_sources?(@locked_gems.sources)
866
- dependencies_by_name = dependencies.inject({}) {|memo, dep| memo.update(dep.name => dep) }
867
- @locked_gems.specs.reduce({}) do |requirements, locked_spec|
830
+ converge_specs(@locked_gems.specs).map do |locked_spec|
868
831
  name = locked_spec.name
869
- dependency = dependencies_by_name[name]
870
- next requirements if @locked_gems.dependencies[name] != dependency
871
- next requirements if dependency && dependency.source.is_a?(Source::Path)
872
832
  dep = Gem::Dependency.new(name, ">= #{locked_spec.version}")
873
- requirements[name] = DepProxy.get_proxy(dep, locked_spec.platform)
874
- requirements
875
- end.values
876
- end
877
-
878
- def equivalent_rubygems_remotes?(source)
879
- return false unless source.is_a?(Source::Rubygems)
880
-
881
- Bundler.settings[:allow_deployment_source_credential_changes] && source.equivalent_remotes?(sources.rubygems_remotes)
833
+ DepProxy.get_proxy(dep, locked_spec.platform)
834
+ end
882
835
  end
883
836
 
884
837
  def source_map
@@ -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, :git, :branch
10
+ attr_reader :groups, :platforms, :gemfile, :git, :github, :branch, :ref
11
11
 
12
12
  PLATFORM_MAP = {
13
13
  :ruby => Gem::Platform::RUBY,
@@ -82,7 +82,9 @@ module Bundler
82
82
  @groups = Array(options["group"] || :default).map(&:to_sym)
83
83
  @source = options["source"]
84
84
  @git = options["git"]
85
+ @github = options["github"]
85
86
  @branch = options["branch"]
87
+ @ref = options["ref"]
86
88
  @platforms = Array(options["platforms"])
87
89
  @env = options["env"]
88
90
  @should_include = options.fetch("should_include", true)
@@ -96,15 +98,11 @@ module Bundler
96
98
  def gem_platforms(valid_platforms)
97
99
  return valid_platforms if @platforms.empty?
98
100
 
99
- valid_generic_platforms = valid_platforms.map {|p| [p, GemHelpers.generic(p)] }.to_h
100
- @gem_platforms ||= expanded_platforms.compact.uniq
101
-
102
- filtered_generic_platforms = valid_generic_platforms.values & @gem_platforms
103
- valid_generic_platforms.select {|_, v| filtered_generic_platforms.include?(v) }.keys
101
+ valid_platforms.select {|p| expanded_platforms.include?(GemHelpers.generic(p)) }
104
102
  end
105
103
 
106
104
  def expanded_platforms
107
- @platforms.map {|pl| PLATFORM_MAP[pl] }
105
+ @expanded_platforms ||= @platforms.map {|pl| PLATFORM_MAP[pl] }.compact.uniq
108
106
  end
109
107
 
110
108
  def should_include?
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This code was extracted from https://github.com/Solistra/ruby-digest which is under public domain
4
+ module Bundler
5
+ module Digest
6
+ # The initial constant values for the 32-bit constant words A, B, C, D, and
7
+ # E, respectively.
8
+ SHA1_WORDS = [0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0].freeze
9
+
10
+ # The 8-bit field used for bitwise `AND` masking. Defaults to `0xFFFFFFFF`.
11
+ SHA1_MASK = 0xFFFFFFFF
12
+
13
+ class << self
14
+ def sha1(string)
15
+ unless string.is_a?(String)
16
+ raise TypeError, "can't convert #{string.class.inspect} into String"
17
+ end
18
+
19
+ buffer = string.b
20
+
21
+ words = SHA1_WORDS.dup
22
+ generate_split_buffer(buffer) do |chunk|
23
+ w = []
24
+ chunk.each_slice(4) do |a, b, c, d|
25
+ w << (((a << 8 | b) << 8 | c) << 8 | d)
26
+ end
27
+ a, b, c, d, e = *words
28
+ (16..79).each do |i|
29
+ w[i] = SHA1_MASK & rotate((w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16]), 1)
30
+ end
31
+ 0.upto(79) do |i|
32
+ case i
33
+ when 0..19
34
+ f = ((b & c) | (~b & d))
35
+ k = 0x5A827999
36
+ when 20..39
37
+ f = (b ^ c ^ d)
38
+ k = 0x6ED9EBA1
39
+ when 40..59
40
+ f = ((b & c) | (b & d) | (c & d))
41
+ k = 0x8F1BBCDC
42
+ when 60..79
43
+ f = (b ^ c ^ d)
44
+ k = 0xCA62C1D6
45
+ end
46
+ t = SHA1_MASK & (SHA1_MASK & rotate(a, 5) + f + e + k + w[i])
47
+ a, b, c, d, e = t, a, SHA1_MASK & rotate(b, 30), c, d # rubocop:disable Style/ParallelAssignment
48
+ end
49
+ mutated = [a, b, c, d, e]
50
+ words.map!.with_index {|word, index| SHA1_MASK & (word + mutated[index]) }
51
+ end
52
+
53
+ words.pack("N*").unpack("H*").first
54
+ end
55
+
56
+ private
57
+
58
+ def generate_split_buffer(string, &block)
59
+ size = string.bytesize * 8
60
+ buffer = string.bytes << 128
61
+ buffer << 0 while buffer.size % 64 != 56
62
+ buffer.concat([size].pack("Q>").bytes)
63
+ buffer.each_slice(64, &block)
64
+ end
65
+
66
+ def rotate(value, spaces)
67
+ value << spaces | value >> (32 - spaces)
68
+ end
69
+ end
70
+ end
71
+ end
data/lib/bundler/dsl.rb CHANGED
@@ -18,6 +18,8 @@ module Bundler
18
18
  VALID_KEYS = %w[group groups git path glob name branch ref tag require submodules
19
19
  platform platforms type source install_if gemfile].freeze
20
20
 
21
+ GITHUB_PULL_REQUEST_URL = %r{\Ahttps://github\.com/([A-Za-z0-9_\-\.]+/[A-Za-z0-9_\-\.]+)/pull/(\d+)\z}.freeze
22
+
21
23
  attr_reader :gemspecs
22
24
  attr_accessor :dependencies
23
25
 
@@ -275,26 +277,24 @@ module Bundler
275
277
 
276
278
  def add_git_sources
277
279
  git_source(:github) do |repo_name|
278
- warn_deprecated_git_source(:github, <<-'RUBY'.strip, 'Change any "reponame" :github sources to "username/reponame".')
279
- "https://github.com/#{repo_name}.git"
280
- RUBY
281
- repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?("/")
282
- "https://github.com/#{repo_name}.git"
280
+ if repo_name =~ GITHUB_PULL_REQUEST_URL
281
+ {
282
+ "git" => "https://github.com/#{$1}.git",
283
+ "branch" => "refs/pull/#{$2}/head",
284
+ "ref" => nil,
285
+ "tag" => nil,
286
+ }
287
+ else
288
+ repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?("/")
289
+ "https://github.com/#{repo_name}.git"
290
+ end
283
291
  end
284
292
 
285
293
  git_source(:gist) do |repo_name|
286
- warn_deprecated_git_source(:gist, '"https://gist.github.com/#{repo_name}.git"')
287
-
288
294
  "https://gist.github.com/#{repo_name}.git"
289
295
  end
290
296
 
291
297
  git_source(:bitbucket) do |repo_name|
292
- warn_deprecated_git_source(:bitbucket, <<-'RUBY'.strip)
293
- user_name, repo_name = repo_name.split("/")
294
- repo_name ||= user_name
295
- "https://#{user_name}@bitbucket.org/#{user_name}/#{repo_name}.git"
296
- RUBY
297
-
298
298
  user_name, repo_name = repo_name.split("/")
299
299
  repo_name ||= user_name
300
300
  "https://#{user_name}@bitbucket.org/#{user_name}/#{repo_name}.git"
@@ -365,7 +365,11 @@ repo_name ||= user_name
365
365
 
366
366
  git_name = (git_names & opts.keys).last
367
367
  if @git_sources[git_name]
368
- opts["git"] = @git_sources[git_name].call(opts[git_name])
368
+ git_opts = @git_sources[git_name].call(opts[git_name])
369
+ git_opts = { "git" => git_opts } if git_opts.is_a?(String)
370
+ opts.merge!(git_opts) do |key, _gemfile_value, _git_source_value|
371
+ raise GemfileError, %(The :#{key} option can't be used with `#{git_name}: #{opts[git_name].inspect}`)
372
+ end
369
373
  end
370
374
 
371
375
  %w[git path].each do |type|
@@ -475,22 +479,6 @@ repo_name ||= user_name
475
479
  end
476
480
  end
477
481
 
478
- def warn_deprecated_git_source(name, replacement, additional_message = nil)
479
- additional_message &&= " #{additional_message}"
480
- replacement = if replacement.count("\n").zero?
481
- "{|repo_name| #{replacement} }"
482
- else
483
- "do |repo_name|\n#{replacement.to_s.gsub(/^/, " ")}\n end"
484
- end
485
-
486
- Bundler::SharedHelpers.major_deprecation 3, <<-EOS
487
- The :#{name} git source is deprecated, and will be removed in the future.#{additional_message} Add this code to the top of your Gemfile to ensure it continues to work:
488
-
489
- git_source(:#{name}) #{replacement}
490
-
491
- EOS
492
- end
493
-
494
482
  class DSLError < GemfileError
495
483
  # @return [String] the description that should be presented to the user.
496
484
  #
@@ -3,7 +3,6 @@
3
3
  module Bundler
4
4
  # used for Creating Specifications from the Gemcutter Endpoint
5
5
  class EndpointSpecification < Gem::Specification
6
- ILLFORMED_MESSAGE = 'Ill-formed requirement ["#<YAML::Syck::DefaultKey'.freeze
7
6
  include MatchPlatform
8
7
 
9
8
  attr_reader :name, :version, :platform, :required_rubygems_version, :required_ruby_version, :checksum
@@ -129,13 +128,6 @@ module Bundler
129
128
 
130
129
  def build_dependency(name, requirements)
131
130
  Gem::Dependency.new(name, requirements)
132
- rescue ArgumentError => e
133
- raise unless e.message.include?(ILLFORMED_MESSAGE)
134
- puts # we shouldn't print the error message on the "fetching info" status line
135
- raise GemspecError,
136
- "Unfortunately, the gem #{name} (#{version}) has an invalid " \
137
- "gemspec.\nPlease ask the gem author to yank the bad version to fix " \
138
- "this issue. For more information, see http://bit.ly/syck-defaultkey."
139
131
  end
140
132
  end
141
133
  end
@@ -38,7 +38,10 @@ module Bundler
38
38
 
39
39
  # Replaces `ENV` with the bundler environment variables backed up
40
40
  def replace_with_backup
41
- ENV.replace(backup) unless Gem.win_platform?
41
+ unless Gem.win_platform?
42
+ ENV.replace(backup)
43
+ return
44
+ end
42
45
 
43
46
  # Fallback logic for Windows below to workaround
44
47
  # https://bugs.ruby-lang.org/issues/16798. Can be dropped once all
@@ -75,10 +75,26 @@ module Bundler
75
75
  end
76
76
  end
77
77
 
78
+ def permission_type
79
+ case @permission_type
80
+ when :create
81
+ "executable permissions for all parent directories and write permissions for `#{parent_folder}`"
82
+ when :delete
83
+ permissions = "executable permissions for all parent directories and write permissions for `#{parent_folder}`"
84
+ permissions += ", and the same thing for all subdirectories inside #{@path}" if File.directory?(@path)
85
+ permissions
86
+ else
87
+ "#{@permission_type} permissions for that path"
88
+ end
89
+ end
90
+
91
+ def parent_folder
92
+ File.dirname(@path)
93
+ end
94
+
78
95
  def message
79
96
  "There was an error while trying to #{action} `#{@path}`. " \
80
- "It is likely that you need to grant #{@permission_type} permissions " \
81
- "for that path."
97
+ "It is likely that you need to grant #{permission_type}."
82
98
  end
83
99
 
84
100
  status_code(23)
@@ -68,11 +68,16 @@ module Bundler
68
68
  compact_index_request :fetch_spec
69
69
 
70
70
  def available?
71
- return nil unless SharedHelpers.md5_available?
72
- user_home = Bundler.user_home
73
- return nil unless user_home.directory? && user_home.writable?
71
+ unless SharedHelpers.md5_available?
72
+ Bundler.ui.debug("FIPS mode is enabled, bundler can't use the CompactIndex API")
73
+ return nil
74
+ end
75
+ if fetch_uri.scheme == "file"
76
+ Bundler.ui.debug("Using a local server, bundler won't use the CompactIndex API")
77
+ return false
78
+ end
74
79
  # Read info file checksums out of /versions, so we can know if gems are up to date
75
- fetch_uri.scheme != "file" && compact_index_client.update_and_parse_checksums!
80
+ compact_index_client.update_and_parse_checksums!
76
81
  rescue CompactIndexClient::Updater::MisMatchedChecksumError => e
77
82
  Bundler.ui.debug(e.message)
78
83
  nil
@@ -28,7 +28,8 @@ module Bundler
28
28
  " is a chance you are experiencing a man-in-the-middle attack, but" \
29
29
  " most likely your system doesn't have the CA certificates needed" \
30
30
  " for verification. For information about OpenSSL certificates, see" \
31
- " http://bit.ly/ruby-ssl. To connect without using SSL, edit your Gemfile" \
31
+ " https://railsapps.github.io/openssl-certificate-verify-failed.html." \
32
+ " To connect without using SSL, edit your Gemfile" \
32
33
  " sources and change 'https' to 'http'."
33
34
  end
34
35
  end
@@ -70,8 +71,8 @@ module Bundler
70
71
  :HTTPUnsupportedMediaType, :HTTPVersionNotSupported].freeze
71
72
  FAIL_ERRORS = begin
72
73
  fail_errors = [AuthenticationRequiredError, BadAuthenticationError, FallbackError]
73
- fail_errors << Gem::Requirement::BadRequirementError if defined?(Gem::Requirement::BadRequirementError)
74
- fail_errors.concat(NET_ERRORS.map {|e| SharedHelpers.const_get_safely(e, Net) }.compact)
74
+ fail_errors << Gem::Requirement::BadRequirementError
75
+ fail_errors.concat(NET_ERRORS.map {|e| Net.const_get(e) })
75
76
  end.freeze
76
77
 
77
78
  class << self
@@ -121,7 +122,6 @@ module Bundler
121
122
 
122
123
  # return the specs in the bundler format as an index
123
124
  def specs(gem_names, source)
124
- old = Bundler.rubygems.sources
125
125
  index = Bundler::Index.new
126
126
 
127
127
  if Bundler::Fetcher.disable_endpoint
@@ -152,8 +152,6 @@ module Bundler
152
152
  rescue CertificateFailureError
153
153
  Bundler.ui.info "" if gem_names && use_api # newline after dots
154
154
  raise
155
- ensure
156
- Bundler.rubygems.sources = old
157
155
  end
158
156
 
159
157
  def use_api