1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

Support XDG_* (#2174)

* Support XDG_CONFIG_HOME for gemrc.

* Support XDG_DATA_HOME for .gem

* Added test for XDG_DATA_HOME

* Do not reuse environmental variable.

* Unify .rdoc path to RDoc.home.

* Support XDG_DATA_HOME for .rdoc

* Ignore exists?

* Extracted config_home path

* Use XDG_CONFIG_HOME for default credential path

* Fixed inconsistency location.

* Fixed the broken tests.

* Support XDG_CONFIG_HOME for irbrc

* Introduce Gem.cache_home as XDG_CACHE_HOME

* Use Gem.cache_home instead of Gem.config_home for the credential file of RubyGems.

* Initialized the old configurations

* Fixed test failure related the configuration initialization

* restore XDG_DATA_HOME

* Fixed the broken examples of bundler with XDG_*

* Do not modify environmental variable on test file

* Use XDG_DATA_HOME insted of XDG_CACHE_HOME for credential file

* stub out Gem.data_home

* Move dir accessor to defaults.rb file

* Use XDG_DATA_HOME for signed gem features

* Use XDG_DATA_HOME for spec cache

* Do not rely on Gem.user_home

* Gem.user_home is always exists. Don't need to use FileUitls.mkdir_p

* Bump support version to RubyGems 3.2.0+

* Removed the needless fallback configuration

* Fixed the inconsistency methods that are find_config_file and config_file

* Use Gem.configuration.credentials_path instead of hard-coded path

* gem_path is always provided

* Removed the duplicated code of find_home

* Also removed the duplicated code of user_home

* use Gem::UNTAINT instead of untaint for surpressing the warnings

* Use File.directory

* Restore XDG_DATA_HOME

* Use File.write
This commit is contained in:
Hiroshi SHIBATA 2020-04-23 19:16:06 +09:00 committed by GitHub
parent f563f3c5ef
commit 5c6269c459
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
Notes: git 2020-04-23 19:16:30 +09:00
Merged-By: hsbt <hsbt@ruby-lang.org>
20 changed files with 186 additions and 76 deletions

View file

@ -271,10 +271,19 @@ module IRB # :nodoc:
if irbrc = ENV["IRBRC"]
yield proc{|rc| rc == "rc" ? irbrc : irbrc+rc}
end
if xdg_config_home = ENV["XDG_CONFIG_HOME"]
irb_home = File.join(xdg_config_home, "irb")
unless File.exist? irb_home
require 'fileutils'
FileUtils.mkdir_p irb_home
end
yield proc{|rc| irb_home + "/irb#{rc}"}
end
if home = ENV["HOME"]
yield proc{|rc| home+"/.irb#{rc}"}
end
current_dir = Dir.pwd
yield proc{|rc| current_dir+"/.config/irb/irb#{rc}"}
yield proc{|rc| current_dir+"/.irb#{rc}"}
yield proc{|rc| current_dir+"/irb#{rc.sub(/\A_?/, '.')}"}
yield proc{|rc| current_dir+"/_irb#{rc}"}

View file

@ -120,6 +120,24 @@ module RDoc
end
end
def self.home
rdoc_dir = begin
File.expand_path('~/.rdoc')
rescue ArgumentError
end
if File.directory?(rdoc_dir)
rdoc_dir
else
# XDG
xdg_data_home = ENV["XDG_DATA_HOME"] || File.join(File.expand_path("~"), '.local', 'share')
unless File.exist?(xdg_data_home)
FileUtils.mkdir_p xdg_data_home
end
File.join xdg_data_home, "rdoc"
end
end
autoload :RDoc, 'rdoc/rdoc'
autoload :CrossReference, 'rdoc/cross_reference'

View file

@ -14,10 +14,7 @@ module RDoc::RI::Paths
BASE = File.join RbConfig::CONFIG['ridir'], version
HOMEDIR = begin
File.expand_path('~/.rdoc')
rescue ArgumentError
end
HOMEDIR = RDoc.home
#:startdoc:
##

View file

@ -482,7 +482,7 @@ class RDoc::Store
when :gem then
parent = File.expand_path '..', @path
"gem #{File.basename parent}"
when :home then '~/.rdoc'
when :home then RDoc.home
when :site then 'ruby site'
when :system then 'ruby core'
else @path

View file

@ -337,13 +337,6 @@ module Gem
Gem::Security.reset if defined?(Gem::Security)
end
##
# The path to standard location of the user's .gemrc file.
def self.config_file
@config_file ||= File.join Gem.user_home, '.gemrc'
end
##
# The standard configuration object for gems.
@ -557,33 +550,6 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
return files
end
##
# Finds the user's home directory.
#--
# Some comments from the ruby-talk list regarding finding the home
# directory:
#
# I have HOME, USERPROFILE and HOMEDRIVE + HOMEPATH. Ruby seems
# to be depending on HOME in those code samples. I propose that
# it should fallback to USERPROFILE and HOMEDRIVE + HOMEPATH (at
# least on Win32).
#++
#--
#
#++
def self.find_home
Dir.home.dup
rescue
if Gem.win_platform?
File.expand_path File.join(ENV['HOMEDRIVE'] || ENV['SystemDrive'], '/')
else
File.expand_path "/"
end
end
private_class_method :find_home
##
# Top level install helper method. Allows you to install gems interactively:
#
@ -1056,13 +1022,6 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
self.paths = hash
end
##
# The home directory for the user.
def self.user_home
@user_home ||= find_home.tap(&Gem::UNTAINT)
end
##
# Is this a windows platform?

View file

@ -261,7 +261,12 @@ if you believe they were disclosed to a third party.
# Location of RubyGems.org credentials
def credentials_path
File.join Gem.user_home, '.gem', 'credentials'
credentials = File.join Gem.user_home, '.gem', 'credentials'
if File.exist? credentials
credentials
else
File.join Gem.data_home, "gem", "credentials"
end
end
def load_api_keys
@ -444,6 +449,10 @@ if you believe they were disclosed to a third party.
# Writes out this config file, replacing its source.
def write
unless File.exist?(File.dirname(config_file_name))
FileUtils.mkdir_p File.dirname(config_file_name)
end
File.open config_file_name, 'w' do |io|
io.write to_yaml
end

View file

@ -20,7 +20,13 @@ module Gem
# specified in the environment
def self.default_spec_cache_dir
File.join Gem.user_home, '.gem', 'specs'
default_spec_cache_dir = File.join Gem.user_home, '.gem', 'specs'
unless File.exist?(default_spec_cache_dir)
default_spec_cache_dir = File.join Gem.data_home, 'gem', 'specs'
end
default_spec_cache_dir
end
##
@ -70,15 +76,91 @@ module Gem
File.join(Gem.default_dir, "specifications", "default")
end
##
# Finds the user's home directory.
#--
# Some comments from the ruby-talk list regarding finding the home
# directory:
#
# I have HOME, USERPROFILE and HOMEDRIVE + HOMEPATH. Ruby seems
# to be depending on HOME in those code samples. I propose that
# it should fallback to USERPROFILE and HOMEDRIVE + HOMEPATH (at
# least on Win32).
#++
#--
#
#++
def self.find_home
Dir.home.dup
rescue
if Gem.win_platform?
File.expand_path File.join(ENV['HOMEDRIVE'] || ENV['SystemDrive'], '/')
else
File.expand_path "/"
end
end
private_class_method :find_home
##
# The home directory for the user.
def self.user_home
@user_home ||= find_home.tap(&Gem::UNTAINT)
end
##
# Path for gems in the user's home directory
def self.user_dir
parts = [Gem.user_home, '.gem', ruby_engine]
gem_dir = File.join(Gem.user_home, ".gem")
gem_dir = File.join(Gem.data_home, "gem") unless File.exist?(gem_dir)
parts = [gem_dir, ruby_engine]
parts << RbConfig::CONFIG['ruby_version'] unless RbConfig::CONFIG['ruby_version'].empty?
File.join parts
end
##
# The path to standard location of the user's configuration directory.
def self.config_home
@config_home ||= (ENV["XDG_CONFIG_HOME"] || File.join(Gem.user_home, '.config'))
end
##
# Finds the user's config file
def self.find_config_file
gemrc = File.join Gem.user_home, '.gemrc'
if File.exist? gemrc
gemrc
else
File.join Gem.config_home, "gem", "gemrc"
end
end
##
# The path to standard location of the user's .gemrc file.
def self.config_file
@config_file ||= find_config_file.tap(&Gem::UNTAINT)
end
##
# The path to standard location of the user's cache directory.
def self.cache_home
@cache_home ||= (ENV["XDG_CACHE_HOME"] || File.join(Gem.user_home, '.cache'))
end
##
# The path to standard location of the user's data directory.
def self.data_home
@data_home ||= (ENV["XDG_DATA_HOME"] || File.join(Gem.user_home, '.local', 'share'))
end
##
# How String Gem paths should be split. Overridable for esoteric platforms.
@ -130,14 +212,26 @@ module Gem
# The default signing key path
def self.default_key_path
File.join Gem.user_home, ".gem", "gem-private_key.pem"
default_key_path = File.join Gem.user_home, ".gem", "gem-private_key.pem"
unless File.exist?(default_key_path)
default_key_path = File.join Gem.data_home, "gem", "gem-private_key.pem"
end
default_key_path
end
##
# The default signing certificate chain path
def self.default_cert_path
File.join Gem.user_home, ".gem", "gem-public_cert.pem"
default_cert_path = File.join Gem.user_home, ".gem", "gem-public_cert.pem"
unless File.exist?(default_cert_path)
default_cert_path = File.join Gem.data_home, "gem", "gem-public_cert.pem"
end
default_cert_path
end
##

View file

@ -19,7 +19,7 @@ module Gem::GemcutterUtilities
def add_key_option
add_option('-k', '--key KEYNAME', Symbol,
'Use the given API key',
'from ~/.gem/credentials') do |value,options|
"from #{Gem.configuration.credentials_path}") do |value,options|
options[:key] = value
end
end

