diff options
author | David RodrÃguez <[email protected]> | 2022-09-09 11:18:18 +0200 |
---|---|---|
committer | Hiroshi SHIBATA <[email protected]> | 2025-02-21 11:31:49 +0900 |
commit | ee2c7bcae5d8c96f41305e1a24739493121ef49b (patch) | |
tree | c53535f305017b26663156aca2e4386ac03528e0 | |
parent | ca46a159911e100ced3d4c96a4ee8291b8e0954e (diff) |
[rubygems/rubygems] Allow noop `bundle install` to work on read-only or protected folders
As long as there's nothing new to install and gems are already there.
If not, give a meaningful error about what happened.
This was how things already worked until
https://github.com/rubygems/rubygems/commit/345ec45f5a87, so this commit partially
reverts that change.
https://github.com/rubygems/rubygems/commit/794b0ecb39
-rw-r--r-- | lib/bundler/errors.rb | 18 | ||||
-rw-r--r-- | lib/bundler/plugin/index.rb | 2 | ||||
-rw-r--r-- | lib/bundler/shared_helpers.rb | 4 | ||||
-rw-r--r-- | spec/bundler/install/process_lock_spec.rb | 25 |
4 files changed, 44 insertions, 5 deletions
diff --git a/lib/bundler/errors.rb b/lib/bundler/errors.rb index 9d3d89ffeb..4d1bface51 100644 --- a/lib/bundler/errors.rb +++ b/lib/bundler/errors.rb @@ -193,6 +193,24 @@ module Bundler status_code(31) end + class ReadOnlyFileSystemError < PermissionError + def message + "There was an error while trying to #{action} `#{@path}`. " \ + "File system is read-only." + end + + status_code(42) + end + + class OperationNotPermittedError < PermissionError + def message + "There was an error while trying to #{action} `#{@path}`. " \ + "Underlying OS system call raised an EPERM error." + end + + status_code(43) + end + class GenericSystemCallError < BundlerError attr_reader :underlying_error diff --git a/lib/bundler/plugin/index.rb b/lib/bundler/plugin/index.rb index 0b1234bbf3..0682d37772 100644 --- a/lib/bundler/plugin/index.rb +++ b/lib/bundler/plugin/index.rb @@ -31,7 +31,7 @@ module Bundler begin load_index(global_index_file, true) - rescue GenericSystemCallError + rescue PermissionError # no need to fail when on a read-only FS, for example nil rescue ArgumentError => e diff --git a/lib/bundler/shared_helpers.rb b/lib/bundler/shared_helpers.rb index 9b398830f7..1ef9d61361 100644 --- a/lib/bundler/shared_helpers.rb +++ b/lib/bundler/shared_helpers.rb @@ -115,6 +115,10 @@ module Bundler raise NoSpaceOnDeviceError.new(path, action) rescue Errno::ENOTSUP raise OperationNotSupportedError.new(path, action) + rescue Errno::EPERM + raise OperationNotPermittedError.new(path, action) + rescue Errno::EROFS + raise ReadOnlyFileSystemError.new(path, action) rescue Errno::EEXIST, Errno::ENOENT raise rescue SystemCallError => e diff --git a/spec/bundler/install/process_lock_spec.rb b/spec/bundler/install/process_lock_spec.rb index 707d2fde5e..8082ec40fa 100644 --- a/spec/bundler/install/process_lock_spec.rb +++ b/spec/bundler/install/process_lock_spec.rb @@ -21,19 +21,36 @@ 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 "raises a friendly error" do - expect { Bundler::ProcessLock.lock(default_bundle_path) }.to raise_error(Bundler::GenericSystemCallError) + 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::EROFS" do before { allow(File).to receive(:open).and_raise(Errno::EROFS) } - it "raises a friendly error" do - expect { Bundler::ProcessLock.lock(default_bundle_path) }.to raise_error(Bundler::GenericSystemCallError) + 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 end |