Fake gems
I tied together a couple of RubyGem irritations and an idea tonight.
The first is the Hoe problem. Hoe is a gem that helps people write gems. However, it also metastasises, making itself a dependency of those gems in turn. The result is that if you install a gem that was created with Hoe, you end up having to install Hoe. And yet Hoe is useless unless you’re actually developing that gem. Even then, it doesn’t really add anything.
That was historically the case, anyway. RubyGems now has the notion of development dependencies, and newer versions of Hoe are polite enough to use that. As a result, simply installing a Hoe-dependent gem for use won’t install Hoe.
… unless the gem is old, or was created with an old version of Hoe, or depends on a gem which in turn was created with an old version of Hoe. And that turns out to be rather a lot of gems. It’s almost impossible to avoid Hoe.
I admit, it’s not a huge burden to have to install Hoe. But being reminded of the annoyance earlier in the week made me wonder: what if we were to create an empty/stub/null gem that was called Hoe? We could install that instead. The dependency would be satisfied, and we’d never actually have to install Hoe.
The second irritation came to mind because I reinstalled Ubuntu on my laptop last weekend. I preserved my home directory but reinstalled the OS itself from scratch. As a result, I’ve been slowly reinstalling dependencies over the past week as I find them lacking.
I installed Mechanize via apt-get
—it depends on
Nokogiri, which requires a binary module which in turn depends on a
couple of libraries (libxml2
and libxslt
,
I think). It’s a lot easier to install one package and have the
package manager satisfy the dependencies than it is to find the
dependencies, install those via the package manager, then install
the Ruby library via RubyGems.
However, RubyGems doesn’t know that I’ve installed Mechanize or Nokogiri. If I install a third package via RubyGems that depends on either of those two, I’ll end up installing them again.
Creating a fake gem that would make RubyGems think that it’s already got, say, Nokogiri 1.3.1 installed would prevent RubyGems from building it unnecessarily.
So that’s what I’ve done. I’ve written a small library that
extends RubyGems with a gem fake
command. It installs
an empty gem of the specified name and version, fooling RubyGems
into believing that the dependency is satisfied. The default
version is 99.0.0
—that should be high enough that it
will supersede any actually existing gem versions.
You can install it via:
gem install fake-gem
To prevent Hoe from getting installed:
gem fake hoe
To say that Nokogiri 1.3.1 is already installed:
gem fake -v 1.3.1 nokogiri
You can find more information along with the code at GitHub.