View file

@ -363,6 +363,13 @@ class Gem::TestCase < (defined?(Minitest::Test) ? Minitest::Test : MiniTest::Uni
Dir.chdir @tempdir
ENV['HOME'] = @userhome
FileUtils.mkdir_p File.join(@userhome, ".gem")
File.write File.join(@userhome, ".gemrc"), "--- {}"
temp_cred = File.join(@userhome, '.gem', 'credentials')
FileUtils.mkdir_p File.dirname(temp_cred)
File.write temp_cred, ':rubygems_api_key: 701229f217cdf23b1344c7b4b54ca97'
File.chmod 0600, temp_cred
Gem.instance_variable_set :@user_home, nil
Gem.instance_variable_set :@gemdeps, nil
Gem.instance_variable_set :@env_requirements_by_name, nil

View file

@ -41,11 +41,17 @@ RSpec.describe Bundler::Env do
end
it "prints user path" do
if Gem::VERSION >= "3.2.0.pre.1"
allow(Gem).to receive(:data_home) { "/a/b/c/.local/share" }
out = described_class.report
expect(out).to include("User Path /a/b/c/.local/share/gem")
else
with_clear_paths("HOME", "/a/b/c") do
out = described_class.report
expect(out).to include("User Path /a/b/c/.gem")
end
end
end
it "prints bin dir" do
with_clear_paths("GEM_HOME", "/a/b/c") do

View file

@ -6,7 +6,10 @@ require "cgi"
RSpec.describe Bundler, "friendly errors" do
context "with invalid YAML in .gemrc" do
let(:config_home) { File.dirname(Gem.configuration.config_file_name) }
before do
FileUtils.mkdir_p config_home
File.open(Gem.configuration.config_file_name, "w") do |f|
f.write "invalid: yaml: hah"
end
@ -24,7 +27,11 @@ RSpec.describe Bundler, "friendly errors" do
bundle :install, :env => { "DEBUG" => "true" }
if Gem::VERSION >= "3.2.0.pre.1"
expect(err).to include("Failed to load #{File.join(config_home, "gemrc")}")
else
expect(err).to include("Failed to load #{home(".gemrc")}")
end
expect(exitstatus).to eq(0) if exitstatus
end
end

View file

@ -15,6 +15,8 @@ class TestRDocRIDriver < RDoc::TestCase
@orig_ri = ENV['RI']
@orig_home = ENV['HOME']
ENV['HOME'] = @tmpdir
@rdoc_home = File.join ENV["HOME"], ".rdoc"
FileUtils.mkdir_p @rdoc_home
ENV.delete 'RI'
@options = RDoc::RI::Driver.default_options
@ -81,7 +83,7 @@ class TestRDocRIDriver < RDoc::TestCase
@RM::Rule.new(1),
@RM::Paragraph.new('Also found in:'),
@RM::Verbatim.new("ruby core", "\n",
"~/.rdoc", "\n"))
@rdoc_home, "\n"))
assert_equal expected, out
end
@ -231,7 +233,7 @@ class TestRDocRIDriver < RDoc::TestCase
doc(
head(1, 'Foo::Bar#blah'),
blank_line,
para('(from ~/.rdoc)'),
para("(from #{@rdoc_home})"),
head(3, 'Implementation from Bar'),
rule(1),
verb("blah(5) => 5\n",
@ -254,7 +256,7 @@ class TestRDocRIDriver < RDoc::TestCase
doc(
head(1, 'Qux#aliased'),
blank_line,
para('(from ~/.rdoc)'),
para("(from #{@rdoc_home})"),
rule(1),
blank_line,
para('alias comment'),
@ -280,7 +282,7 @@ class TestRDocRIDriver < RDoc::TestCase
doc(
head(1, 'Foo::Bar#attr'),
blank_line,
para('(from ~/.rdoc)'),
para("(from #{@rdoc_home})"),
rule(1),
blank_line,
blank_line)
@ -299,7 +301,7 @@ class TestRDocRIDriver < RDoc::TestCase
doc(
head(1, 'Bar#inherit'),
blank_line,
para('(from ~/.rdoc)'),
para("(from #{@rdoc_home})"),
head(3, 'Implementation from Foo'),
rule(1),
blank_line,
@ -343,13 +345,13 @@ class TestRDocRIDriver < RDoc::TestCase
doc(
head(1, 'Foo#inherit'),
blank_line,
para('(from ~/.rdoc)'),
para("(from #{@rdoc_home})"),
rule(1),
blank_line,
blank_line,
head(1, 'Foo#override'),
blank_line,
para('(from ~/.rdoc)'),
para("(from #{@rdoc_home})"),
rule(1),
blank_line,
para('must not be displayed in Bar#override'),
@ -802,7 +804,7 @@ Foo::Bar#bother
@driver.display_page 'home:README'
end
assert_match %r%= README pages in ~/\.rdoc%, out
assert_match %r%= README pages in #{@rdoc_home}%, out
assert_match %r%README\.rdoc%, out
assert_match %r%README\.md%, out
end
@ -856,7 +858,7 @@ Foo::Bar#bother
@driver.display_page_list @store1
end
assert_match %r%= Pages in ~/\.rdoc%, out
assert_match %r%= Pages in #{@rdoc_home}%, out
assert_match %r%README\.rdoc%, out
end
@ -876,7 +878,7 @@ Foo::Bar#bother
@driver.display_page_list @store1
end
assert_match %r%= Pages in ~/\.rdoc%, out
assert_match %r%= Pages in #{@rdoc_home}%, out
assert_match %r%README\.rdoc%, out
assert_match %r%OTHER\.rdoc%, out
end

View file

@ -317,6 +317,9 @@ class TestRDocStore < XrefTestCase
end
def test_friendly_path
@orig_xdg_data_home = ENV['XDG_DATA_HOME']
ENV.delete('XDG_DATA_HOME')
@s.path = @tmpdir
@s.type = nil
assert_equal @s.path, @s.friendly_path
@ -331,11 +334,13 @@ class TestRDocStore < XrefTestCase
assert_equal "ruby site", @s.friendly_path
@s.type = :home
assert_equal "~/.rdoc", @s.friendly_path
assert_equal File.expand_path("~/.local/share/rdoc"), @s.friendly_path
@s.type = :gem
@s.path = "#{@tmpdir}/gem_repository/doc/gem_name-1.0/ri"
assert_equal "gem gem_name-1.0", @s.friendly_path
ensure
ENV['XDG_DATA_HOME'] = @orig_xdg_data_home
end
def test_dry_run

View file

@ -1359,6 +1359,8 @@ class TestGem < Gem::TestCase
parts = [@userhome, '.gem', Gem.ruby_engine]
parts << RbConfig::CONFIG['ruby_version'] unless RbConfig::CONFIG['ruby_version'].empty?
FileUtils.mkdir_p File.join(parts)
assert_equal File.join(parts), Gem.user_dir
end

View file

@ -376,7 +376,6 @@ class TestGemCommandsBuildCommand < Gem::TestCase
skip 'openssl is missing' unless defined?(OpenSSL::SSL) && !java_platform?
gem_path = File.join Gem.user_home, ".gem"
Dir.mkdir gem_path
Gem::Security.trust_dir
@ -420,7 +419,6 @@ class TestGemCommandsBuildCommand < Gem::TestCase
skip 'openssl is missing' unless defined?(OpenSSL::SSL) && !java_platform?
gem_path = File.join Gem.user_home, ".gem"
Dir.mkdir gem_path
Gem::Security.trust_dir

View file

@ -597,7 +597,6 @@ ERROR: --private-key not specified and ~/.gem/gem-private_key.pem does not exis
def test_execute_re_sign
gem_path = File.join Gem.user_home, ".gem"
Dir.mkdir gem_path
path = File.join @tempdir, 'cert.pem'
Gem::Security.write EXPIRED_PUBLIC_CERT, path, 0600
@ -628,9 +627,6 @@ ERROR: --private-key not specified and ~/.gem/gem-private_key.pem does not exis
end
def test_execute_re_sign_with_cert_expiration_length_days
gem_path = File.join Gem.user_home, ".gem"
Dir.mkdir gem_path
path = File.join @tempdir, 'cert.pem'
Gem::Security.write EXPIRED_PUBLIC_CERT, path, 0600

View file

@ -8,6 +8,7 @@ class TestGemCommandsSignoutCommand < Gem::TestCase
def setup
super
File.delete Gem.configuration.credentials_path if File.exist?(Gem.configuration.credentials_path)
@cmd = Gem::Commands::SignoutCommand.new
end

View file

@ -170,7 +170,7 @@ class TestGemConfigFile < Gem::TestCase
assert_nil @cfg.instance_variable_get :@api_keys
temp_cred = File.join Gem.user_home, '.gem', 'credentials'
FileUtils.mkdir File.dirname(temp_cred)
FileUtils.mkdir_p File.dirname(temp_cred)
File.open temp_cred, 'w', 0600 do |fp|
fp.puts ':rubygems_api_key: 701229f217cdf23b1344c7b4b54ca97'
end
@ -296,7 +296,7 @@ if you believe they were disclosed to a third party.
def test_load_api_keys
temp_cred = File.join Gem.user_home, '.gem', 'credentials'
FileUtils.mkdir File.dirname(temp_cred)
FileUtils.mkdir_p File.dirname(temp_cred)
File.open temp_cred, 'w', 0600 do |fp|
fp.puts ":rubygems_api_key: 701229f217cdf23b1344c7b4b54ca97"
fp.puts ":other: a5fdbb6ba150cbb83aad2bb2fede64c"

View file

@ -230,7 +230,7 @@ class TestGemSource < Gem::TestCase
end
def test_update_cache_eh_home_nonexistent
FileUtils.rmdir Gem.user_home
FileUtils.rm_rf Gem.user_home
refute @source.update_cache?
end

View file

@ -33,7 +33,7 @@ class TestGemSpecFetcher < Gem::TestCase
end
def test_initialize_nonexistent_home_dir
FileUtils.rmdir Gem.user_home
FileUtils.rm_rf Gem.user_home
assert Gem::SpecFetcher.new
end