Friday, January 27, 2012

Rubygems rdoc spec exclude & rdoc task exclude

One more or less popular error in gemspec:

spec = Gem::Specification.new {|i|
  [...]

  i.rdoc_options << '-m' << 'doc/README.rdoc' << '-x' << 'lib/**/templates/**/*'
  i.extra_rdoc_files = FileList['doc/*']

  [...]
}

In this example a pattern after -x option is invalid. rdoc internally constructs an Regexp object from argument to -x option:

  • If you supply a string 'foo' it will end up as /foo/ argument to a Regexp.new.
  • If you have several -x options like -x foo -x bar, the argument will be /foo|bar/.

(At first rdoc constructs an array from all -x options and then converts it into 1 regexp.)

Now, 'lib/**/templates/**/*' is obviously a bogus regexp and rdoc will loudly complain about it during gem installation. [1] How did it appear in the spec in the first place?

A developer just copied a string from RDoc task which might look like:

RDoc::Task.new('html') do |i|
      i.main = "doc/README.rdoc"
      i.rdoc_files = FileList['doc/*', 'lib/**/*.rb']
      i.rdoc_files.exclude 'lib/**/templates/**/*'
end

This rake task works as intended: 'lib/**/templates/**/*' parameter is a valid one because i.rdoc_files is a Rake::FileList object and exclude method of that object expects such kind of patterns and doesn't understand regexps.

So, don't mix up those patterns it the spec and in the RDoc task itself.

[1]The right one would be something like 'lib/.+/templates/'.