bundler 2.2.29 → 2.2.33

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +79 -1
  3. data/README.md +1 -1
  4. data/lib/bundler/build_metadata.rb +2 -2
  5. data/lib/bundler/cli/doctor.rb +3 -2
  6. data/lib/bundler/cli/gem.rb +69 -7
  7. data/lib/bundler/cli/info.rb +16 -4
  8. data/lib/bundler/cli/issue.rb +4 -3
  9. data/lib/bundler/cli/update.rb +2 -2
  10. data/lib/bundler/cli.rb +4 -1
  11. data/lib/bundler/compact_index_client/updater.rb +0 -5
  12. data/lib/bundler/compact_index_client.rb +2 -2
  13. data/lib/bundler/definition.rb +62 -124
  14. data/lib/bundler/digest.rb +71 -0
  15. data/lib/bundler/dsl.rb +18 -3
  16. data/lib/bundler/environment_preserver.rb +4 -1
  17. data/lib/bundler/errors.rb +18 -2
  18. data/lib/bundler/fetcher.rb +2 -1
  19. data/lib/bundler/friendly_errors.rb +5 -30
  20. data/lib/bundler/gem_helper.rb +5 -16
  21. data/lib/bundler/lazy_specification.rb +17 -1
  22. data/lib/bundler/lockfile_parser.rb +1 -0
  23. data/lib/bundler/man/bundle-add.1 +1 -1
  24. data/lib/bundler/man/bundle-binstubs.1 +1 -1
  25. data/lib/bundler/man/bundle-cache.1 +1 -1
  26. data/lib/bundler/man/bundle-check.1 +1 -1
  27. data/lib/bundler/man/bundle-clean.1 +1 -1
  28. data/lib/bundler/man/bundle-config.1 +3 -3
  29. data/lib/bundler/man/bundle-config.1.ronn +2 -2
  30. data/lib/bundler/man/bundle-doctor.1 +1 -1
  31. data/lib/bundler/man/bundle-exec.1 +1 -1
  32. data/lib/bundler/man/bundle-gem.1 +14 -1
  33. data/lib/bundler/man/bundle-gem.1.ronn +16 -0
  34. data/lib/bundler/man/bundle-info.1 +1 -1
  35. data/lib/bundler/man/bundle-init.1 +1 -1
  36. data/lib/bundler/man/bundle-inject.1 +1 -1
  37. data/lib/bundler/man/bundle-install.1 +1 -1
  38. data/lib/bundler/man/bundle-list.1 +1 -1
  39. data/lib/bundler/man/bundle-lock.1 +1 -1
  40. data/lib/bundler/man/bundle-open.1 +1 -1
  41. data/lib/bundler/man/bundle-outdated.1 +1 -1
  42. data/lib/bundler/man/bundle-platform.1 +1 -1
  43. data/lib/bundler/man/bundle-pristine.1 +1 -1
  44. data/lib/bundler/man/bundle-remove.1 +1 -1
  45. data/lib/bundler/man/bundle-show.1 +1 -1
  46. data/lib/bundler/man/bundle-update.1 +1 -1
  47. data/lib/bundler/man/bundle-viz.1 +1 -1
  48. data/lib/bundler/man/bundle.1 +1 -1
  49. data/lib/bundler/man/gemfile.5 +27 -1
  50. data/lib/bundler/man/gemfile.5.ronn +8 -0
  51. data/lib/bundler/plugin/api/source.rb +1 -0
  52. data/lib/bundler/resolver.rb +2 -4
  53. data/lib/bundler/rubygems_ext.rb +4 -0
  54. data/lib/bundler/rubygems_gem_installer.rb +20 -4
  55. data/lib/bundler/rubygems_integration.rb +26 -9
  56. data/lib/bundler/runtime.rb +2 -2
  57. data/lib/bundler/shared_helpers.rb +2 -3
  58. data/lib/bundler/source/git/git_proxy.rb +7 -4
  59. data/lib/bundler/source/git.rb +3 -1
  60. data/lib/bundler/source/rubygems.rb +52 -84
  61. data/lib/bundler/source/rubygems_aggregate.rb +1 -1
  62. data/lib/bundler/source.rb +1 -1
  63. data/lib/bundler/source_list.rb +7 -29
  64. data/lib/bundler/spec_set.rb +1 -1
  65. data/lib/bundler/templates/newgem/Gemfile.tt +5 -2
  66. data/lib/bundler/templates/newgem/Rakefile.tt +5 -1
  67. data/lib/bundler/templates/newgem/github/workflows/main.yml.tt +2 -2
  68. data/lib/bundler/templates/newgem/newgem.gemspec.tt +12 -12
  69. data/lib/bundler/templates/newgem/sig/newgem.rbs.tt +8 -0
  70. data/lib/bundler/templates/newgem/standard.yml.tt +2 -0
  71. data/lib/bundler/vendor/.document +1 -0
  72. data/lib/bundler/vendor/connection_pool/LICENSE +20 -0
  73. data/lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb +19 -21
  74. data/lib/bundler/vendor/connection_pool/lib/connection_pool/version.rb +1 -1
  75. data/lib/bundler/vendor/connection_pool/lib/connection_pool/wrapper.rb +57 -0
  76. data/lib/bundler/vendor/connection_pool/lib/connection_pool.rb +39 -74
  77. data/lib/bundler/vendor/fileutils/LICENSE.txt +22 -0
  78. data/lib/bundler/vendor/molinillo/LICENSE +9 -0
  79. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph.rb +2 -2
  80. data/lib/bundler/vendor/net-http-persistent/README.rdoc +82 -0
  81. data/lib/bundler/vendor/thor/LICENSE.md +20 -0
  82. data/lib/bundler/vendor/tsort/LICENSE.txt +22 -0
  83. data/lib/bundler/vendor/tsort/lib/tsort.rb +453 -0
  84. data/lib/bundler/vendor/uri/LICENSE.txt +22 -0
  85. data/lib/bundler/vendored_tsort.rb +4 -0
  86. data/lib/bundler/version.rb +1 -1
  87. data/lib/bundler/worker.rb +2 -2
  88. data/lib/bundler.rb +2 -1
  89. metadata +20 -7
  90. data/lib/bundler/vendor/connection_pool/lib/connection_pool/monotonic_time.rb +0 -66
