summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam Wanninger <ajwann@ajwann.codes>2017-10-29 12:24:09 -0400
committerAdam Wanninger <ajwann@ajwann.codes>2018-01-25 10:00:58 -0500
commit40911ddadbd052e342ebb99ad4188efffc8290c1 (patch)
treeb3431a3f022821ae821d136b6cc587f0e427a9aa
parent914a4a8b8d0cf1a79dbc7b334fbb5c2db1ecdc16 (diff)
downloadbundler-40911ddadbd052e342ebb99ad4188efffc8290c1.tar.gz
check Bundler.home permissions in doctor command
-rw-r--r--lib/bundler/cli/doctor.rb34
-rw-r--r--spec/commands/doctor_spec.rb55
2 files changed, 74 insertions, 15 deletions
diff --git a/lib/bundler/cli/doctor.rb b/lib/bundler/cli/doctor.rb
index 7f28a5eb13..93366c33a9 100644
--- a/lib/bundler/cli/doctor.rb
+++ b/lib/bundler/cli/doctor.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
require "rbconfig"
+require "find"
module Bundler
class CLI::Doctor
@@ -61,6 +62,7 @@ module Bundler
end
def run
+ check_home_permissions
Bundler.ui.level = "error" if options[:quiet]
Bundler.settings.validate!
check!
@@ -90,5 +92,37 @@ module Bundler
Bundler.ui.info "No issues found with the installed bundle"
end
end
+
+ private
+
+ def check_home_permissions
+ check_for_files_not_owned_by_current_user_but_still_rw
+ check_for_files_not_readable_or_writable
+ end
+
+ def check_for_files_not_owned_by_current_user_but_still_rw
+ return unless any_files_not_owned_by_current_user_but_still_rw?
+ Bundler.ui.warn "Files exist in Bundler home that are owned by another " \
+ "user, but are stil readable/writable"
+ end
+
+ def check_for_files_not_readable_or_writable
+ return unless any_files_not_readable_or_writable?
+ raise ProductionError, "Files exist in Bundler home that are not " \
+ "readable/writable to the current user"
+ end
+
+ def any_files_not_readable_or_writable?
+ Find.find(Bundler.home.to_s).any? do |f|
+ !(File.writable?(f) && File.readable?(f))
+ end
+ end
+
+ def any_files_not_owned_by_current_user_but_still_rw?
+ Find.find(Bundler.home.to_s).any? do |f|
+ (File.stat(f).uid != Process.uid) &&
+ (File.writable?(f) && File.readable?(f))
+ end
+ end
end
end
diff --git a/spec/commands/doctor_spec.rb b/spec/commands/doctor_spec.rb
index 2572d4ff4d..3e58adff36 100644
--- a/spec/commands/doctor_spec.rb
+++ b/spec/commands/doctor_spec.rb
@@ -6,6 +6,19 @@ require "bundler/cli/doctor"
RSpec.describe "bundle doctor" do
before(:each) do
+ install_gemfile! <<-G
+ source "file://#{gem_repo1}"
+ gem "rack"
+ G
+
+ stat = double("stat")
+ unwritable_file = double("file")
+ allow(Find).to receive(:find).with(Bundler.home.to_s) { [unwritable_file] }
+ allow(File).to receive(:stat).with(unwritable_file) { stat }
+ allow(stat).to receive(:uid) { Process.uid }
+ allow(File).to receive(:writable?).with(unwritable_file) { true }
+ allow(File).to receive(:readable?).with(unwritable_file) { true }
+
@stdout = StringIO.new
[:error, :warn].each do |method|
@@ -17,21 +30,11 @@ RSpec.describe "bundle doctor" do
end
it "exits with no message if the installed gem has no C extensions" do
- install_gemfile! <<-G
- source "file://#{gem_repo1}"
- gem "rack"
- G
-
expect { Bundler::CLI::Doctor.new({}).run }.not_to raise_error
expect(@stdout.string).to be_empty
end
it "exits with no message if the installed gem's C extension dylib breakage is fine" do
- install_gemfile! <<-G
- source "file://#{gem_repo1}"
- gem "rack"
- G
-
doctor = Bundler::CLI::Doctor.new({})
expect(doctor).to receive(:bundles_for_gem).exactly(2).times.and_return ["/path/to/rack/rack.bundle"]
expect(doctor).to receive(:dylibs).exactly(2).times.and_return ["/usr/lib/libSystem.dylib"]
@@ -42,11 +45,6 @@ RSpec.describe "bundle doctor" do
end
it "exits with a message if one of the linked libraries is missing" do
- install_gemfile! <<-G
- source "file://#{gem_repo1}"
- gem "rack"
- G
-
doctor = Bundler::CLI::Doctor.new({})
expect(doctor).to receive(:bundles_for_gem).exactly(2).times.and_return ["/path/to/rack/rack.bundle"]
expect(doctor).to receive(:dylibs).exactly(2).times.and_return ["/usr/local/opt/icu4c/lib/libicui18n.57.1.dylib"]
@@ -58,4 +56,31 @@ RSpec.describe "bundle doctor" do
* rack: /usr/local/opt/icu4c/lib/libicui18n.57.1.dylib
E
end
+
+ it "exits with an error if home contains files that are not read/write" do
+ stat = double("stat")
+ unwritable_file = double("file")
+ doctor = Bundler::CLI::Doctor.new({})
+ allow(Find).to receive(:find).with(Bundler.home.to_s) { [unwritable_file] }
+ allow(File).to receive(:stat).with(unwritable_file) { stat }
+ allow(stat).to receive(:uid) { Process.uid }
+ allow(File).to receive(:writable?).with(unwritable_file) { false }
+ allow(File).to receive(:readable?).with(unwritable_file) { false }
+ expect { doctor.run }.to raise_error(
+ Bundler::ProductionError,
+ "Files exist in Bundler home that are not readable/writable to the current user"
+ )
+ end
+
+ it "exits with a warning if home contains files that are read/write but not owned by current user" do
+ stat = double("stat")
+ unwritable_file = double("file")
+ allow(Find).to receive(:find).with(Bundler.home.to_s) { [unwritable_file] }
+ allow(File).to receive(:stat).with(unwritable_file) { stat }
+ allow(stat).to receive(:uid) { 0o0000 }
+ allow(File).to receive(:writable?).with(unwritable_file) { true }
+ allow(File).to receive(:readable?).with(unwritable_file) { true }
+ expect { Bundler::CLI::Doctor.new({}).run }.not_to raise_error
+ expect(@stdout.string).to include("Files exist in Bundler home that are owned by another user, but are stil readable/writable")
+ end
end