summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Rodríguez <[email protected]>2022-09-09 11:18:18 +0200
committerHiroshi SHIBATA <[email protected]>2025-02-21 11:31:49 +0900
commitee2c7bcae5d8c96f41305e1a24739493121ef49b (patch)
treec53535f305017b26663156aca2e4386ac03528e0
parentca46a159911e100ced3d4c96a4ee8291b8e0954e (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.rb18
-rw-r--r--lib/bundler/plugin/index.rb2
-rw-r--r--lib/bundler/shared_helpers.rb4
-rw-r--r--spec/bundler/install/process_lock_spec.rb25
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