@@ -73,7 +73,6 @@ module Bundler
73
73
  @lockfile_contents = String.new
74
74
  @locked_bundler_version = nil
75
75
  @locked_ruby_version = nil
76
- @locked_specs_incomplete_for_platform = false
77
76
  @new_platform = nil
78
77
 
79
78
  if lockfile && File.exist?(lockfile)
@@ -139,6 +138,8 @@ module Bundler
139
138
  @dependency_changes = converge_dependencies
140
139
  @local_changes = converge_locals
141
140
 
141
+ @locked_specs_incomplete_for_platform = !@locked_specs.for(requested_dependencies & expand_dependencies(locked_dependencies), true, true)
142
+
142
143
  @requires = compute_requires
143
144
  end
144
145
 
@@ -157,10 +158,6 @@ module Bundler
157
158
  end
158
159
  end
159
160
 
160
- def multisource_allowed?
161
- @multisource_allowed
162
- end
163
-
164
161
  def resolve_only_locally!
165
162
  @remote = false
166
163
  sources.local_only!
@@ -228,17 +225,22 @@ module Bundler
228
225
  end
229
226
  end
230
227
 
228
+ def locked_dependencies
229
+ @locked_deps.values
230
+ end
231
+
231
232
  def specs_for(groups)
232
- groups = requested_groups if groups.empty?
233
+ return specs if groups.empty?
233
234
  deps = dependencies_for(groups)
234
- materialize(expand_dependencies(deps))
235
+ materialize(deps)
235
236
  end
236
237
 
237
238
  def dependencies_for(groups)
238
239
  groups.map!(&:to_sym)
