1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

[rubygems/rubygems] Fix misleading error if compact index cannot be copied

Previously if `~/.bundle/cache/compact_index/rubygems.org.*/version`
were owned by root with read-only access, `bundle install` would fail
with a misleading error message. For example:

```
There was an error while trying to write to `/tmp/bundler-compact-index-20220711-1823-npllre/versions`. It is
likely that you need to grant write permissions for that path.
```

This happened because the EACCESS error was caught by
`SharedHelpers.filesystem_access`, which makes it look like the target
directory is at fault instead of the source.

We can't simply drop this guard because that causes the opposite
problem: the permission error appears to come from the source instead of
the target, since `CompactIndexClient::Cache#lines` also wraps read
access errors.

Instead, bring a minimal implementation of `FileUtils.cp` and nest calls
to `SharedHelpers.filesystem_access` properly.

https://github.com/rubygems/rubygems/commit/320822c070

Co-authored-by: Stan Hu <stanhu@gmail.com>
This commit is contained in:
David Rodríguez 2022-07-12 12:33:12 +02:00 committed by git
parent 9d900620ca
commit 76de7a92b9
2 changed files with 35 additions and 3 deletions

View file

@ -31,9 +31,8 @@ module Bundler
# first try to fetch any new bytes on the existing file # first try to fetch any new bytes on the existing file
if retrying.nil? && local_path.file? if retrying.nil? && local_path.file?
SharedHelpers.filesystem_access(local_temp_path) do copy_file local_path, local_temp_path
FileUtils.cp local_path, local_temp_path
end
headers["If-None-Match"] = etag_for(local_temp_path) headers["If-None-Match"] = etag_for(local_temp_path)
headers["Range"] = headers["Range"] =
if local_temp_path.size.nonzero? if local_temp_path.size.nonzero?
@ -98,6 +97,20 @@ module Bundler
SharedHelpers.digest(:MD5).hexdigest(File.read(path)) SharedHelpers.digest(:MD5).hexdigest(File.read(path))
end end
end end
private
def copy_file(source, dest)
SharedHelpers.filesystem_access(source, :read) do
File.open(source, "r") do |s|
SharedHelpers.filesystem_access(dest, :write) do
File.open(dest, "wb", s.stat.mode) do |f|
IO.copy_stream(s, f)
end
end
end
end
end
end end
end end
end end

View file

@ -163,6 +163,25 @@ The checksum of /versions does not match the checksum provided by the server! So
expect(the_bundle).to include_gems "rack 1.0.0" expect(the_bundle).to include_gems "rack 1.0.0"
end end
it "shows proper path when permission errors happen", :permissions do
gemfile <<-G
source "#{source_uri}"
gem "rack"
G
versions = File.join(Bundler.rubygems.user_home, ".bundle", "cache", "compact_index",
"localgemserver.test.80.dd34752a738ee965a2a4298dc16db6c5", "versions")
FileUtils.mkdir_p(File.dirname(versions))
FileUtils.touch(versions)
FileUtils.chmod("-r", versions)
bundle :install, :artifice => "compact_index", :raise_on_error => false
expect(err).to include(
"There was an error while trying to read from `#{versions}`. It is likely that you need to grant read permissions for that path."
)
end
it "falls back when the user's home directory does not exist or is not writable" do it "falls back when the user's home directory does not exist or is not writable" do
ENV["HOME"] = tmp("missing_home").to_s ENV["HOME"] = tmp("missing_home").to_s