When both Ruby 1.8.x and 1.9.x is installed and gems with executables are installed using the "gem" comman rather than Portage (e.g. because the gems are installed by a rake task or because a gem is not available as an ebuild which is true for most bleeding edge gems from Github), the following can happen: eselect ruby set ruby18 gem install rake # => /usr/bin/rake is created with shebang ruby18 eselect ruby set ruby19 gem install rake # => /usr/bin/rake is overwritten with shebang ruby19 eselect ruby set ruby18 # => /usr/bin/rake still uses ruby19 Furthermore if different versions of gems are used on the two profiles, the executables will still be overwritten and cause inconsistencies. Reproducible: Always Steps to Reproduce: Here's a solution: (1) Extend the ruby.ebuild (for Ruby 1.9) and rubygems.ebuild to install the file /etc/gemrc with the following content: <snippet begins> --- gem: --format-executable <snippet ends> This will cause all executables installed by the "gem" command to get the version postfix 18 or 19, e.g. /usr/bin/rake18. (2) Apply the attached patch to eselect-ruby.ebuild. It extends the "create_symlinks" part to remove all unversioned executables and creates symlinks to the versioned executables. (3) Add informational text to eselect-ruby.ebuild, something like: <snippet begins> If you install gems with executables using the gem command, make sure to run the following command to make the executables available without version postfix: eselect ruby set `eselect ruby show | grep ruby` Furthermore, if you see this message for the first time, you should re-install all gems with executables in order to built them correctly. <snippet ends> (4) Maybe a good extra would be a "rebuild" action for "eselect ruby" which sets the current profile as the command in (3) does. I've tried this approach with Ruby 1.8.x and 1.9.x and it works fine so far. Big thanks for considering this patch!
Created attachment 190541 [details, diff] Patch to switch executables installed with the "gem" command.
Does this patch also work correctly when using eselect on gem modules? E.g. rails.eselect for Rails, or the more generic but still experimental gem.eselect module from the ruby overlay which manages gem binary symlinks for multiple slots.
I guess it can be made compatible with rails.eselect (and gem.eselect which I haven't yet checked out). But I'm not sure whether it's a good idea to introduce/use slotting for gems in the first place, because RubyGems already has slotting of sorts in place. Here's what the gem help says: > For example `rake _0.7.3_ --version` will run rake version 0.7.3 if a newer > version is also installed. Is there a reason for having additional slotting on Portage level? Maybe redesigning gem.eselect to use the RubyGems slotting would be good common ground? (I've extended the patch to include a "rebuild" task as described in (4) above.)
Created attachment 190604 [details, diff] Patch to switch executables installed with the "gem" command.
(In reply to comment #3) > the first place, because RubyGems already has slotting of sorts in place. > Here's what the gem help says: > > > For example `rake _0.7.3_ --version` will run rake version 0.7.3 if a newer > > version is also installed. > > Is there a reason for having additional slotting on Portage level? Maybe > redesigning gem.eselect to use the RubyGems slotting would be good common > ground? rubygems slotting works fine for the files in /usr/lib/ruby/gems, but it simply overwrites the binaries in /usr/bin, so you'll end up with whatever the last version of the gem installed there. This usually works fine anyway since most of these /usr/bin files are just thin wrappers around invoking the code in /usr/lib, and many of them use the trick described above with rake to allow executing a particular version. There are two problems with this: 1) portage does not allow this overwriting and will complain when one slot tries to overwrite files installed by another. 2) there are cases where the binaries between versions are not the same (gettext comes to mind here). 2. may be an exception that we could solve in a different way, but in any case we need to solve 1.
> 1) portage does not allow this overwriting and will complain when one slot > tries to overwrite files installed by another. The clean solution would be a patch to Portage: Allow a file to belong to more than one slot and only delete it once the last owning slot is uninstalled. I don't know the guts of Portage well enough to tell whether this is doable, sounds like it to an outsider. What do you think? > 2) there are cases where the binaries between versions are not the same > (gettext comes to mind here). This is IMHO an upstream issue and if gettext breaks this behaviour, then it should be fixed there by slimming down the executable to a mere wrapper - as do the others.
(In reply to comment #6) > The clean solution would be a patch to Portage: Allow a file to belong to more > than one slot and only delete it once the last owning slot is uninstalled. > > I don't know the guts of Portage well enough to tell whether this is doable, > sounds like it to an outsider. What do you think? It sounds like an interesting idea, but I have no clue how feasible this is for portage or the other package managers. This would probably need to be an EAPI-related functionality. Perhaps you could raise this issue on the gentoo-dev list and see what happens?
I guess this can be closed; while not perfect, the current fakegem solution fixes the problem of gems for multiple Ruby versions; just use ruby18 -S $foo or ruby19 -S $foo to get it with the non-default implementation.