239
- current_dependencies.reject do |d|
240
+ deps = current_dependencies.reject do |d|
240
241
  (d.groups & groups).empty?
241
242
  end
243
+ expand_dependencies(deps)
242
244
  end
243
245
 
244
246
  # Resolve all the dependencies specified in Gemfile. It ensures that
@@ -362,44 +364,26 @@ module Bundler
362
364
  added.concat new_platforms.map {|p| "* platform: #{p}" }
363
365
  deleted.concat deleted_platforms.map {|p| "* platform: #{p}" }
364
366
 
365
- gemfile_sources = sources.lock_sources
366
-
367
- new_sources = gemfile_sources - @locked_sources
368
- deleted_sources = @locked_sources - gemfile_sources
369
-
370
- new_deps = @dependencies - @locked_deps.values
371
- deleted_deps = @locked_deps.values - @dependencies
372
-
373
- # Check if it is possible that the source is only changed thing
374
- if (new_deps.empty? && deleted_deps.empty?) && (!new_sources.empty? && !deleted_sources.empty?)
375
- new_sources.reject! {|source| (source.path? && source.path.exist?) || equivalent_rubygems_remotes?(source) }
376
- deleted_sources.reject! {|source| (source.path? && source.path.exist?) || equivalent_rubygems_remotes?(source) }
377
- end
378
-
379
- if @locked_sources != gemfile_sources
380
- if new_sources.any?
381
- added.concat new_sources.map {|source| "* source: #{source}" }
382
- end
383
-
384
- if deleted_sources.any?
385
- deleted.concat deleted_sources.map {|source| "* source: #{source}" }
386
- end
387
- end
367
+ new_deps = @dependencies - locked_dependencies
368
+ deleted_deps = locked_dependencies - @dependencies
388
369
 
389
370
  added.concat new_deps.map {|d| "* #{pretty_dep(d)}" } if new_deps.any?
390
- if deleted_deps.any?
391
- deleted.concat deleted_deps.map {|d| "* #{pretty_dep(d)}" }
392
- end
371
+ deleted.concat deleted_deps.map {|d| "* #{pretty_dep(d)}" } if deleted_deps.any?
393
372
 
394
373
  both_sources = Hash.new {|h, k| h[k] = [] }
395
374
  @dependencies.each {|d| both_sources[d.name][0] = d }
396
- @locked_deps.each {|name, d| both_sources[name][1] = d.source }
375
+ locked_dependencies.each {|d| both_sources[d.name][1] = d }
376
+
377
+ both_sources.each do |name, (dep, lock_dep)|
378
+ next if dep.nil? || lock_dep.nil?
397
379
 
398
- both_sources.each do |name, (dep, lock_source)|
399
- next if lock_source.nil? || (dep && lock_source.can_lock?(dep))
400
- gemfile_source_name = (dep && dep.source) || "no specified source"
401
- lockfile_source_name = lock_source
402
- changed << "* #{name} from `#{gemfile_source_name}` to `#{lockfile_source_name}`"
380
+ gemfile_source = dep.source || sources.default_source
381
+ lock_source = lock_dep.source || sources.default_source
382
+ next if lock_source.include?(gemfile_source)
383
+
384
+ gemfile_source_name = dep.source ? gemfile_source.identifier : "no specified source"
385
+ lockfile_source_name = lock_dep.source ? lock_source.identifier : "no specified source"
386
+ changed << "* #{name} from `#{lockfile_source_name}` to `#{gemfile_source_name}`"
403
387
  end
404
388
 
405
389
  reason = change_reason
@@ -560,7 +544,7 @@ module Bundler
560
544
 
561
545
  def dependencies_for_source_changed?(source, locked_source = source)
562
546
  deps_for_source = @dependencies.select {|s| s.source == source }
563
- locked_deps_for_source = @locked_deps.values.select {|dep| dep.source == locked_source }
547
+ locked_deps_for_source = locked_dependencies.select {|dep| dep.source == locked_source }
564
548
 
565
549
  deps_for_source.uniq.sort != locked_deps_for_source.sort
