mirror of
https://github.com/ruby/ruby.git
synced 2026-01-26 20:19:19 +00:00
[rubygems/rubygems] Improve Bundler errors when trying to install to a protected folder in macOS
### Before ``` $ GEM_HOME=/System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/gems/2.6.0/ bundle Fetching gem metadata from https://rubygems.org/. Source rubygems repository https://rubygems.org/ or installed locally is ignoring #<Bundler::StubSpecification name=sqlite3 version=1.3.13 platform=ruby> because it is missing extensions Source rubygems repository https://rubygems.org/ or installed locally is ignoring #<Bundler::StubSpecification name=nokogiri version=1.13.8 platform=ruby> because it is missing extensions Source rubygems repository https://rubygems.org/ or installed locally is ignoring #<Bundler::StubSpecification name=libxml-ruby version=3.2.1 platform=ruby> because it is missing extensions Resolving dependencies... Fetching ruby2_keywords 0.0.5 Retrying download gem from https://rubygems.org/ due to error (2/4): Bundler::GenericSystemCallError There was an error accessing `/System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/gems/2.6.0/cache/ruby2_keywords-0.0.5.gem`. The underlying system error is Errno::EPERM: Operation not permitted @ rb_sysopen - /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/gems/2.6.0/cache/ruby2_keywords-0.0.5.gem Retrying download gem from https://rubygems.org/ due to error (3/4): Bundler::GenericSystemCallError There was an error accessing `/System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/gems/2.6.0/cache/ruby2_keywords-0.0.5.gem`. The underlying system error is Errno::EPERM: Operation not permitted @ rb_sysopen - /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/gems/2.6.0/cache/ruby2_keywords-0.0.5.gem Retrying download gem from https://rubygems.org/ due to error (4/4): Bundler::GenericSystemCallError There was an error accessing `/System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/gems/2.6.0/cache/ruby2_keywords-0.0.5.gem`. The underlying system error is Errno::EPERM: Operation not permitted @ rb_sysopen - /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/gems/2.6.0/cache/ruby2_keywords-0.0.5.gem Bundler::GenericSystemCallError: There was an error accessing `/System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/gems/2.6.0/cache/ruby2_keywords-0.0.5.gem`. The underlying system error is Errno::EPERM: Operation not permitted @ rb_sysopen - /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/gems/2.6.0/cache/ruby2_keywords-0.0.5.gem /Users/deivid/code/rubygems/rubygems/bundler/lib/bundler/shared_helpers.rb:119:in `rescue in filesystem_access' /Users/deivid/code/rubygems/rubygems/bundler/lib/bundler/shared_helpers.rb:104:in `filesystem_access' /Users/deivid/code/rubygems/rubygems/bundler/lib/bundler/rubygems_integration.rb:431:in `block in download_gem' /Users/deivid/code/rubygems/rubygems/bundler/lib/bundler/retry.rb:40:in `run' /Users/deivid/code/rubygems/rubygems/bundler/lib/bundler/retry.rb:30:in `attempt' /Users/deivid/code/rubygems/rubygems/bundler/lib/bundler/rubygems_integration.rb:423:in `download_gem' /Users/deivid/code/rubygems/rubygems/bundler/lib/bundler/source/rubygems.rb:479:in `download_gem' /Users/deivid/code/rubygems/rubygems/bundler/lib/bundler/source/rubygems.rb:436:in `fetch_gem' /Users/deivid/code/rubygems/rubygems/bundler/lib/bundler/source/rubygems.rb:420:in `fetch_gem_if_possible' /Users/deivid/code/rubygems/rubygems/bundler/lib/bundler/source/rubygems.rb:162:in `install' /Users/deivid/code/rubygems/rubygems/bundler/lib/bundler/installer/gem_installer.rb:55:in `install' /Users/deivid/code/rubygems/rubygems/bundler/lib/bundler/installer/gem_installer.rb:17:in `install_from_spec' /Users/deivid/code/rubygems/rubygems/bundler/lib/bundler/installer/parallel_installer.rb:133:in `do_install' /Users/deivid/code/rubygems/rubygems/bundler/lib/bundler/installer/parallel_installer.rb:124:in `block in worker_pool' /Users/deivid/code/rubygems/rubygems/bundler/lib/bundler/worker.rb:62:in `apply_func' /Users/deivid/code/rubygems/rubygems/bundler/lib/bundler/worker.rb:57:in `block in process_queue' <internal:kernel>:187:in `loop' /Users/deivid/code/rubygems/rubygems/bundler/lib/bundler/worker.rb:54:in `process_queue' /Users/deivid/code/rubygems/rubygems/bundler/lib/bundler/worker.rb:90:in `block (2 levels) in create_threads' An error occurred while installing ruby2_keywords (0.0.5), and Bundler cannot continue. In Gemfile: ruby2_keywords ``` ### After ``` $ GEM_HOME=/System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/gems/2.6.0/ bundle There was an error creating `/System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/gems/2.6.0/bundler.lock`. The underlying system error is Errno::EPERM: Operation not permitted @ rb_sysopen - /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/gems/2.6.0/bundler.lock ``` https://github.com/rubygems/rubygems/commit/345ec45f5a
This commit is contained in:
parent
055ed5f592
commit
f2380081df
@ -2,23 +2,19 @@
|
||||
|
||||
module Bundler
|
||||
class ProcessLock
|
||||
def self.lock(bundle_path = Bundler.bundle_path)
|
||||
def self.lock(bundle_path = Bundler.bundle_path, &block)
|
||||
lock_file_path = File.join(bundle_path, "bundler.lock")
|
||||
has_lock = false
|
||||
base_lock_file_path = lock_file_path.delete_suffix(".lock")
|
||||
|
||||
File.open(lock_file_path, "w") do |f|
|
||||
f.flock(File::LOCK_EX)
|
||||
has_lock = true
|
||||
yield
|
||||
f.flock(File::LOCK_UN)
|
||||
require "fileutils" if Bundler.rubygems.provides?("< 3.5.23")
|
||||
|
||||
begin
|
||||
SharedHelpers.filesystem_access(lock_file_path, :write) do
|
||||
Gem.open_file_with_lock(base_lock_file_path, &block)
|
||||
end
|
||||
rescue PermissionError
|
||||
block.call
|
||||
end
|
||||
rescue Errno::EACCES, Errno::ENOLCK, Errno::ENOTSUP, Errno::EPERM, Errno::EROFS
|
||||
# In the case the user does not have access to
|
||||
# create the lock file or is using NFS where
|
||||
# locks are not available we skip locking.
|
||||
yield
|
||||
ensure
|
||||
FileUtils.rm_f(lock_file_path) if has_lock
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -103,7 +103,9 @@ module Bundler
|
||||
# @see {Bundler::PermissionError}
|
||||
def filesystem_access(path, action = :write, &block)
|
||||
yield(path.dup)
|
||||
rescue Errno::EACCES
|
||||
rescue Errno::EACCES => e
|
||||
raise unless e.message.include?(path.to_s) || action == :create
|
||||
|
||||
raise PermissionError.new(path, action)
|
||||
rescue Errno::EAGAIN
|
||||
raise TemporaryResourceError.new(path, action)
|
||||
|
||||
@ -801,6 +801,7 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
|
||||
file_lock = "#{path}.lock"
|
||||
open_file_with_flock(file_lock, &block)
|
||||
ensure
|
||||
require "fileutils"
|
||||
FileUtils.rm_f file_lock
|
||||
end
|
||||
|
||||
|
||||
@ -15,7 +15,7 @@ RSpec.describe Bundler::Definition do
|
||||
it "raises an PermissionError with explanation" do
|
||||
allow(File).to receive(:open).and_call_original
|
||||
expect(File).to receive(:open).with(bundled_app_lock, "wb").
|
||||
and_raise(Errno::EACCES)
|
||||
and_raise(Errno::EACCES.new(bundled_app_lock.to_s))
|
||||
expect { subject.lock }.
|
||||
to raise_error(Bundler::PermissionError, /Gemfile\.lock/)
|
||||
end
|
||||
|
||||
@ -458,7 +458,7 @@ RSpec.describe Bundler::SharedHelpers do
|
||||
end
|
||||
|
||||
context "system throws Errno::EACESS" do
|
||||
let(:file_op_block) { proc {|_path| raise Errno::EACCES } }
|
||||
let(:file_op_block) { proc {|_path| raise Errno::EACCES.new("/path") } }
|
||||
|
||||
it "raises a PermissionError" do
|
||||
expect { subject.filesystem_access("/path", &file_op_block) }.to raise_error(
|
||||
|
||||
@ -21,36 +21,19 @@ RSpec.describe "process lock spec" do
|
||||
expect(the_bundle).to include_gems "myrack 1.0"
|
||||
end
|
||||
|
||||
context "when creating a lock raises Errno::ENOTSUP" do
|
||||
before { allow(File).to receive(:open).and_raise(Errno::ENOTSUP) }
|
||||
|
||||
it "skips creating the lock file and yields" do
|
||||
processed = false
|
||||
Bundler::ProcessLock.lock(default_bundle_path) { processed = true }
|
||||
|
||||
expect(processed).to eq true
|
||||
end
|
||||
end
|
||||
|
||||
context "when creating a lock raises Errno::EPERM" do
|
||||
before { allow(File).to receive(:open).and_raise(Errno::EPERM) }
|
||||
|
||||
it "skips creating the lock file and yields" do
|
||||
processed = false
|
||||
Bundler::ProcessLock.lock(default_bundle_path) { processed = true }
|
||||
|
||||
expect(processed).to eq true
|
||||
it "raises a friendly error" do
|
||||
expect { Bundler::ProcessLock.lock(default_bundle_path) }.to raise_error(Bundler::GenericSystemCallError)
|
||||
end
|
||||
end
|
||||
|
||||
context "when creating a lock raises Errno::EROFS" do
|
||||
before { allow(File).to receive(:open).and_raise(Errno::EROFS) }
|
||||
|
||||
it "skips creating the lock file and yields" do
|
||||
processed = false
|
||||
Bundler::ProcessLock.lock(default_bundle_path) { processed = true }
|
||||
|
||||
expect(processed).to eq true
|
||||
it "raises a friendly error" do
|
||||
expect { Bundler::ProcessLock.lock(default_bundle_path) }.to raise_error(Bundler::GenericSystemCallError)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user