diff options
author | Gabriel Mazetto <brodock@gmail.com> | 2018-05-23 05:51:53 +0200 |
---|---|---|
committer | Gabriel Mazetto <brodock@gmail.com> | 2018-06-12 10:28:18 +0100 |
commit | fb40210e0642547e6b7802f934a42cb207eba165 (patch) | |
tree | 5c956e5e9b2f19783d763b5e900f27d1643bb34f | |
parent | c793c38a55559677573d28d4bfadd811e8508b48 (diff) | |
download | bundler-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.rb | 3 | ||||
-rw-r--r-- | spec/bundler/bundler_spec.rb | 51 |
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 |