566
550
  end
@@ -643,25 +627,14 @@ module Bundler
643
627
  end
644
628
 
645
629
  def converge_dependencies
646
- frozen = Bundler.frozen_bundle?
647
- (@dependencies + @locked_deps.values).each do |dep|
648
- locked_source = @locked_deps[dep.name]
649
- # This is to make sure that if bundler is installing in deployment mode and
650
- # after locked_source and sources don't match, we still use locked_source.
651
- if frozen && !locked_source.nil? &&
652
- locked_source.respond_to?(:source) && locked_source.source.instance_of?(Source::Path) && locked_source.source.path.exist?
653
- dep.source = locked_source.source
654
- elsif dep.source
630
+ changes = false
631
+
632
+ @dependencies.each do |dep|
633
+ if dep.source
655
634
  dep.source = sources.get(dep.source)
656
635
  end
657
- end
658
636
 
659
- changes = false
660
- # We want to know if all match, but don't want to check all entries
661
- # This means we need to return false if any dependency doesn't match
662
- # the lock or doesn't exist in the lock.
663
- @dependencies.each do |dependency|
664
- unless locked_dep = @locked_deps[dependency.name]
637
+ unless locked_dep = @locked_deps[dep.name]
665
638
  changes = true
666
639
  next
667
640
  end
@@ -672,11 +645,11 @@ module Bundler
672
645
  # directive, the lockfile dependencies and resolved dependencies end up
673
646
  # with a mismatch on #type. Work around that by setting the type on the
674
647
  # dep from the lockfile.
675
- locked_dep.instance_variable_set(:@type, dependency.type)
648
+ locked_dep.instance_variable_set(:@type, dep.type)
676
649
 
677
650
  # We already know the name matches from the hash lookup
678
651
  # so we only need to check the requirement now
679
- changes ||= dependency.requirement != locked_dep.requirement
652
+ changes ||= dep.requirement != locked_dep.requirement
680
653
  end
681
654
 
682
655
  changes
@@ -686,39 +659,36 @@ module Bundler
686
659
  # commonly happen if the Gemfile has changed since the lockfile was last
687
660
  # generated
688
661
  def converge_locked_specs
689
- deps = []
690
-
691
- # Build a list of dependencies that are the same in the Gemfile
692
- # and Gemfile.lock. If the Gemfile modified a dependency, but
693
- # the gem in the Gemfile.lock still satisfies it, this is fine
694
- # too.
695
- @dependencies.each do |dep|
696
- locked_dep = @locked_deps[dep.name]
662
+ resolve = converge_specs(@locked_specs)
697
663
 
698
- # If the locked_dep doesn't match the dependency we're looking for then we ignore the locked_dep
699
- locked_dep = nil unless locked_dep == dep
664
+ diff = nil
700
665
 
701
- if in_locked_deps?(dep, locked_dep) || satisfies_locked_spec?(dep)
702
- deps << dep
703
- elsif dep.source.is_a?(Source::Path) && dep.current_platform? && (!locked_dep || dep.source != locked_dep.source)
704
- @locked_specs.each do |s|
705
- @unlock[:gems] << s.name if s.source == dep.source
706
- end
666
+ # Now, we unlock any sources that do not have anymore gems pinned to it
667
+ sources.all_sources.each do |source|
668
+ next unless source.respond_to?(:unlock!)
707
669
 
708
- dep.source.unlock! if dep.source.respond_to?(:unlock!)
709
- dep.source.specs.each {|s| @unlock[:gems] << s.name }
670
+ unless resolve.any? {|s| s.source == source }
671
+ diff ||= @locked_specs.to_a - resolve.to_a
672
+ source.unlock! if diff.any? {|s| s.source == source }
710
673
  end
711
674
  end
712
675
 
676
+ resolve
677
+ end
678
+
679
+ def converge_specs(specs)
680
+ deps = []
713
681
  converged = []
714
- @locked_specs.each do |s|
682
+ specs.each do |s|
715
683
  # Replace the locked dependency's source with the equivalent source from the Gemfile
