summarylogtreecommitdiffstats
path: root/Gem.default_install.patch
blob: a7ad243675ee06375cd39d5afb8ea933ba56180d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
From 9e3a7232d0a69cca5cd3245aa2f2ec02d5da9e33 Mon Sep 17 00:00:00 2001
From: Felipe Contreras <felipe.contreras@gmail.com>
Date: Thu, 20 May 2021 16:26:25 -0500
Subject: [PATCH] Add Gem.default_install

We need a way to enable user installs by default so that tools like
bundler don't attempt to install to system directories.

The configuration Gem.default_user_install was meant to enable user
installs, but it only affects `gem install`, not bundler. Distributions
were already able to change the defaults of `gem install`, so it didn't
change anything, and that's why nobody is using it.

Instead we need a method that allows something that is not currently
possible: override Gem.dir.

Gem.default_install is that method, which allows changing user installs
to both gem and bundler.

To retain backwards compatibility it uses Gem.default_user_install by
default:

  def default_install
    default_user_install ? user_dir : default_dir
  end

Distributions can then override this to enable user installs by default:

  def default_install
    user_dir
  end

This allows for more flexibility than Gem.default_user_install. For
example distributions can choose to install to different directories
based on the user id:

  def default_install
    Process.uid == 0 ? local_dir : user_dir
  end

The current Gem.default_user_install solution is simply not enough.
---
 lib/rubygems.rb                     |  1 +
 lib/rubygems/defaults.rb            | 14 ++++++++------
 lib/rubygems/installer.rb           |  6 +++---
 lib/rubygems/path_support.rb        |  2 +-
 test/rubygems/test_gem_installer.rb |  4 ++--
 5 files changed, 15 insertions(+), 12 deletions(-)

diff --git a/lib/rubygems.rb b/lib/rubygems.rb
index 78017765e1..5e98321df7 100644
--- a/lib/rubygems.rb
+++ b/lib/rubygems.rb
@@ -1085,6 +1085,7 @@ def self.use_paths(home, *paths)
     hash = { "GEM_HOME" => home, "GEM_PATH" => paths.empty? ? home : paths.join(File::PATH_SEPARATOR) }
     hash.delete_if {|_, v| v.nil? }
     self.paths = hash
+    @default_install = home
   end
 
   ##
diff --git a/lib/rubygems/defaults.rb b/lib/rubygems/defaults.rb
index db07681a17..06ddf7bac6 100644
--- a/lib/rubygems/defaults.rb
+++ b/lib/rubygems/defaults.rb
@@ -9,6 +9,13 @@ module Gem
   @pre_uninstall_hooks  ||= []
   @pre_install_hooks    ||= []
 
+  ##
+  # Determines the default install directory
+
+  def self.default_install
+    @default_install ||= default_user_install ? user_dir : default_dir
+  end
+
   ##
   # An Array of the default sources that come with RubyGems
 
@@ -239,12 +246,7 @@ def self.default_cert_path
   # Enables automatic installation into user directory
 
   def self.default_user_install # :nodoc:
-    if !ENV.key?("GEM_HOME") && File.exist?(Gem.dir) && !File.writable?(Gem.dir)
-      Gem.ui.say "Defaulting to user installation because default installation directory (#{Gem.dir}) is not writable."
-      return true
-    end
-
-    false
+    File.exist?(default_dir) && !File.writable?(default_dir)
   end
 
   ##
diff --git a/lib/rubygems/installer.rb b/lib/rubygems/installer.rb
index 2b3200223a..b6eb616861 100644
--- a/lib/rubygems/installer.rb
+++ b/lib/rubygems/installer.rb
@@ -670,7 +670,7 @@ def process_options # :nodoc:
 
     @build_args = options[:build_args]
 
-    @gem_home = @install_dir || user_install_dir || Gem.dir
+    @gem_home = @install_dir || user_install_dir || Gem.default_install
 
     # If the user has asked for the gem to be installed in a directory that is
     # the system gem directory, then use the system bin directory, else create
@@ -961,13 +961,13 @@ def ensure_writable_dir(dir) # :nodoc:
 
   def user_install_dir
     # never install to user home in --build-root mode
-    return unless @build_root.nil?
+    return Gem.default_dir if @build_root || @user_install == false
 
     # Please note that @user_install might have three states:
     # * `true`: `--user-install`
     # * `false`: `--no-user-install` and
     # * `nil`: option was not specified
-    if @user_install || (@user_install.nil? && Gem.default_user_install)
+    if @user_install
       Gem.user_dir
     end
   end
diff --git a/lib/rubygems/path_support.rb b/lib/rubygems/path_support.rb
index 13091e29ba..455f413f3d 100644
--- a/lib/rubygems/path_support.rb
+++ b/lib/rubygems/path_support.rb
@@ -24,7 +24,7 @@ class Gem::PathSupport
   # hashtable, or defaults to ENV, the system environment.
   #
   def initialize(env)
-    @home = normalize_home_dir(env["GEM_HOME"] || Gem.default_dir)
+    @home = normalize_home_dir(env["GEM_HOME"] || Gem.default_install)
     @path = split_gem_path env["GEM_PATH"], @home
 
     @spec_cache_dir = env["GEM_SPEC_CACHE"] || Gem.default_spec_cache_dir
diff --git a/test/rubygems/test_gem_installer.rb b/test/rubygems/test_gem_installer.rb
index 34415aa7dd..c475aea917 100644
--- a/test/rubygems/test_gem_installer.rb
+++ b/test/rubygems/test_gem_installer.rb
@@ -1986,10 +1986,10 @@ def test_process_options_fallback_to_user_install_when_gem_home_not_writable
 
     FileUtils.chmod 0o000, @gemhome
 
+    Gem.use_paths(nil)
     installer = use_ui(@ui) { Gem::Installer.at @gem }
 
     assert_equal Gem.user_dir, installer.gem_home
-    assert_equal "Defaulting to user installation because default installation directory (#{@gemhome}) is not writable.", @ui.output.strip
   ensure
     FileUtils.chmod 0o755, @gemhome
     ENV["GEM_HOME"] = orig_gem_home
@@ -2007,10 +2007,10 @@ def test_process_options_does_not_fallback_to_user_install_when_gem_home_not_wri
 
     FileUtils.chmod 0o000, @gemhome
 
+    Gem.use_paths(nil)
     installer = use_ui(@ui) { Gem::Installer.at @gem, user_install: false }
 
     assert_equal @gemhome, installer.gem_home
-    assert_empty @ui.output.strip
   ensure
     FileUtils.chmod 0o755, @gemhome
     ENV["GEM_HOME"] = orig_gem_home
-- 
0.1