[Fedora-packaging] New packaging guidelines for Ruby

Bohuslav Kabrda bkabrda at redhat.com
Mon Mar 5 06:50:04 UTC 2012


----- Original Message -----
> On Fri, Mar 02, 2012 at 12:42:26AM -0500, Bohuslav Kabrda wrote:
> > ----- Original Message -----
> > > On Tue, Feb 28, 2012 at 4:47 AM, Bohuslav Kabrda
> > > <bkabrda at redhat.com>
> > > wrote:
> > > > ----- Original Message -----
> > > >> = ruby(name) vs rubygems(name) =
> > > >
> > > > Here is one important reason why Gems should not provide
> > > > ruby(name):
> > > > The ruby(name) provides are supposed to be provided by the
> > > > libraries, that are meant to be directly loadable with "require
> > > > 'name'" even without Rubygems library. The Rubygems are loaded
> > > > by
> > > > default in Ruby 1.9.3, but the users may choose not to load
> > > > them
> > > > by passing "--disable-gems" option to the interpreter (either
> > > > directly or via environment variable RUBYOPT).
> > > > For a user, who turns of his Rubygems, a packaged Gem providing
> > > > ruby(name) wouldn't load, while some other non-gem package
> > > > providing ruby(name) would load, which is obviously a puzzling
> > > > behaviour.
> > > >
> > > If the guidelines are to assume that people are going to be
> > > passing
> > > --disable-gems then they must require that non-gem subpackages
> > > exist
> > > for all gems.  When a packager packages something that requires
> > > other
> > > ruby libraries they *must* inspect the code to see whether the
> > > code
> > > requires the gem or non-gem form.  Otherwise, libraries,
> > > applications,
> > > and scripts will break when the user runs with the --disable-gems
> > > option.
> > > 
> > > However, the argument that non-gem is legacy behaviour and should
> > > no
> > > longer be represented in packaging has been made.  After looking
> > > at
> > > how rubygems have become such an integral part of the ruby
> > > ecosystem,
> > > this seems reasonable to me but it does not just mean that the
> > > non-gem
> > > subpackages have been simplified away.  It also means that the
> > > Provides and Requires situation has been simplified as well.  If
> > > you
> > > want to keep the ruby()/rubygem() Provides split because people
> > > may
> > > run ruby with "--disable-gems" then we need to make non-gem
> > > subpackages mandatory as well.
> > > 
> > > -Toshio
> > 
> > A simple question: why would we mandate creating non-gem
> > subpackages? If the developer uses --disable-gems, then he knows
> > he won't be able to require any gems. He may even base his code on
> > it:
> > 
> > begin
> >   require 'mocha'
> > rescue LoadError
> >   Mocha = nil
> > end
> > 
> > if Mocha then
> >   # ...
> > else
> >   # ...
> > end
> > 
> > I believe that this simple piece of code says it all. The developer
> > may be doing something _based on the fact that rubygems are/are
> > not loaded_. Therefore creating non-gem subpackages should be
> > forbidden. Please note, that --disable-gems can be used, for
> > example, for use-cases where hundreds of ruby interpreters run in
> > parallel (not requiring rubygems can make things significantly
> > faster in this case), so I'm not just making all this up.
> > 

Hi Toshio,
I believe you didn't get my point, I'll try to explain it differently:
You have a Ruby developer that is developing on some platform (which might not be Fedora) and as Ruby developers do, he uses Rubygems (installed by gem install command) and non-Gem libraries. Let's say that the Gem is rubygem-mocha and the non-gem package is ruby-bsearch. He installs mocha with "gem install mocha" and installs ruby-bsearch as administrator somewhere under %{ruby_sitelibdir}. If he runs the mentioned code with --disable-gems, he is counting on mocha not to be requireable => therefore raise the LoadError, which he catches. In this case, he still knows that he can require ruby-bsearch, as it is requireable without Rubygems. So the application runs and does some very fast stuff, because it's programmed that way. If the application is run with Rubygems, mocha is requireable and application does something different, which takes more time to do.
Now imagine a situation, that this developer deploys his application to Fedora, where local adminstrator has installed non-Gem subpackage of mocha. All of a sudden, the application doesn't run properly, because mocha is requireable even with --disable-gems. This is why non-Gem subpackages are bad and we shouldn't create them: There is nothing like this in the Ruby world, Ruby developers simply don't need it, will never use it and it may even seriously break their applications.
Please note, that ruby-bsearch has Provides: ruby(bsearch), as it is requireable with --disable-gems and mocha has Provides: rubygem(mocha) as it is requireable only with Rubygems, which makes perfect sense.

> If the developer codes something like that then a theoretical
> packaging of
> the code does not need to have a Requires: ruby(mocha) either.  So
> this
> example doesn't show that Requires: ruby(mocha) or Requires:
> rubygem(mocha)
> would have any effect.
> 
> Here's some examples of why I think that the Requires/Provides and
> the
> subpackages go hand in hand:
> 
> (1)
> * My script has a "require 'mocha'" which, in Fedora is the packaged
> non-gem
> * mocha has a "require 'latte'" which, in Fedora is only packaged as
> a gem.
>   ruby-mocha therefore has Require: rubygem(latte)
> 
> If I run my script with --disable-gem my script will fail even though
> mocha
> was packaged as a non-gem and knew to Require the rubygem version of
> latte..
> 

And this is precisely my point. It shows how creating and having non-Gem subpackages installed may break code - a code which relies on mocha not being requireable.

> (2)
> * My script has a "require 'mocha'".
> * mocha has a "require 'latte'" which in Fedora is only packaged as a
> gem.
> * The ruby-mocha package has Require: ruby(latte) since someone could
>   attempt to run mocha with --disable-gems.  Since there's no
>   ruby(latte)
>   Provides, ruby-mocha will either not pass review or fail to yum
>   install on
>   user's systems.
> 

This shows even further, how non-Gem subpackages are not only dangerous, but also unnecessary load for the packagers.

> (3)
> * The web application better-cms is packaged in Fedora.  It Requires:
>   rubygem(latte) because it uses "require 'latte'"
> * I install that application on my server.
> * Because I want to make things faster, I try to run it with
> --disable-gems.
> * It fails because latte cannot be found if rubygems are not loaded.
> 

The developer of the better-cms knows, that if his application is run with --disable-gems, it will not work. So he may tell his users "never do this, it's not supported" or he just finds non-Gem libraries, that he can use and use them. There isn't a single person in the Ruby world that I know, who would be using something like non-Gem subpackages. They are non-standard and dangerous and as I have shown, they can break your code. So why do you want to create them?

> In all of these cases a strict Require on whether the package needs
> the gem
> or non-gem version does not have an effect on whether the code in
> question
> will run -- it fails in all instances.  In all cases, having a
> non-gem
> version of the gem libraries is one way to solve the problem.  In all
> instances, deciding that rubygems must be loaded would also solve the
> problem.
> 

Nope. The code in question will not run properly only in the case that the non-Gem subpackage is installed. Otherwise, it will work just fine and the way it was supposed to run. Moreover, the Provides: ruby(bsearch) and rubygem(mocha) make sense, since the first provide says, that the bsearch library is required with --disable-gems, while mocha is not.

> -Toshio

-- 
Regards,
Bohuslav "Slavek" Kabrda.


More information about the packaging mailing list