716
684
  dep = @dependencies.find {|d| s.satisfies?(d) }
717
- s.source = (dep && dep.source) || sources.get(s.source) unless multisource_allowed?
718
685
 
719
- # Don't add a spec to the list if its source is expired. For example,
720
- # if you change a Git gem to RubyGems.
721
- next if s.source.nil?
686
+ if dep && (!dep.source || s.source.include?(dep.source))
687
+ deps << dep
688
+ end
689
+
690
+ s.source = (dep && dep.source) || sources.get(s.source) || sources.default_source unless Bundler.frozen_bundle?
691
+
722
692
  next if @unlock[:sources].include?(s.source.name)
723
693
 
724
694
  # If the spec is from a path source and it doesn't exist anymore
@@ -731,7 +701,7 @@ module Bundler
731
701
  rescue PathError, GitError
732
702
  # if we won't need the source (according to the lockfile),
733
703
  # don't error if the path/git source isn't available
734
- next if @locked_specs.
704
+ next if specs.
735
705
  for(requested_dependencies, false, true).
736
706
  none? {|locked_spec| locked_spec.source == s.source }
737
707
 
@@ -747,36 +717,15 @@ module Bundler
747
717
  s.dependencies.replace(new_spec.dependencies)
748
718
  end
749
719
 
750
- converged << s
751
- end
752
-
753
- resolve = SpecSet.new(converged)
754
- @locked_specs_incomplete_for_platform = !resolve.for(expand_dependencies(requested_dependencies & deps), true, true)
755
- resolve = SpecSet.new(resolve.for(expand_dependencies(deps, true), false, false).reject{|s| @unlock[:gems].include?(s.name) })
756
- diff = nil
757
-
758
- # Now, we unlock any sources that do not have anymore gems pinned to it
759
- sources.all_sources.each do |source|
760
- next unless source.respond_to?(:unlock!)
761
-
762
- unless resolve.any? {|s| s.source == source }
763
- diff ||= @locked_specs.to_a - resolve.to_a
764
- source.unlock! if diff.any? {|s| s.source == source }
720
+ if dep.nil? && requested_dependencies.find {|d| s.name == d.name }
721
+ @unlock[:gems] << s.name
722
+ else
723
+ converged << s
765
724
  end
766
725
  end
767
726
 
768
- resolve
769
- end
770
-
771
- def in_locked_deps?(dep, locked_dep)
772
- # Because the lockfile can't link a dep to a specific remote, we need to
773
- # treat sources as equivalent anytime the locked dep has all the remotes
774
- # that the Gemfile dep does.
775
- locked_dep && locked_dep.source && dep.source && locked_dep.source.include?(dep.source)
776
- end
777
-
778
- def satisfies_locked_spec?(dep)
779
- @locked_specs[dep].any? {|s| s.satisfies?(dep) && (!dep.source || s.source.include?(dep.source)) }
727
+ resolve = SpecSet.new(converged)
728
+ SpecSet.new(resolve.for(expand_dependencies(deps, true), false, false).reject{|s| @unlock[:gems].include?(s.name) })
780
729
  end
781
730
 
782
731
  def metadata_dependencies
@@ -869,22 +818,11 @@ module Bundler
869
818
 
870
819
  def additional_base_requirements_for_resolve
871
820
  return [] unless @locked_gems && unlocking? && !sources.expired_sources?(@locked_gems.sources)
872
- dependencies_by_name = dependencies.inject({}) {|memo, dep| memo.update(dep.name => dep) }
873
- @locked_gems.specs.reduce({}) do |requirements, locked_spec|
821
+ converge_specs(@locked_gems.specs).map do |locked_spec|
874
822
  name = locked_spec.name
875
- dependency = dependencies_by_name[name]
876
- next requirements if @locked_gems.dependencies[name] != dependency
877
- next requirements if dependency && dependency.source.is_a?(Source::Path)
878
823
  dep = Gem::Dependency.new(name, ">= #{locked_spec.version}")
