diff --git a/lib/bundler.rb b/lib/bundler.rb index 829dc5d9496..f44b7b6d786 100644 --- a/lib/bundler.rb +++ b/lib/bundler.rb @@ -195,8 +195,26 @@ def tmp_home_path(login, warning) raise e.exception("#{warning}\nBundler also failed to create a temporary home directory at `#{path}':\n#{e}") end - def user_bundle_path - Pathname.new(user_home).join(".bundle") + def user_bundle_path(dir = "home") + env_var, fallback = case dir + when "home" + ["BUNDLE_USER_HOME", Pathname.new(user_home).join(".bundle")] + when "cache" + ["BUNDLE_USER_CACHE", user_bundle_path.join("cache")] + when "config" + ["BUNDLE_USER_CONFIG", user_bundle_path.join("config")] + when "plugin" + ["BUNDLE_USER_PLUGIN", user_bundle_path.join("plugin")] + else + raise BundlerError, "Unknown user path requested: #{dir}" + end + # `fallback` will already be a Pathname, but Pathname.new() is + # idempotent so it's OK + Pathname.new(ENV.fetch(env_var, fallback)) + end + + def user_cache + user_bundle_path("cache") end def home @@ -211,10 +229,6 @@ def specs_path bundle_path.join("specifications") end - def user_cache - user_bundle_path.join("cache") - end - def root @root ||= begin SharedHelpers.root diff --git a/lib/bundler/plugin.rb b/lib/bundler/plugin.rb index 0aa13ab7849..53f9806b73d 100644 --- a/lib/bundler/plugin.rb +++ b/lib/bundler/plugin.rb @@ -81,8 +81,8 @@ def index # The directory root for all plugin related data # - # Points to root in app_config_path if ran in an app else points to the one - # in user_bundle_path + # If run in an app, points to local root, in app_config_path + # Otherwise, points to global root, in Bundler.user_bundle_path("plugin") def root @root ||= if SharedHelpers.in_bundle? local_root @@ -97,7 +97,7 @@ def local_root # The global directory root for all plugin related data def global_root - Bundler.user_bundle_path.join("plugin") + Bundler.user_bundle_path("plugin") end # The cache directory for plugin stuffs diff --git a/lib/bundler/settings.rb b/lib/bundler/settings.rb index 611c5a4ef9d..fe68d510ffa 100644 --- a/lib/bundler/settings.rb +++ b/lib/bundler/settings.rb @@ -395,7 +395,7 @@ def global_config_file Pathname.new(ENV["BUNDLE_CONFIG"]) else begin - Bundler.user_bundle_path.join("config") + Bundler.user_bundle_path("config") rescue PermissionError, GenericSystemCallError nil end diff --git a/spec/bundler/bundler_spec.rb b/spec/bundler/bundler_spec.rb index 40dc0948854..2b9051a9747 100644 --- a/spec/bundler/bundler_spec.rb +++ b/spec/bundler/bundler_spec.rb @@ -306,4 +306,62 @@ expect(Bundler.tmp_home_path("USER", "")).to eq(Pathname("/TMP/bundler/home/USER")) end end + + context "user cache dir" do + let(:home_path) { Pathname.new(ENV["HOME"]) } + + let(:xdg_data_home) { home_path.join(".local") } + let(:xdg_cache_home) { home_path.join(".cache") } + let(:xdg_config_home) { home_path.join(".config") } + + let(:bundle_user_home_default) { home_path.join(".bundle") } + let(:bundle_user_home_custom) { xdg_data_home.join("bundle") } + + let(:bundle_user_cache_default) { bundle_user_home_default.join("cache") } + let(:bundle_user_cache_custom) { xdg_cache_home.join("bundle") } + + let(:bundle_user_config_default) { bundle_user_home_default.join("config") } + let(:bundle_user_config_custom) { xdg_config_home.join("bundle") } + + let(:bundle_user_plugin_default) { bundle_user_home_default.join("plugin") } + let(:bundle_user_plugin_custom) { xdg_data_home.join("bundle").join("plugin") } + + describe "#user_bundle_path" do + before do + allow(Bundler.rubygems).to receive(:user_home).and_return(home_path) + end + + it "should use the default home path" do + expect(Bundler.user_bundle_path).to eq(bundle_user_home_default) + expect(Bundler.user_bundle_path("home")).to eq(bundle_user_home_default) + expect(Bundler.user_bundle_path("cache")).to eq(bundle_user_cache_default) + expect(Bundler.user_cache).to eq(bundle_user_cache_default) + expect(Bundler.user_bundle_path("config")).to eq(bundle_user_config_default) + expect(Bundler.user_bundle_path("plugin")).to eq(bundle_user_plugin_default) + end + + it "should use custom home path as root for other paths" do + ENV["BUNDLE_USER_HOME"] = bundle_user_home_custom.to_s + expect(Bundler.user_bundle_path).to eq(bundle_user_home_custom) + expect(Bundler.user_bundle_path("home")).to eq(bundle_user_home_custom) + expect(Bundler.user_bundle_path("cache")).to eq(bundle_user_home_custom.join("cache")) + expect(Bundler.user_cache).to eq(bundle_user_home_custom.join("cache")) + expect(Bundler.user_bundle_path("config")).to eq(bundle_user_home_custom.join("config")) + expect(Bundler.user_bundle_path("plugin")).to eq(bundle_user_home_custom.join("plugin")) + end + + it "should use all custom paths, except home" do + ENV.delete("BUNDLE_USER_HOME") + ENV["BUNDLE_USER_CACHE"] = bundle_user_cache_custom.to_s + ENV["BUNDLE_USER_CONFIG"] = bundle_user_config_custom.to_s + ENV["BUNDLE_USER_PLUGIN"] = bundle_user_plugin_custom.to_s + expect(Bundler.user_bundle_path).to eq(bundle_user_home_default) + expect(Bundler.user_bundle_path("home")).to eq(bundle_user_home_default) + expect(Bundler.user_bundle_path("cache")).to eq(bundle_user_cache_custom) + expect(Bundler.user_cache).to eq(bundle_user_cache_custom) + expect(Bundler.user_bundle_path("config")).to eq(bundle_user_config_custom) + expect(Bundler.user_bundle_path("plugin")).to eq(bundle_user_plugin_custom) + end + end + end end