bundler 2.2.29 → 2.2.30

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of bundler might be problematic. Click here for more details.

Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +20 -1
  3. data/README.md +1 -1
  4. data/lib/bundler/build_metadata.rb +2 -2
  5. data/lib/bundler/cli/info.rb +11 -4
  6. data/lib/bundler/cli/issue.rb +4 -3
  7. data/lib/bundler/compact_index_client.rb +2 -2
  8. data/lib/bundler/definition.rb +10 -6
  9. data/lib/bundler/digest.rb +71 -0
  10. data/lib/bundler/errors.rb +18 -2
  11. data/lib/bundler/fetcher.rb +2 -1
  12. data/lib/bundler/friendly_errors.rb +5 -30
  13. data/lib/bundler/gem_helper.rb +5 -16
  14. data/lib/bundler/rubygems_ext.rb +4 -0
  15. data/lib/bundler/rubygems_gem_installer.rb +20 -4
  16. data/lib/bundler/rubygems_integration.rb +26 -9
  17. data/lib/bundler/runtime.rb +1 -1
  18. data/lib/bundler/source/git.rb +3 -1
  19. data/lib/bundler/source/rubygems.rb +35 -71
  20. data/lib/bundler/vendor/connection_pool/LICENSE +20 -0
  21. data/lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb +19 -21
  22. data/lib/bundler/vendor/connection_pool/lib/connection_pool/version.rb +1 -1
  23. data/lib/bundler/vendor/connection_pool/lib/connection_pool/wrapper.rb +57 -0
  24. data/lib/bundler/vendor/connection_pool/lib/connection_pool.rb +39 -74
  25. data/lib/bundler/vendor/fileutils/LICENSE.txt +22 -0
  26. data/lib/bundler/vendor/molinillo/LICENSE +9 -0
  27. data/lib/bundler/vendor/net-http-persistent/README.rdoc +82 -0
  28. data/lib/bundler/vendor/thor/LICENSE.md +20 -0
  29. data/lib/bundler/vendor/uri/LICENSE.txt +22 -0
  30. data/lib/bundler/version.rb +1 -1
  31. data/lib/bundler/worker.rb +2 -2
  32. data/lib/bundler.rb +2 -1
  33. metadata +14 -7
  34. data/lib/bundler/vendor/connection_pool/lib/connection_pool/monotonic_time.rb +0 -66
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7069421e0020f0587932b3789c8f14b8aadb042d325355fc4072d56c083743c0
4
- data.tar.gz: 5bd5f85c8a0c755f41e8a4be840f1b534700636390e5b6c64123693c3096c365
3
+ metadata.gz: e20b3afe2b252225aaf6d7e99c4aeb2e476e4e6e928e42be1b6b03b3cba5f68a
4
+ data.tar.gz: e398755ca8b609ea5b6cadbc205e48fad15ddf369932964fa293c1532f42b8b1
5
5
  SHA512:
6
- metadata.gz: b35d34e74e52b7522a6cfe1734b741b707685c7fb8811d82de51c2829024f4c14c4695e26def71f3f5aaa2473bc4f7301cd601d490a9d60e38f63b68936638a9
7
- data.tar.gz: 319d8e58acf68df04ac61973b808df92bacf8793cd2bf0a301ddcd446c62c1bf5e1519de730c206fe8a9dbb447dbc48389d0900cdda16475135d93dcbe9d769d
6
+ metadata.gz: 8fdddc111238b3365bfb45466d8c4239b3f5b7a005cb477d675d00be9585e7ae2e7feb8669e979a5695dea8be31f6c87670e7fe72fd7d18b6da4e27775cd650f
7
+ data.tar.gz: 51dec18f2ade00c902d9e45fcbee5dd7010d96d06edd6daf9856279fd9267651020bdc49f8d95bae853627e060f64444f25675fd633e975158dee3c724c6d908
data/CHANGELOG.md CHANGED
@@ -1,3 +1,22 @@
1
+ # 2.2.30 (October 26, 2021)
2
+
3
+ ## Enhancements:
4
+
5
+ - Add a custom SHA1 digest implementation to no longer depend on the digest gem before we know which version to activate [#4989](https://github.com/rubygems/rubygems/pull/4989)
6
+ - Ensure vendored gems have licenses [#4998](https://github.com/rubygems/rubygems/pull/4998)
7
+ - Update broken link in Bundler::Fetcher::CertificateFailureError [#4987](https://github.com/rubygems/rubygems/pull/4987)
8
+ - Give better errors for some permission issues [#4965](https://github.com/rubygems/rubygems/pull/4965)
9
+ - Print better errors when `bundler/gem_tasks` fail [#4872](https://github.com/rubygems/rubygems/pull/4872)
10
+ - Fix `bundle install` to reinstall deleted gems [#4974](https://github.com/rubygems/rubygems/pull/4974)
11
+ - Unify issue template and ISSUES.md document [#4980](https://github.com/rubygems/rubygems/pull/4980)
12
+ - Bump vendored connection_pool to 2.2.5 [#4738](https://github.com/rubygems/rubygems/pull/4738)
13
+
14
+ ## Bug fixes:
15
+
16
+ - Fix error message pointing to non existing file when using a global gem cache [#4999](https://github.com/rubygems/rubygems/pull/4999)
17
+ - Fix install crash when lockfile has missing dependencies for the current platform [#4941](https://github.com/rubygems/rubygems/pull/4941)
18
+ - Make `bundle info` show a proper warning every time it finds a deleted gem [#4971](https://github.com/rubygems/rubygems/pull/4971)
19
+
1
20
  # 2.2.29 (October 8, 2021)
2
21
 
3
22
  ## Enhancements:
@@ -107,7 +126,7 @@
107
126
  - Fix `bundle doctor` crashing when finding a broken symlink [#4707](https://github.com/rubygems/rubygems/pull/4707)
108
127
  - Fix incorrect re-resolve edge case [#4700](https://github.com/rubygems/rubygems/pull/4700)
109
128
  - Fix some gems being unintentionally locked under multiple lockfile sections [#4701](https://github.com/rubygems/rubygems/pull/4701)
110
- - Fix `--conservative` flag unexpectedly updating indirect dependencies [#4692](https://github.com/rubygems/rubygems/pull/4692)
129
+ - Fix `--conservative` flag unexpectedly updating indirect dependencies. NOTE: As part of this bug fix, some undocumented, unintentional code causing `bundle update --source <gem>` to update conservatively was fixed. Use the documented `bundle update --conservative <gem>` instead [#4692](https://github.com/rubygems/rubygems/pull/4692)
111
130
 
112
131
  # 2.2.21 (June 23, 2021)
113
132
 
data/README.md CHANGED
@@ -32,7 +32,7 @@ See [bundler.io](https://bundler.io) for the full documentation.
32
32
 
33
33
  For help with common problems, see [TROUBLESHOOTING](doc/TROUBLESHOOTING.md).
34
34
 
35
- Still stuck? Try [filing an issue](doc/contributing/ISSUES.md).
35
+ Still stuck? Try [filing an issue](https://github.com/rubygems/rubygems/issues/new?labels=Bundler&template=bundler-related-issue.md).
36
36
 
37
37
  ### Other questions
38
38
 
@@ -4,8 +4,8 @@ module Bundler
4
4
  # Represents metadata from when the Bundler gem was built.
5
5
  module BuildMetadata
6
6
  # begin ivars
7
- @built_at = "2021-10-08".freeze
8
- @git_commit_sha = "4440b035ef".freeze
7
+ @built_at = "2021-10-26".freeze
8
+ @git_commit_sha = "e8df9bea62".freeze
9
9
  @release = true
10
10
  # end ivars
11
11
 
@@ -40,12 +40,13 @@ module Bundler
40
40
  end
41
41
 
42
42
  def print_gem_path(spec)
43
- if spec.name == "bundler"
43
+ name = spec.name
44
+ if name == "bundler"
44
45
  path = File.expand_path("../../../..", __FILE__)
45
46
  else
46
47
  path = spec.full_gem_path
47
- unless File.directory?(path)
48
- return Bundler.ui.warn "The gem #{gem_name} has been deleted. It was installed at: #{path}"
48
+ if spec.deleted_gem?
49
+ return Bundler.ui.warn "The gem #{name} has been deleted. It was installed at: #{path}"
49
50
  end
50
51
  end
51
52
 
@@ -54,8 +55,9 @@ module Bundler
54
55
 
55
56
  def print_gem_info(spec)
56
57
  metadata = spec.metadata
58
+ name = spec.name
57
59
  gem_info = String.new
58
- gem_info << " * #{spec.name} (#{spec.version}#{spec.git_version})\n"
60
+ gem_info << " * #{name} (#{spec.version}#{spec.git_version})\n"
59
61
  gem_info << "\tSummary: #{spec.summary}\n" if spec.summary
60
62
  gem_info << "\tHomepage: #{spec.homepage}\n" if spec.homepage
61
63
  gem_info << "\tDocumentation: #{metadata["documentation_uri"]}\n" if metadata.key?("documentation_uri")
@@ -67,6 +69,11 @@ module Bundler
67
69
  gem_info << "\tMailing List: #{metadata["mailing_list_uri"]}\n" if metadata.key?("mailing_list_uri")
68
70
  gem_info << "\tPath: #{spec.full_gem_path}\n"
69
71
  gem_info << "\tDefault Gem: yes" if spec.respond_to?(:default_gem?) && spec.default_gem?
72
+
73
+ if spec.deleted_gem?
74
+ return Bundler.ui.warn "The gem #{name} has been deleted. Gemspec information is still available though:\n#{gem_info}"
75
+ end
76
+
70
77
  Bundler.ui.info gem_info
71
78
  end
72
79
  end
@@ -20,9 +20,10 @@ module Bundler
20
20
 
21
21
  Hopefully the troubleshooting steps above resolved your problem! If things
22
22
  still aren't working the way you expect them to, please let us know so
23
- that we can diagnose and help fix the problem you're having. Please
24
- view the Filing Issues guide for more information:
25
- https://github.com/rubygems/rubygems/blob/master/bundler/doc/contributing/ISSUES.md
23
+ that we can diagnose and help fix the problem you're having, by filling
24
+ in the new issue form located at
25
+ https://github.com/rubygems/rubygems/issues/new?labels=Bundler&template=bundler-related-issue.md,
26
+ and copy and pasting the information below.
26
27
 
27
28
  EOS
28
29
 
@@ -5,7 +5,7 @@ require "set"
5
5
 
6
6
  module Bundler
7
7
  class CompactIndexClient
8
- DEBUG_MUTEX = Mutex.new
8
+ DEBUG_MUTEX = Thread::Mutex.new
9
9
  def self.debug
10
10
  return unless ENV["DEBUG_COMPACT_INDEX"]
11
11
  DEBUG_MUTEX.synchronize { warn("[#{self}] #{yield}") }
@@ -25,7 +25,7 @@ module Bundler
25
25
  @endpoints = Set.new
26
26
  @info_checksums_by_name = {}
27
27
  @parsed_checksums = false
28
- @mutex = Mutex.new
28
+ @mutex = Thread::Mutex.new
29
29
  end
30
30
 
31
31
  def execution_mode=(block)
@@ -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(expand_dependencies(requested_dependencies & locked_dependencies), true, true)
142
+
142
143
  @requires = compute_requires
143
144
  end
144
145
 
@@ -228,6 +229,10 @@ module Bundler
228
229
  end
229
230
  end
230
231
 
232
+ def locked_dependencies
233
+ @locked_deps.values
234
+ end
235
+
231
236
  def specs_for(groups)
232
237
  groups = requested_groups if groups.empty?
233
238
  deps = dependencies_for(groups)
@@ -367,8 +372,8 @@ module Bundler
367
372
  new_sources = gemfile_sources - @locked_sources
368
373
  deleted_sources = @locked_sources - gemfile_sources
369
374
 
370
- new_deps = @dependencies - @locked_deps.values
371
- deleted_deps = @locked_deps.values - @dependencies
375
+ new_deps = @dependencies - locked_dependencies
376
+ deleted_deps = locked_dependencies - @dependencies
372
377
 
373
378
  # Check if it is possible that the source is only changed thing
374
379
  if (new_deps.empty? && deleted_deps.empty?) && (!new_sources.empty? && !deleted_sources.empty?)
@@ -560,7 +565,7 @@ module Bundler
560
565
 
561
566
  def dependencies_for_source_changed?(source, locked_source = source)
562
567
  deps_for_source = @dependencies.select {|s| s.source == source }
563
- locked_deps_for_source = @locked_deps.values.select {|dep| dep.source == locked_source }
568
+ locked_deps_for_source = locked_dependencies.select {|dep| dep.source == locked_source }
564
569
 
565
570
  deps_for_source.uniq.sort != locked_deps_for_source.sort
566
571
  end
@@ -644,7 +649,7 @@ module Bundler
644
649
 
645
650
  def converge_dependencies
646
651
  frozen = Bundler.frozen_bundle?
647
- (@dependencies + @locked_deps.values).each do |dep|
652
+ (@dependencies + locked_dependencies).each do |dep|
648
653
  locked_source = @locked_deps[dep.name]
649
654
  # This is to make sure that if bundler is installing in deployment mode and
650
655
  # after locked_source and sources don't match, we still use locked_source.
@@ -751,7 +756,6 @@ module Bundler
751
756
  end
752
757
 
753
758
  resolve = SpecSet.new(converged)
754
- @locked_specs_incomplete_for_platform = !resolve.for(expand_dependencies(requested_dependencies & deps), true, true)
755
759
  resolve = SpecSet.new(resolve.for(expand_dependencies(deps, true), false, false).reject{|s| @unlock[:gems].include?(s.name) })
756
760
  diff = nil
757
761
 
@@ -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
@@ -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(%W[git push #{remote} refs/heads/#{current_branch}])
133
+ sh(%W[git push #{remote} refs/tags/#{version_tag}])
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
@@ -85,6 +85,10 @@ module Gem
85
85
  dependencies - development_dependencies
86
86
  end
87
87
 
88
+ def deleted_gem?
89
+ !default_gem? && !File.directory?(full_gem_path)
90
+ end
91
+
88
92
  private
89
93
 
90
94
  def dependencies_to_gemfile(dependencies, group = nil)
@@ -16,10 +16,12 @@ module Bundler
16
16
  spec.loaded_from = spec_file
17
17
 
18
18
  # Completely remove any previous gem files
19
- FileUtils.rm_rf gem_dir
20
- FileUtils.rm_rf spec.extension_dir
19
+ strict_rm_rf gem_dir
20
+ strict_rm_rf spec.extension_dir
21
21
 
22
- FileUtils.mkdir_p gem_dir, :mode => 0o755
22
+ SharedHelpers.filesystem_access(gem_dir, :create) do
23
+ FileUtils.mkdir_p gem_dir, :mode => 0o755
24
+ end
23
25
 
24
26
  extract_files
25
27
 
@@ -31,7 +33,10 @@ module Bundler
31
33
  generate_plugins
32
34
 
33
35
  write_spec
34
- write_cache_file
36
+
37
+ SharedHelpers.filesystem_access("#{gem_home}/cache", :write) do
38
+ write_cache_file
39
+ end
35
40
 
36
41
  say spec.post_install_message unless spec.post_install_message.nil?
37
42
 
@@ -87,6 +92,17 @@ module Bundler
87
92
 
88
93
  private
89
94
 
95
+ def strict_rm_rf(dir)
96
+ # FileUtils.rm_rf should probably rise in case of permission issues like
97
+ # `rm -rf` does. However, it fails to delete the folder silently due to
98
+ # https://github.com/ruby/fileutils/issues/57. It should probably be fixed
99
+ # inside `fileutils` but for now I`m checking whether the folder was
100
+ # removed after it completes, and raising otherwise.
101
+ FileUtils.rm_rf dir
102
+
103
+ raise PermissionError.new(dir, :delete) if File.directory?(dir)
104
+ end
105
+
90
106
  def validate_bundler_checksum(checksum)
91
107
  return true if Bundler.settings[:disable_checksum_validation]
92
108
  return true unless checksum
@@ -86,16 +86,12 @@ module Bundler
86
86
  def spec_missing_extensions?(spec, default = true)
87
87
  return spec.missing_extensions? if spec.respond_to?(:missing_extensions?)
88
88
 
89
- return false if spec_default_gem?(spec)
89
+ return false if spec.default_gem?
90
90
  return false if spec.extensions.empty?
91
91
 
92
92
  default
93
93
  end
94
94
 
95
- def spec_default_gem?(spec)
96
- spec.respond_to?(:default_gem?) && spec.default_gem?
97
- end
98
-
99
95
  def spec_matches_for_glob(spec, glob)
100
96
  return spec.matches_for_glob(glob) if spec.respond_to?(:matches_for_glob)
101
97
 
@@ -504,14 +500,15 @@ module Bundler
504
500
  end
505
501
 
506
502
  def fetch_specs(remote, name)
503
+ require "rubygems/remote_fetcher"
507
504
  path = remote.uri.to_s + "#{name}.#{Gem.marshal_version}.gz"
508
505
  fetcher = gem_remote_fetcher
509
506
  fetcher.headers = { "X-Gemfile-Source" => remote.original_uri.to_s } if remote.original_uri
510
507
  string = fetcher.fetch_path(path)
511
508
  Bundler.load_marshal(string)
512
- rescue Gem::RemoteFetcher::FetchError => e
509
+ rescue Gem::RemoteFetcher::FetchError
513
510
  # it's okay for prerelease to fail
514
- raise e unless name == "prerelease_specs"
511
+ raise unless name == "prerelease_specs"
515
512
  end
516
513
 
517
514
  def fetch_all_remote_specs(remote)
@@ -521,12 +518,32 @@ module Bundler
521
518
  specs.concat(pres)
522
519
  end
523
520
 
524
- def download_gem(spec, uri, path)
521
+ def download_gem(spec, uri, cache_dir)
522
+ require "rubygems/remote_fetcher"
525
523
  uri = Bundler.settings.mirror_for(uri)
526
524
  fetcher = gem_remote_fetcher
527
525
  fetcher.headers = { "X-Gemfile-Source" => spec.remote.original_uri.to_s } if spec.remote.original_uri
528
526
  Bundler::Retry.new("download gem from #{uri}").attempts do
529
- fetcher.download(spec, uri, path)
527
+ gem_file_name = spec.file_name
528
+ local_gem_path = File.join cache_dir, gem_file_name
529
+ return if File.exist? local_gem_path
530
+
531
+ begin
532
+ remote_gem_path = uri + "gems/#{gem_file_name}"
533
+ remote_gem_path = remote_gem_path.to_s if provides?("< 3.2.0.rc.1")
534
+
535
+ SharedHelpers.filesystem_access(local_gem_path) do
536
+ fetcher.cache_update_path remote_gem_path, local_gem_path
537
+ end
538
+ rescue Gem::RemoteFetcher::FetchError
539
+ raise if spec.original_platform == spec.platform
540
+
541
+ original_gem_file_name = "#{spec.original_name}.gem"
542
+ raise if gem_file_name == original_gem_file_name
543
+
544
+ gem_file_name = original_gem_file_name
545
+ retry
546
+ end
530
547
  end
531
548
  rescue Gem::RemoteFetcher::FetchError => e
532
549
  raise Bundler::HTTPError, "Could not download gem from #{uri} due to underlying error <#{e.message}>"
@@ -291,7 +291,7 @@ module Bundler
291
291
  return unless activated_spec = Bundler.rubygems.loaded_specs(spec.name)
292
292
  return if activated_spec.version == spec.version
293
293
 
294
- suggestion = if Bundler.rubygems.spec_default_gem?(activated_spec)
294
+ suggestion = if activated_spec.default_gem?
295
295
  "Since #{spec.name} is a default gem, you can either remove your dependency on it" \
296
296
  " or try updating to a newer version of bundler that supports #{spec.name} as a default gem."
297
297
  else
@@ -307,7 +307,9 @@ module Bundler
307
307
  # If there is no URI scheme, assume it is an ssh/git URI
308
308
  input = uri
309
309
  end
310
- SharedHelpers.digest(:SHA1).hexdigest(input)
310
+ # We use SHA1 here for historical reason and to preserve backward compatibility.
311
+ # But a transition to a simpler mangling algorithm would be welcome.
312
+ Bundler::Digest.sha1(input)
311
313
  end
312
314
 
313
315
  def cached_revision