879
- requirements[name] = DepProxy.get_proxy(dep, locked_spec.platform)
880
- requirements
881
- end.values
882
- end
883
-
884
- def equivalent_rubygems_remotes?(source)
885
- return false unless source.is_a?(Source::Rubygems)
886
-
887
- Bundler.settings[:allow_deployment_source_credential_changes] && source.equivalent_remotes?(sources.rubygems_remotes)
824
+ DepProxy.get_proxy(dep, locked_spec.platform)
825
+ end
888
826
  end
889
827
 
890
828
  def source_map
@@ -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
 
@@ -278,8 +280,17 @@ module Bundler
278
280
  warn_deprecated_git_source(:github, <<-'RUBY'.strip, 'Change any "reponame" :github sources to "username/reponame".')
279
281
  "https://github.com/#{repo_name}.git"
280
282
  RUBY
281
- repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?("/")
282
- "https://github.com/#{repo_name}.git"
283
+ if repo_name =~ GITHUB_PULL_REQUEST_URL
284
+ {
285
+ "git" => "https://github.com/#{$1}.git",
286
+ "branch" => "refs/pull/#{$2}/head",
287
+ "ref" => nil,
288
+ "tag" => nil,
289
+ }
290
+ else
291
+ repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?("/")
292
+ "https://github.com/#{repo_name}.git"
293
+ end
283
294
  end
284
295
 
285
296
  git_source(:gist) do |repo_name|
@@ -365,7 +376,11 @@ repo_name ||= user_name
365
376
 
366
377
  git_name = (git_names & opts.keys).last
367
378
  if @git_sources[git_name]
368
- opts["git"] = @git_sources[git_name].call(opts[git_name])
379
+ git_opts = @git_sources[git_name].call(opts[git_name])
380
+ git_opts = { "git" => git_opts } if git_opts.is_a?(String)
381
+ opts.merge!(git_opts) do |key, _gemfile_value, _git_source_value|
382
+ raise GemfileError, %(The :#{key} option can't be used with `#{git_name}: #{opts[git_name].inspect}`)
383
+ end
369
384
  end
370
385
 
371
386
  %w[git path].each do |type|
@@ -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)
@@ -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
@@ -63,34 +63,6 @@ module Bundler
63
63
  def request_issue_report_for(e)
64
64
  Bundler.ui.error <<-EOS.gsub(/^ {8}/, ""), nil, nil
65
65
  --- ERROR REPORT TEMPLATE -------------------------------------------------------
66
- # Error Report
67
-
68
- ## Questions
69
-
70
- Please fill out answers to these questions, it'll help us figure out
71
- why things are going wrong.
72
-
73
- - **What did you do?**
74
-
75
- I ran the command `#{$PROGRAM_NAME} #{ARGV.join(" ")}`
76
-
77
- - **What did you expect to happen?**
78
-
79
- I expected Bundler to...
80
-
81
- - **What happened instead?**
82
-
83
- Instead, what happened was...
84
-
85
- - **Have you tried any solutions posted on similar issues in our issue tracker, stack overflow, or google?**
86
-
87
- I tried...
88
-
89
- - **Have you read our issues document, https://github.com/rubygems/rubygems/blob/master/bundler/doc/contributing/ISSUES.md?**
90
-
91
- ...
92
-
93
- ## Backtrace
94
66
 
