Hi,
I recently had an idea of faking load paths [0] to satisfy bundler's loading and help bring our behavior closer to upstream while still unbundling the libraries.
To automatically test for the usual user's workflow with bundler
and a default gem (only RDoc so far),
I have created small TMT test suite [1]. It pulls the Ruby RPMs
from my copr repo
https://copr.fedorainfracloud.org/coprs/jackorp/ruby-rdoc-default-gem/
.
It is adjustable to fit your own copr if you wish to do your own
changes [2], TMT can also install RPMs from a local directory, but
that's going off-topic.
One of my TODO item here is to validate this against some rbenv
Ruby install.
To the loading itself and my examination.
Default gems seem to skip bundler somewhere and go their own path
which is more similar to regular `Kernel.require`
without bundler.
Therefore, just having it on the default load path, where default
gems are expected to exist is enough.
However, regular Ruby loading also means that it expects a certain
layout that it won't search for itself if it can't find a subfile,
see Rake and `rdoc/task` below.
So, if we place `rdoc.rb` into `/usr/share/ruby/` that adjusts the load
path accordingly and then just passes on the require, that's
enough if the code is either
~~~
$ cat foo.rb
require 'rdoc'
p RDoc::VERSION # Demonstrate that RDoc is available
~~~
and run with bundler `bundle exec
ruby ./foo.rb`.
or in CLI like this: `bundle exec ruby
-rrdoc -e 'p RDoc::VERSION'`.
In both cases, the associated Gemfile is empty. No gems are
recored in the file.
My approach, at this point in time, falls apart with Rake and
RDoc using `require rdoc/task`, as
there is no /usr/share/ruby/rdoc/task.rb.
I am unable to track down the exact code path,
but it seems to skip some places inside bundler, even rubygems,
that could otherwise make it possible to work (with a few minor
adjustments of course).
This demostrated a problem, we'd have to fake out the whole
structure of any gem we'd like to unbundle this way.
That, of course, is a possibility.
So the pros / cons of this approach currently seem:
+ we'd unbundle default gems away
+ no more symlinks.
+ closer to upstream behavior for the users
- We'd have to retain the structure and provide each "fake" path
to a file.
* Though we are doing something a small bit similar with the
symlinks.
- added complexity of writing correct paths into the files on
their correct places.
Alternatively, this is just an academic idea, populate the
default load path with default gems.
I, however, do not know where would the right place for that be,
or what would be the cons of this approach
(apart from potentially breaking expectations set accross the
whole Ruby environment for loadables).
Also to adjust the Kernel.require,
but that feels very wrong (also potentially unsafe, as the code is
in C AFAICT, and very divergent from upstream).
But I have quickly dismissed these as I have high doubts such
patches would ever be accepted upstream and maintainability of
such approaches is quetionable at best.
Additionally, I am not sure what should be the behaviour with the plain rdoc executable and bundler executed like this: `bundle exec rdoc`
I will try to apply the approach of faking the whole gem
directory and file tree in /usr/share/ruby for RDoc and record my
findings.
I am open to discussion, should you want to share your thoughts
or ideas regarding this topic.
Regards,
Jarek Prokop
[0]
https://src.fedoraproject.org/fork/jackorp/rpms/ruby/c/1f660500090ad6d176a98a2e0883d69810b98da8?branch=rdoc_require_stub
[1] https://gitlab.com/jackorp/test_default_gem_fedora_ruby
[2]
https://gitlab.com/jackorp/test_default_gem_fedora_ruby/-/blob/76581956440fc465dd37c13f62d114b18943b901/plans/main.fmf#L7