Rubygems: Avoid RDoc dependency

Created on 20 Nov 2018  路  2Comments  路  Source: rubygems/rubygems

In stable versions of RubyGems, it was possible to install gems without RDoc available:

~
$ gem install gem2rpm
Fetching: gem2rpm-1.0.1.gem (100%)
WARNING: You don't have /builddir/bin in your PATH,
gem executables will not run.
Successfully installed gem2rpm-1.0.1
ERROR: While executing gem ... (Gem::DocumentError)
RDoc is not installed: cannot load such file -- rdoc/rdoc
~

Yes, it complained a bit, but the installation of gem was successful. With --no-doc option, it does not even complain.

However, for RubyGems 3.0.0.beta2, the same scenario fails:

~
$ RUBYOPT=-d gem ins gem2rpm --no-document
Exception LoadError' at /usr/share/rubygems/rubygems.rb:1384 - cannot load such file -- rubygems/defaults/ruby ExceptionGem::MissingSpecError' at /usr/share/rubygems/rubygems/dependency.rb:311 - Gem::MissingSpecError
Exception LoadError' at /usr/share/rubygems/rubygems/core_ext/kernel_require.rb:54 - cannot load such file -- abrt ExceptionLoadError' at /usr/share/rubygems/rubygems/core_ext/kernel_require.rb:132 - cannot load such file -- abrt
Exception LoadError' at /usr/share/rubygems/rubygems/core_ext/kernel_require.rb:54 - cannot load such file -- 2.6/psych.so ExceptionLoadError' at /usr/share/rubygems/rubygems/core_ext/kernel_require.rb:132 - cannot load such file -- 2.6/psych.so
Exception NameError' at /usr/share/ruby/psych/class_loader.rb:68 - uninitialized constant BigDecimal ExceptionNameError' at /usr/share/ruby/psych/class_loader.rb:68 - uninitialized constant Date
Exception NameError' at /usr/share/ruby/psych/class_loader.rb:68 - uninitialized constant DateTime ExceptionNameError' at /usr/share/rubygems/rubygems/syck_hack.rb:43 - method to_s' not defined in Psych::Syck::DefaultKey ExceptionLoadError' at /usr/share/ruby/resolv.rb:170 - LoadError
Exception Gem::MissingSpecError' at /usr/share/rubygems/rubygems/dependency.rb:311 - Gem::MissingSpecError ExceptionLoadError' at /usr/share/rubygems/rubygems/core_ext/kernel_require.rb:54 - cannot load such file -- rdoc/rubygems_hook
Exception LoadError' at /usr/share/rubygems/rubygems/core_ext/kernel_require.rb:132 - cannot load such file -- rdoc/rubygems_hook ExceptionNameError' at /usr/share/rubygems/rubygems/rdoc.rb:24 - uninitialized constant Gem::RDoc
Exception NameError' at /usr/share/rubygems/rubygems/core_ext/kernel_require.rb:54 - uninitialized constant Gem::RDoc ERROR: While executing gem ... (NameError) uninitialized constant Gem::RDoc /usr/share/rubygems/rubygems/rdoc.rb:24:in /usr/share/rubygems/rubygems/core_ext/kernel_require.rb:54:in require' /usr/share/rubygems/rubygems/core_ext/kernel_require.rb:54:inrequire'
/usr/share/rubygems/rubygems/commands/install_command.rb:293:in load_hooks' /usr/share/rubygems/rubygems/commands/install_command.rb:164:inexecute'
/usr/share/rubygems/rubygems/command.rb:321:in invoke_with_build_args' /usr/share/rubygems/rubygems/command_manager.rb:176:inprocess_args'
/usr/share/rubygems/rubygems/command_manager.rb:146:in run' /usr/share/rubygems/rubygems/gem_runner.rb:59:inrun'
/usr/bin/gem:21:in `

'
~

This is very likely due to #2235. You might admit that RDoc is now part of StdLib, but IMO, this interdependency is something, what should be avoided at all cost. Because now, RDoc is a dependency of RubyGems while RubyGems is a dependency of RDoc, which makes nice unbreakable circular dependency. In the end, while the StdLib will appear as a bunch of independent libraries, it won't be possible to separate them.

Now I wonder how to solve this issue. Thinking about it, I believe that the best option is to revert #2235 and remove the https://github.com/ruby/rdoc/blob/master/lib/rdoc/rubygems_hook.rb from RDoc. I don't understand how and why it got into RDoc, but it feels wrong. RubyGems is using RDoc, RubyGems is RDoc client, not the opposite way. @hsbt thoughts?

bug report

Most helpful comment

This file https://github.com/rubygems/rubygems/blob/master/lib/rubygems/rdoc.rb contains following code

begin
  require 'rdoc/rubygems_hook'
  module Gem
    RDoc = ::RDoc::RubygemsHook
  end
rescue LoadError
end

Gem.done_installing(&Gem::RDoc.method(:generation_hook))

Gem::RDoc is defined inside begin-rescue section but used outside. If rdoc gem is not available then the block gets LoadError so no Gem::RDoc. In this case Gem.done_installing fails. Gem.done_installing needs to be moved to begin-rescue as well:

begin
  require 'rdoc/rubygems_hook'
  module Gem
    RDoc = ::RDoc::RubygemsHook
  end

  Gem.done_installing(&Gem::RDoc.method(:generation_hook))
rescue LoadError
end

All 2 comments

Arch Linux bumped rubygems and now I see this issue with multiple packages. Currently Arch Linux ruby 2.6 migration is blocked by this issue.

Is there any workaround for the given problem?

This file https://github.com/rubygems/rubygems/blob/master/lib/rubygems/rdoc.rb contains following code

begin
  require 'rdoc/rubygems_hook'
  module Gem
    RDoc = ::RDoc::RubygemsHook
  end
rescue LoadError
end

Gem.done_installing(&Gem::RDoc.method(:generation_hook))

Gem::RDoc is defined inside begin-rescue section but used outside. If rdoc gem is not available then the block gets LoadError so no Gem::RDoc. In this case Gem.done_installing fails. Gem.done_installing needs to be moved to begin-rescue as well:

begin
  require 'rdoc/rubygems_hook'
  module Gem
    RDoc = ::RDoc::RubygemsHook
  end

  Gem.done_installing(&Gem::RDoc.method(:generation_hook))
rescue LoadError
end
Was this page helpful?
0 / 5 - 0 ratings