95
67
  ```
96
68
  #{e.class}: #{e.message}
@@ -109,8 +81,7 @@ module Bundler
109
81
  First, try this link to see if there are any existing issue reports for this error:
110
82
  #{issues_url(e)}
111
83
 
112
- If there aren't any reports for this error yet, please copy and paste the report template above into a new issue. Don't forget to anonymize any private data! The new issue form is located at:
113
- https://github.com/rubygems/rubygems/issues/new?labels=Bundler&template=bundler-related-issue.md
84
+ If there aren't any reports for this error yet, please fill in the new issue form located at #{new_issue_url}, and copy and paste the report template above in there.
114
85
  EOS
115
86
  end
116
87
 
@@ -121,6 +92,10 @@ module Bundler
121
92
  "https://github.com/rubygems/rubygems/search?q=" \
122
93
  "#{CGI.escape(message)}&type=Issues"
123
94
  end
95
+
96
+ def new_issue_url
97
+ "https://github.com/rubygems/rubygems/issues/new?labels=Bundler&template=bundler-related-issue.md"
98
+ end
124
99
  end
125
100
 
126
101
  def self.with_friendly_errors
@@ -98,10 +98,7 @@ module Bundler
98
98
  built_gem_path ||= build_gem
99
99
  cmd = [*gem_command, "install", built_gem_path.to_s]
100
100
  cmd << "--local" if local
101
- _, status = sh_with_status(cmd)
102
- unless status.success?
103
- raise "Couldn't install gem, run `gem install #{built_gem_path}' for more detailed output"
104
- end
101
+ sh(cmd)
105
102
  Bundler.ui.confirm "#{name} (#{version}) installed."
106
103
  end
107
104
 
@@ -110,7 +107,7 @@ module Bundler
110
107
  SharedHelpers.filesystem_access(File.join(base, "checksums")) {|p| FileUtils.mkdir_p(p) }
111
108
  file_name = "#{File.basename(built_gem_path)}.sha512"
112
109
  require "digest/sha2"
113
- checksum = Digest::SHA512.new.hexdigest(built_gem_path.to_s)
110
+ checksum = ::Digest::SHA512.new.hexdigest(built_gem_path.to_s)
114
111
  target = File.join(base, "checksums", file_name)
115
112
  File.write(target, checksum)
116
113
  Bundler.ui.confirm "#{name} #{version} checksum written to checksums/#{file_name}."
@@ -132,8 +129,8 @@ module Bundler
132
129
 
133
130
  def git_push(remote = nil)
134
131
  remote ||= default_remote
135
- perform_git_push "#{remote} refs/heads/#{current_branch}"
136
- perform_git_push "#{remote} refs/tags/#{version_tag}"
132
+ sh("git push #{remote} refs/heads/#{current_branch}".shellsplit)
133
+ sh("git push #{remote} refs/tags/#{version_tag}".shellsplit)
137
134
  Bundler.ui.confirm "Pushed git commits and release tag."
138
135
  end
139
136
 
@@ -161,13 +158,6 @@ module Bundler
161
158
  allowed_push_host || env_rubygems_host || "rubygems.org"
162
159
  end
163
160
 
164
- def perform_git_push(options = "")
165
- cmd = "git push #{options}"
166
- out, status = sh_with_status(cmd.shellsplit)
167
- return if status.success?
168
- raise "Couldn't git push. `#{cmd}' failed with the following output:\n\n#{out}\n"
169
- end
170
-
171
161
  def already_tagged?
172
162
  return false unless sh(%w[git tag]).split(/\n/).include?(version_tag)
173
163
  Bundler.ui.confirm "Tag #{version_tag} has already been created."
@@ -218,8 +208,7 @@ module Bundler
218
208
  def sh(cmd, &block)
219
209
  out, status = sh_with_status(cmd, &block)
220
210
  unless status.success?
221
- cmd = cmd.shelljoin if cmd.respond_to?(:shelljoin)
222
- raise(out.empty? ? "Running `#{cmd}` failed. Run this command directly for more detailed output." : out)
211
+ raise("Running `#{cmd.shelljoin}` failed with the following output:\n\n#{out}\n")
223
212
  end
224
213
  out
225
214
  end
@@ -38,8 +38,24 @@ module Bundler
38
38
  identifier.hash
39
39
  end
40
40
 
