summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThe Bundler Bot <bot@bundler.io>2017-02-09 03:12:23 +0000
committerThe Bundler Bot <bot@bundler.io>2017-02-09 03:12:23 +0000
commit311b090449b591d4fb96a725e548b4d35ac95ed0 (patch)
tree2415597dfd09c75ea9397c01a904abd137a80369
parentd35a85385e9ddd56aeaabfae6952b1e41aee2992 (diff)
parent2c1ffb86763d351b0cfc7843e3bf94ea54b94766 (diff)
downloadbundler-311b090449b591d4fb96a725e548b4d35ac95ed0.tar.gz
Auto merge of #5363 - svoop:permissive_tmp_home_dirs, r=indirect
Permissive temporary home directory We're deploying to a server with several Ruby applications each with it's own user. However, the home directory of these users is *not* writable by the users. Since Bundler 1.14.x, a temporary home directoy in the `tmpdir` is used as a fallback. This works well for only one user, but will fail with more than one: 1. user1 execs `bundle` 2. `/tmp/bundler/home/user1` is created usually with 0755 modes 3. user2 execs `bundle` 4. `/tmp/bundler/home/user2` cannot be created since user2 can't write to `home` This PR adds a `chmod` to apply mode 0777 to `home`. It rescues to nil in order to silently fail on step 4 (user2 cannot chmod `home` since it's owned by user1) as well as in case of any other problem performing chmod. Since we're in a fallback here, I guess it's okay to do this. However, if this is too much code smell, a `unless File.exist?` will do the trick as well.
-rw-r--r--lib/bundler.rb45
-rw-r--r--spec/bundler/bundler_spec.rb39
-rw-r--r--spec/spec_helper.rb8
3 files changed, 71 insertions, 21 deletions
diff --git a/lib/bundler.rb b/lib/bundler.rb
index 2cd8d9916b..c98dece747 100644
--- a/lib/bundler.rb
+++ b/lib/bundler.rb
@@ -146,34 +146,37 @@ module Bundler
def user_home
@user_home ||= begin
home = Bundler.rubygems.user_home
- warning = "Your home directory is not set properly:"
- if home.nil?
- warning += "\n * It is not set at all"
+
+ warning = if home.nil?
+ "Your home directory is not set."
elsif !File.directory?(home)
- warning += "\n * `#{home}` is not a directory"
+ "`#{home}` is not a directory."
elsif !File.writable?(home)
- warning += "\n * `#{home}` is not writable"
- else
- return @user_home = Pathname.new(home)
+ "`#{home}` is not writable."
end
- login = Etc.getlogin || "unknown"
-
- tmp_home = Pathname.new(Dir.tmpdir).join("bundler", "home", login)
- begin
- SharedHelpers.filesystem_access(tmp_home, :write) do |p|
- FileUtils.mkdir_p(p)
- end
- rescue => e
- warning += "\n\nBundler also failed to create a temporary home directory at `#{tmp_home}`:\n#{e}"
- raise warning
+ if warning
+ user_home = tmp_home_path(Etc.getlogin, warning)
+ Bundler.ui.warn "#{warning}\nBundler will use `#{user_home}' as your home directory temporarily.\n"
+ user_home
+ else
+ Pathname.new(home)
end
+ end
+ end
- warning += "\n\nBundler will use `#{tmp_home}` as your home directory temporarily"
-
- Bundler.ui.warn(warning)
- tmp_home
+ def tmp_home_path(login, warning)
+ login ||= "unknown"
+ path = Pathname.new(Dir.tmpdir).join("bundler", "home")
+ SharedHelpers.filesystem_access(path) do |tmp_home_path|
+ unless tmp_home_path.exist?
+ tmp_home_path.mkpath
+ tmp_home_path.chmod(0o777)
+ end
+ tmp_home_path.join(login).tap(&:mkpath)
end
+ rescue => e
+ raise "#{warning}\nBundler also failed to create a temporary home directory at `#{path}':\n#{e}"
end
def user_bundle_path
diff --git a/spec/bundler/bundler_spec.rb b/spec/bundler/bundler_spec.rb
index 4458efce6a..268c0d99ac 100644
--- a/spec/bundler/bundler_spec.rb
+++ b/spec/bundler/bundler_spec.rb
@@ -170,4 +170,43 @@ EOF
end
end
end
+
+ describe "#user_home" do
+ context "home directory is set" do
+ it "should return the 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 true
+ allow(File).to receive(:writable?).with(path).and_return true
+ expect(Bundler.user_home).to eq(Pathname(path))
+ end
+ end
+
+ context "home directory is not set" do
+ it "should issue warning and return a temporary user home" do
+ allow(Bundler.rubygems).to receive(:user_home).and_return(nil)
+ 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
+Your home directory is not set.
+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
+ end
+
+ describe "#tmp_home_path" do
+ it "should create temporary user home" do
+ allow(Dir).to receive(:tmpdir).and_return("/TMP")
+ allow(FileTest).to receive(:exist?).with("/TMP/bundler/home").and_return(false)
+ expect(FileUtils).to receive(:mkpath).once.ordered.with("/TMP/bundler/home")
+ expect(FileUtils).to receive(:mkpath).once.ordered.with("/TMP/bundler/home/USER")
+ expect(File).to receive(:chmod).with(0o777, "/TMP/bundler/home")
+ expect(Bundler.tmp_home_path("USER", "")).to eq(Pathname("/TMP/bundler/home/USER"))
+ end
+ end
end
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index 53b7527545..297d81f531 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -103,6 +103,14 @@ RSpec.configure do |config|
config.before :all do
build_repo1
+ # HACK: necessary until rspec-mocks > 3.5.0 is used
+ # see https://github.com/bundler/bundler/pull/5363#issuecomment-278089256
+ if RUBY_VERSION < "1.9"
+ FileUtils.module_eval do
+ alias_method :mkpath, :mkdir_p
+ module_function :mkpath
+ end
+ end
end
config.before :each do