Richard Crowley’s blog

Man pages versus RubyGems

I have long felt RubyGems provides a bad solution to the package management problem.  Specifically, I think the solution it provides is at odds with other packaging systems, other programming languages, and the UNIX way.  The damage begins with the isolation of each package in its own versioned directory and snowballs from there to cause headaches for Ruby programmers and UNIX admins alike.  Tomayko has already covered in detail why RubyGems makes it hard to use your library.  I am similarly concerned that RubyGems makes it hard to use UNIX.

This has all come to a head in the past few days on Twitter and in the rcrowley/home@45eea3e commit comments.  With no disrespect to Chris Wanstrath, I feel that gem-man(1) is an ugly solution to RubyGems’ problem.  I should not need to know that ronn(1) comes from a gem to find its man page.

UNIX programs, libraries, and man pages are traditionally installed in a select few well-known locations that reinforce each other (/usr/bin, /usr/lib, and /usr/share/man follow the same pattern as /usr/local/bin, /usr/local/lib, and /usr/local/share/man, for example).  This pattern flows all the way up to the standard installation tools where you set a prefix, within which this pattern is followed by default.  RubyGems ignores this.  Taking ronn(1) as an example, it installs executables at /var/lib/gems/1.8/bin, code libraries in /var/lib/gems/1.8/gems/ronn-0.4.1/lib, and man pages in /var/lib/gems/1.8/gems/ronn-0.4.1/man.

I offer a two-part solution that I feel fits better into the spirit of UNIX.  First, use manskeleton(1) to generate the directory structure and makefiles for your project’s ronn(1)-based man pages.  Afterward, alias mandb(1), man(1), whatis(1), and apropos(1) to set the -M option to the current list of man paths, including all your gems as in rcrowley/home@8a9bef3.

I should mention that the correct directory structure for man pages is $PREFIX/share/man/man$SECTION/$PAGE.$SECTION and the share/ component is generally omitted outside of /usr/share/man and sometimes /usr/local/share/man.  What is not optional is the man$SECTION/ component.  While man(1) can handle that omission, whatis(1) and apropos(1) cannot.

There are two ways RubyGems itself could fix this problem.  Option one is to treat man/ within gems as special, copying these trees to a known location, even if it’s /var/lib/gems/1.8/man.  This would allow us to use the standard tools with the environment variable MANPATH=:/var/lib/gems/1.8/man.  Option two is to follow RubyGems runs with mandb -M... to add the new gem to the man page indexes.  This would still require man(1), whatis(1), and apropos(1) to be aliased but at least new man pages will be indexed automatically.  This second option strikes me as a good RubyGems plugin — is it possible?