41
+ ##
42
+ # Does this locked specification satisfy +dependency+?
43
+ #
44
+ # NOTE: Rubygems default requirement is ">= 0", which doesn't match
45
+ # prereleases of 0 versions, like "0.0.0.dev" or "0.0.0.SNAPSHOT". However,
46
+ # bundler users expect those to work. We need to make sure that Gemfile
47
+ # dependencies without explicit requirements (which use ">= 0" under the
48
+ # hood by default) are still valid for locked specs using this kind of
49
+ # versions. The method implements an ad-hoc fix for that. A better solution
50
+ # might be to change default rubygems requirement of dependencies to be ">=
51
+ # 0.A" but that's a major refactoring likely to break things. Hopefully we
52
+ # can attempt it in the future.
53
+ #
54
+
41
55
  def satisfies?(dependency)
42
- @name == dependency.name && dependency.requirement.satisfied_by?(Gem::Version.new(@version))
56
+ effective_requirement = dependency.requirement == Gem::Requirement.default ? Gem::Requirement.new(">= 0.A") : dependency.requirement
57
+
58
+ @name == dependency.name && effective_requirement.satisfied_by?(Gem::Version.new(@version))
43
59
  end
44
60
 
45
61
  def to_lock
@@ -86,6 +86,7 @@ module Bundler
86
86
 
87
87
  def warn_for_outdated_bundler_version
88
88
  return unless bundler_version
89
+ return if bundler_version.segments.last == "dev"
89
90
  prerelease_text = bundler_version.prerelease? ? " --pre" : ""
90
91
  current_version = Gem::Version.create(Bundler::VERSION)
91
92
  return unless current_version < bundler_version
@@ -1,7 +1,7 @@
1
1
  .\" generated with Ronn/v0.7.3
2
2
  .\" http://github.com/rtomayko/ronn/tree/0.7.3
3
3
  .
4
- .TH "BUNDLE\-ADD" "1" "June 2021" "" ""
4
+ .TH "BUNDLE\-ADD" "1" "December 2021" "" ""
5
5
  .
6
6
  .SH "NAME"
7
7
  \fBbundle\-add\fR \- Add gem to the Gemfile and run bundle install
@@ -1,7 +1,7 @@
1
1
  .\" generated with Ronn/v0.7.3
2
2
  .\" http://github.com/rtomayko/ronn/tree/0.7.3
3
3
  .
4
- .TH "BUNDLE\-BINSTUBS" "1" "June 2021" "" ""
4
+ .TH "BUNDLE\-BINSTUBS" "1" "December 2021" "" ""
5
5
  .
6
6
  .SH "NAME"
7
7
  \fBbundle\-binstubs\fR \- Install the binstubs of the listed gems
@@ -1,7 +1,7 @@
1
1
  .\" generated with Ronn/v0.7.3
2
2
  .\" http://github.com/rtomayko/ronn/tree/0.7.3
3
3
  .
4
- .TH "BUNDLE\-CACHE" "1" "June 2021" "" ""
4
+ .TH "BUNDLE\-CACHE" "1" "December 2021" "" ""
5
5
  .
6
6
  .SH "NAME"
7
7
  \fBbundle\-cache\fR \- Package your needed \fB\.gem\fR files into your application
@@ -1,7 +1,7 @@
1
1
  .\" generated with Ronn/v0.7.3
2
2
  .\" http://github.com/rtomayko/ronn/tree/0.7.3
3
3
  .
4
- .TH "BUNDLE\-CHECK" "1" "June 2021" "" ""
4
+ .TH "BUNDLE\-CHECK" "1" "December 2021" "" ""
5
5
  .
6
6
  .SH "NAME"
7
7
  \fBbundle\-check\fR \- Verifies if dependencies are satisfied by installed gems
@@ -1,7 +1,7 @@
1
1
  .\" generated with Ronn/v0.7.3
2
2
  .\" http://github.com/rtomayko/ronn/tree/0.7.3
3
3
  .
4
- .TH "BUNDLE\-CLEAN" "1" "June 2021" "" ""
4
+ .TH "BUNDLE\-CLEAN" "1" "December 2021" "" ""
5
5
  .
6
6
  .SH "NAME"
7
7
  \fBbundle\-clean\fR \- Cleans up unused gems in your bundler directory