diff options
author | Homu <homu@barosl.com> | 2016-09-30 17:11:17 +0900 |
---|---|---|
committer | Homu <homu@barosl.com> | 2016-09-30 17:11:17 +0900 |
commit | c8991533ff4a6c512e9b18e037c2da581c6d76fb (patch) | |
tree | 0704426a5375abcc38125c3b673160874a159a4e | |
parent | dd6aef97a5f2e7173f406267256a8c319d6134ab (diff) | |
parent | 2ac0c510a4528d3eeef7fcc1b8e68bb7e053ebac (diff) | |
download | bundler-c8991533ff4a6c512e9b18e037c2da581c6d76fb.tar.gz |
Auto merge of #4951 - bundler:seg-no-writable-home, r=indirect
Fallback to a temp dir when the home directory is not usable
Closes https://github.com/bundler/bundler/issues/4778
This is an alternative to https://github.com/bundler/bundler/pull/4886
\c @allenzhao @indirect
-rw-r--r-- | lib/bundler.rb | 38 | ||||
-rw-r--r-- | lib/bundler/cli.rb | 2 | ||||
-rw-r--r-- | lib/bundler/fetcher/compact_index.rb | 2 | ||||
-rw-r--r-- | lib/bundler/gem_helper.rb | 2 | ||||
-rw-r--r-- | lib/bundler/shared_helpers.rb | 13 | ||||
-rw-r--r-- | lib/bundler/ui/shell.rb | 4 | ||||
-rw-r--r-- | lib/bundler/ui/silent.rb | 9 | ||||
-rw-r--r-- | spec/bundler/shared_helpers_spec.rb | 5 | ||||
-rw-r--r-- | spec/runtime/inline_spec.rb | 20 |
9 files changed, 87 insertions, 8 deletions
diff --git a/lib/bundler.rb b/lib/bundler.rb index 249c4e2d..f25d43e0 100644 --- a/lib/bundler.rb +++ b/lib/bundler.rb @@ -3,6 +3,8 @@ require "fileutils" require "pathname" require "rbconfig" require "thread" +require "tmpdir" + require "bundler/errors" require "bundler/environment_preserver" require "bundler/gem_remote_fetcher" @@ -143,8 +145,41 @@ module Bundler "#{Bundler.rubygems.ruby_engine}/#{Bundler.rubygems.config_map[:ruby_version]}" end + 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" + elsif !File.directory?(home) + warning += "\n * `#{home}` is not a directory" + elsif !File.writable?(home) + warning += "\n * `#{home}` is not writable" + else + return @user_home = Pathname.new(home) + 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 + end + + warning += "\n\nBundler will use `#{tmp_home}` as your home directory temporarily" + + Bundler.ui.warn(warning) + tmp_home + end + end + def user_bundle_path - Pathname.new(Bundler.rubygems.user_home).join(".bundle") + Pathname.new(user_home).join(".bundle") end def home @@ -409,6 +444,7 @@ EOF @locked_gems = nil @bundle_path = nil @bin_path = nil + @user_home = nil Plugin.reset! diff --git a/lib/bundler/cli.rb b/lib/bundler/cli.rb index ee18767a..8aa4a0e5 100644 --- a/lib/bundler/cli.rb +++ b/lib/bundler/cli.rb @@ -36,8 +36,10 @@ module Bundler ensure self.options ||= {} Bundler.settings.cli_flags_given = !options.empty? + unprinted_warnings = Bundler.ui.unprinted_warnings Bundler.ui = UI::Shell.new(options) Bundler.ui.level = "debug" if options["verbose"] + unprinted_warnings.each {|w| Bundler.ui.warn(w) } if ENV["RUBYGEMS_GEMDEPS"] && !ENV["RUBYGEMS_GEMDEPS"].empty? Bundler.ui.warn( diff --git a/lib/bundler/fetcher/compact_index.rb b/lib/bundler/fetcher/compact_index.rb index 9461368d..63b5c837 100644 --- a/lib/bundler/fetcher/compact_index.rb +++ b/lib/bundler/fetcher/compact_index.rb @@ -61,7 +61,7 @@ module Bundler compact_index_request :fetch_spec def available? - user_home = Pathname.new(Bundler.rubygems.user_home) + user_home = Bundler.user_home return nil unless user_home.directory? && user_home.writable? # Read info file checksums out of /versions, so we can know if gems are up to date fetch_uri.scheme != "file" && compact_index_client.update_and_parse_checksums! diff --git a/lib/bundler/gem_helper.rb b/lib/bundler/gem_helper.rb index fdb2db7d..73cbf9e0 100644 --- a/lib/bundler/gem_helper.rb +++ b/lib/bundler/gem_helper.rb @@ -98,7 +98,7 @@ module Bundler allowed_push_host = @gemspec.metadata["allowed_push_host"] gem_command += " --host #{allowed_push_host}" if allowed_push_host end - unless allowed_push_host || Pathname.new("~/.gem/credentials").expand_path.file? + unless allowed_push_host || Bundler.user_home.join(".gem/credentials").file? raise "Your rubygems.org credentials aren't set. Run `gem push` to set them." end sh(gem_command) diff --git a/lib/bundler/shared_helpers.rb b/lib/bundler/shared_helpers.rb index ca4eafd6..0ddcea1c 100644 --- a/lib/bundler/shared_helpers.rb +++ b/lib/bundler/shared_helpers.rb @@ -39,10 +39,12 @@ module Bundler bundle_dir = find_directory(".bundle") return nil unless bundle_dir - global_bundle_dir = File.join(Bundler.rubygems.user_home, ".bundle") + bundle_dir = Pathname.new(bundle_dir) + + global_bundle_dir = Bundler.user_home.join(".bundle") return nil if bundle_dir == global_bundle_dir - Pathname.new(bundle_dir) + bundle_dir end def in_bundle? @@ -202,10 +204,15 @@ module Bundler def set_rubylib rubylib = (ENV["RUBYLIB"] || "").split(File::PATH_SEPARATOR) - rubylib.unshift File.expand_path("../..", __FILE__) + rubylib.unshift bundler_ruby_lib ENV["RUBYLIB"] = rubylib.uniq.join(File::PATH_SEPARATOR) end + def bundler_ruby_lib + File.expand_path("../..", __FILE__) + end + private :bundler_ruby_lib + def clean_load_path # handle 1.9 where system gems are always on the load path if defined?(::Gem) diff --git a/lib/bundler/ui/shell.rb b/lib/bundler/ui/shell.rb index 5c1fa615..697290f7 100644 --- a/lib/bundler/ui/shell.rb +++ b/lib/bundler/ui/shell.rb @@ -83,6 +83,10 @@ module Bundler with_level("silent", &blk) end + def unprinted_warnings + [] + end + private # valimism diff --git a/lib/bundler/ui/silent.rb b/lib/bundler/ui/silent.rb index 367eaa58..5e0037f4 100644 --- a/lib/bundler/ui/silent.rb +++ b/lib/bundler/ui/silent.rb @@ -2,6 +2,10 @@ module Bundler module UI class Silent + def initialize + @warnings = [] + end + def add_color(string, color) string end @@ -13,6 +17,7 @@ module Bundler end def warn(message, newline = nil) + @warnings |= [message] end def error(message, newline = nil) @@ -44,6 +49,10 @@ module Bundler def silence yield end + + def unprinted_warnings + @warnings + end end end end diff --git a/spec/bundler/shared_helpers_spec.rb b/spec/bundler/shared_helpers_spec.rb index 4c0d61cf..8826dcd4 100644 --- a/spec/bundler/shared_helpers_spec.rb +++ b/spec/bundler/shared_helpers_spec.rb @@ -234,7 +234,9 @@ describe Bundler::SharedHelpers do shared_examples_for "ENV['RUBYLIB'] gets set correctly" do let(:ruby_lib_path) { "stubbed_ruby_lib_dir" } - before { allow(File).to receive(:expand_path).and_return(ruby_lib_path) } + before do + allow(Bundler::SharedHelpers).to receive(:bundler_ruby_lib).and_return(ruby_lib_path) + end it "ensures bundler's ruby version lib path is in ENV['RUBYLIB']" do subject.set_bundle_environment @@ -324,7 +326,6 @@ describe Bundler::SharedHelpers do let(:ruby_lib_path) { "stubbed_ruby_lib_dir" } before do - allow(File).to receive(:expand_path).and_return(ruby_lib_path) ENV["RUBYLIB"] = ruby_lib_path end diff --git a/spec/runtime/inline_spec.rb b/spec/runtime/inline_spec.rb index 3119045b..4d9a1f7f 100644 --- a/spec/runtime/inline_spec.rb +++ b/spec/runtime/inline_spec.rb @@ -173,4 +173,24 @@ describe "bundler/inline#gemfile" do expect(err).to be_empty expect(exitstatus).to be_zero if exitstatus end + + it "allows calling gemfile twice" do + script <<-RUBY + gemfile do + path "#{lib_path}" do + gem "two" + end + end + + gemfile do + path "#{lib_path}" do + gem "four" + end + end + RUBY + + expect(out).to eq("two\nfour") + expect(err).to be_empty + expect(exitstatus).to be_zero if exitstatus + end end |