rubygems/rubygems

gem signin raise "NameError: uninitialized constant Gem::ConfigFile::FileUtils"

ybiquitous opened this issue ยท 6 comments

I'm having a problem or would like to suggest a feature.

My current problem is that the gem signin command raises "NameError: uninitialized constant Gem::ConfigFile::FileUtils" if the ~/.local/share/gem directory does not exist.

Here is a reproduction:

$ bin/gem --debug signin
NOTE:  Debugging mode prints all exceptions even when rescued
Enter your RubyGems.org credentials.
Don't have an account yet? Create one at https://rubygems.org/sign_up
   Email:   ybiquitous
Password:

API Key name [F200420NT01.local-masafumi.koba-20210715184510]:
Please select scopes you want to enable for the API key (y/n)
index_rubygems [y/N]:   y
push_rubygem [y/N]:
yank_rubygem [y/N]:
add_owner [y/N]:
remove_owner [y/N]:
access_webhooks [y/N]:
show_dashboard [y/N]:

You have enabled multi-factor authentication. Please enter OTP code.
Code:   316891
Signed in with API key: F200420NT01.local-masafumi.koba-20210715184510.
Exception `NameError' at /Users/masafumi.koba/.rbenv/versions/3.0.2/lib/ruby/site_ruby/3.0.0/rubygems/config_file.rb:323 - uninitialized constant Gem::ConfigFile::FileUtils
Did you mean?  FileTest
ERROR:  While executing gem ... (NameError)
    uninitialized constant Gem::ConfigFile::FileUtils
Did you mean?  FileTest
	/Users/masafumi.koba/.rbenv/versions/3.0.2/lib/ruby/site_ruby/3.0.0/rubygems/config_file.rb:323:in `set_api_key'
	/Users/masafumi.koba/.rbenv/versions/3.0.2/lib/ruby/site_ruby/3.0.0/rubygems/config_file.rb:309:in `rubygems_api_key='
	/Users/masafumi.koba/.rbenv/versions/3.0.2/lib/ruby/site_ruby/3.0.0/rubygems/gemcutter_utilities.rb:222:in `set_api_key'
	/Users/masafumi.koba/.rbenv/versions/3.0.2/lib/ruby/site_ruby/3.0.0/rubygems/gemcutter_utilities.rb:175:in `block in sign_in'
	/Users/masafumi.koba/.rbenv/versions/3.0.2/lib/ruby/site_ruby/3.0.0/rubygems/gemcutter_utilities.rb:203:in `with_response'
	/Users/masafumi.koba/.rbenv/versions/3.0.2/lib/ruby/site_ruby/3.0.0/rubygems/gemcutter_utilities.rb:173:in `sign_in'
	/Users/masafumi.koba/.rbenv/versions/3.0.2/lib/ruby/site_ruby/3.0.0/rubygems/commands/signin_command.rb:31:in `execute'
	/Users/masafumi.koba/.rbenv/versions/3.0.2/lib/ruby/site_ruby/3.0.0/rubygems/command.rb:323:in `invoke_with_build_args'
	/Users/masafumi.koba/.rbenv/versions/3.0.2/lib/ruby/site_ruby/3.0.0/rubygems/command_manager.rb:178:in `process_args'
	/Users/masafumi.koba/.rbenv/versions/3.0.2/lib/ruby/site_ruby/3.0.0/rubygems/command_manager.rb:147:in `run'
	/Users/masafumi.koba/.rbenv/versions/3.0.2/lib/ruby/site_ruby/3.0.0/rubygems/gem_runner.rb:53:in `run'
	bin/gem:13:in `<main>'

When I add a patch require 'fileutils' before calling FileUtils.mkdir_p(dirname), the command works.

FileUtils.mkdir_p(dirname) unless File.exist? dirname

This issue is related to:

  • Network problems
  • Installing a library
  • Publishing a library
  • The command line gem
  • Other

Here are my current environment details:

$ gem env version
3.3.0.dev

I will abide by the code of conduct.

In addition, my ruby version is:

$ ruby -v
ruby 3.0.2p107 (2021-07-07 revision 0db68f0233) [x86_64-darwin20]

Thanks, can you send a PR?

Yes! ๐Ÿ’ช๐Ÿผ


BTW, I notice a workaround to specify RUBYOPT=-rfileutils gem signin instead of adding such a patch... ๐Ÿ˜…

I have a question. Can we require 'fileutils' only at the top-level (lib/rubygems.rb)?

Currently, there are 70 locations using FileUtils, but it seems to be not DRY to add require 'fileutils' to all... ๐Ÿค”

$ git grep 'FileUtils' lib/rubygems | wc -l
      70

$ git grep 'fileutils' lib/rubygems
lib/rubygems/commands/rdoc_command.rb:5:require 'fileutils'
lib/rubygems/commands/setup_command.rb:161:    require 'fileutils'
lib/rubygems/commands/sources_command.rb:11:    require 'fileutils'
lib/rubygems/commands/uninstall_command.rb:5:require 'fileutils'
lib/rubygems/commands/unpack_command.rb:20:    require 'fileutils'
lib/rubygems/ext/builder.rb:187:    require "fileutils"
lib/rubygems/ext/ext_conf_builder.rb:12:    require 'fileutils'
lib/rubygems/indexer.rb:46:    require 'fileutils'
lib/rubygems/installer.rb:172:    require 'fileutils'
lib/rubygems/installer.rb:499:        require 'fileutils'
lib/rubygems/installer.rb:536:    require 'fileutils'
lib/rubygems/package/old.rb:22:    require 'fileutils'
lib/rubygems/package_task.rb:85:    @fileutils_output = $stdout
lib/rubygems/remote_fetcher.rb:130:    require "fileutils"
lib/rubygems/security/trust_dir.rb:107:    require 'fileutils'
lib/rubygems/source.rb:157:      require "fileutils"
lib/rubygems/source.rb:190:      require "fileutils"
lib/rubygems/uninstaller.rb:8:require 'fileutils'

No, better inline. In general we prefer to require default gems as lazily as possible. Sometimes requiring them at the top level messes with the end user version choice of the default gem and causes issues.

@deivid-rodriguez Thanks, I understand now.

BTW, we tend to forget that we must require fileutils before using FileUtils, so there hopefully would be a better solution... ๐Ÿ˜