summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGabriel Mazetto <brodock@gmail.com>2018-05-23 05:51:53 +0200
committerGabriel Mazetto <brodock@gmail.com>2018-06-12 10:28:18 +0100
commitfb40210e0642547e6b7802f934a42cb207eba165 (patch)
tree5c956e5e9b2f19783d763b5e900f27d1643bb34f
parentc793c38a55559677573d28d4bfadd811e8508b48 (diff)
downloadbundler-fb40210e0642547e6b7802f934a42cb207eba165.tar.gz
Don't fallback to tempdir when required directories exist.
When home directory is not writable, but the required .bundle is, we should use it instead of falling back to use tempdirs. This creates a workaround for more restrictive setups using Omnibus Docker or any hardened setup, to overcome the annoyances introduced by #4951.
-rw-r--r--lib/bundler.rb3
-rw-r--r--spec/bundler/bundler_spec.rb51
2 files changed, 53 insertions, 1 deletions
diff --git a/lib/bundler.rb b/lib/bundler.rb
index 9944ebd051..8ed5b0861f 100644
--- a/lib/bundler.rb
+++ b/lib/bundler.rb
@@ -159,12 +159,13 @@ module Bundler
def user_home
@user_home ||= begin
home = Bundler.rubygems.user_home
+ bundle_home = home ? File.join(home, ".bundle") : nil
warning = if home.nil?
"Your home directory is not set."
elsif !File.directory?(home)
"`#{home}` is not a directory."
- elsif !File.writable?(home)
+ elsif !File.writable?(home) && (!File.directory?(bundle_home) || !File.writable?(bundle_home))
"`#{home}` is not writable."
end
diff --git a/spec/bundler/bundler_spec.rb b/spec/bundler/bundler_spec.rb
index 131146119e..c483701d6e 100644
--- a/spec/bundler/bundler_spec.rb
+++ b/spec/bundler/bundler_spec.rb
@@ -199,6 +199,57 @@ EOF
allow(File).to receive(:writable?).with(path).and_return true
expect(Bundler.user_home).to eq(Pathname(path))
end
+
+ context "is not a directory" do
+ it "should issue a warning and return a temporary user home" do
+ path = "/home/oggy"
+ allow(Bundler.rubygems).to receive(:user_home).and_return(path)
+ allow(File).to receive(:directory?).with(path).and_return false
+ allow(Etc).to receive(:getlogin).and_return("USER")
+ allow(Dir).to receive(:tmpdir).and_return("/TMP")
+ allow(FileTest).to receive(:exist?).with("/TMP/bundler/home").and_return(true)
+ expect(FileUtils).to receive(:mkpath).with("/TMP/bundler/home/USER")
+ message = <<EOF
+`/home/oggy` is not a directory.
+Bundler will use `/TMP/bundler/home/USER' as your home directory temporarily.
+EOF
+ expect(Bundler.ui).to receive(:warn).with(message)
+ expect(Bundler.user_home).to eq(Pathname("/TMP/bundler/home/USER"))
+ end
+ end
+
+ context "is not writable" do
+ let(:path) { "/home/oggy" }
+ let(:dotbundle) { "/home/oggy/.bundle" }
+
+ it "should issue a warning and return a temporary user home" do
+ allow(Bundler.rubygems).to receive(:user_home).and_return(path)
+ allow(File).to receive(:directory?).with(path).and_return true
+ allow(File).to receive(:writable?).with(path).and_return false
+ allow(File).to receive(:directory?).with(dotbundle).and_return false
+ allow(Etc).to receive(:getlogin).and_return("USER")
+ allow(Dir).to receive(:tmpdir).and_return("/TMP")
+ allow(FileTest).to receive(:exist?).with("/TMP/bundler/home").and_return(true)
+ expect(FileUtils).to receive(:mkpath).with("/TMP/bundler/home/USER")
+ message = <<EOF
+`/home/oggy` is not writable.
+Bundler will use `/TMP/bundler/home/USER' as your home directory temporarily.
+EOF
+ expect(Bundler.ui).to receive(:warn).with(message)
+ expect(Bundler.user_home).to eq(Pathname("/TMP/bundler/home/USER"))
+ end
+
+ context ".bundle exists and have correct permissions" do
+ it "should return the user home" do
+ allow(Bundler.rubygems).to receive(:user_home).and_return(path)
+ allow(File).to receive(:directory?).with(path).and_return true
+ allow(File).to receive(:writable?).with(path).and_return false
+ allow(File).to receive(:directory?).with(dotbundle).and_return true
+ allow(File).to receive(:writable?).with(dotbundle).and_return true
+ expect(Bundler.user_home).to eq(Pathname(path))
+ end
+ end
+ end
end
context "home directory is not set" do