Time to give myself a little pat on the back.

Last week I sat down to work for a whole working day on "whatever I wanted to", as part of the Canonical Server Team's pilot "Fedex Day" program. Mathias Gug and I both looked at this idea from Dan Pink's book "Drive" and thought it made sense to try it out.

Management approved, and we set about on a day of "work on one thing, make it go, and then show it off the following week".

I was originally going to work on improving the search capabilities of the MoinMoin wiki software that we use at Canonical. But it turns out, somebody already did that by adding Xapian support, and so we really just need to backport that to whatever version of Ubuntu canonical's servers run on.

So, I decided to tackle another issue that has been nagging at me.

I love perl. I've used it for years, and I have always found that the ease with which one can get software from perl's central repository, CPAN, was a huge differentiator from other languages.

So much so, that PHP, Python, and Ruby have in many ways gone even further than CPAN with their respective tools, PEAR, pypi, and rubygems.

Well one thing Debian developers love is perl too. So for a long time now, its been relatively simple, even braindead simple, to create a debian source package from a CPAN module.

Simply download the tarball, unpack, and 'dh-make-perl', that gets you 90% of the way there. All that is left is renaming a few dependencies, making sure the copyrights are done, and verifying that the module doesn't do anything nasty.

How cool is that?

Python has a few tools like this too, like sdist, so they're covered.

But Ruby had no such thing for rubygems. There are definitely tools to create debs from ruby source distributions, but often times projects don't actually distribute source any other way than a .gem file or code repository. To make matters worse, there is a bit of confusion between some users of rubygems on Debian and Ubuntu about how it should work. Many people feel that gems is a poor way to distribute software, or that it lacks certain features. Others would just like to use it like any other developer tool.

Well I happen to think that many ruby users would probably grow to love .debs if they covered a large portion of rubygems software.

So, DebiGem is born! I created this project in about 8 working hours, with zero Ruby knowledge beforehand. I'm sure that shows in my style of Ruby. With some help from perusing the rubygems code base and about 80 Ruby tutorial pages on the net, I think I've created something that actually works.

If you want to try it, go ahead and fire it up, simply install the debs available in my PPA on Launchpad, and then download a .gem, and turn it into a source package (apologies for all the debug output, we're talking about v0.0.2 here!).

clint@ubuntu:~/testgem$ wget http://rubygems.org/downloads/a2ws-0.1.9.gem
--2010-09-07 15:58:46-- http://rubygems.org/downloads/a2ws-0.1.9.gem
Resolving rubygems.org... 72.4.120.124
Connecting to rubygems.org|72.4.120.124|:80... connected.
HTTP request sent, awaiting response... 302 Found
Location: /gems/a2ws-0.1.9.gem [following]
--2010-09-07 15:58:46-- http://rubygems.org/gems/a2ws-0.1.9.gem
Reusing existing connection to rubygems.org:80.
HTTP request sent, awaiting response... 302 Found
Location: http://production.cf.rubygems.org/gems/a2ws-0.1.9.gem [following]
--2010-09-07 15:58:46-- http://production.cf.rubygems.org/gems/a2ws-0.1.9.gem
Resolving production.cf.rubygems.org... 216.137.37.222, 216.137.37.239, 216.137.37.11, ...
Connecting to production.cf.rubygems.org|216.137.37.222|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 7168 (7.0K) []
Saving to: `a2ws-0.1.9.gem'

100%[================================================================================================================================================================>] 7,168 --.-K/s in 0.07s

2010-09-07 15:58:46 (94.9 KB/s) - `a2ws-0.1.9.gem' saved [7168/7168]

clint@ubuntu:~/testgem$ dh-make-gem a2ws-0.1.9.gem
Extracting gem file a2ws-0.1.9.gem
tar -xvf a2ws-0.1.9.gem data.tar.gz
data.tar.gz
tar: data.tar.gz: implausibly old time stamp 1969-12-31 16:00:00
tar -C liba2ws-ruby-0.1.9 -zxf data.tar.gz
tar: .document: implausibly old time stamp 1969-12-31 16:00:00
tar: .gitignore: implausibly old time stamp 1969-12-31 16:00:00
tar: LICENSE: implausibly old time stamp 1969-12-31 16:00:00
tar: README.rdoc: implausibly old time stamp 1969-12-31 16:00:00
tar: Rakefile: implausibly old time stamp 1969-12-31 16:00:00
tar: VERSION.yml: implausibly old time stamp 1969-12-31 16:00:00
tar: a2ws.gemspec: implausibly old time stamp 1969-12-31 16:00:00
tar: lib/a2ws.rb: implausibly old time stamp 1969-12-31 16:00:00
tar: lib/a2ws/base.rb: implausibly old time stamp 1969-12-31 16:00:00
tar: lib/a2ws/image.rb: implausibly old time stamp 1969-12-31 16:00:00
tar: lib/a2ws/image_search.rb: implausibly old time stamp 1969-12-31 16:00:00
tar: lib/a2ws/item.rb: implausibly old time stamp 1969-12-31 16:00:00
tar: lib/a2ws/item_search.rb: implausibly old time stamp 1969-12-31 16:00:00
tar: lib/a2ws/methodize.rb: implausibly old time stamp 1969-12-31 16:00:00
tar: spec/a2ws_spec.rb: implausibly old time stamp 1969-12-31 16:00:00
tar: spec/spec_helper.rb: implausibly old time stamp 1969-12-31 16:00:00
tar -zcf liba2ws-ruby_0.1.9.orig.tar.gz --exclude=liba2ws-ruby-0.1.9/debian liba2ws-ruby-0.1.9
changing working dir to liba2ws-ruby-0.1.9
DEBUG: a2ws-0.1.9.gem.gemspec
WARNING: no description specified
WARNING: no rubyforge_project specified
DEBUG: req = libhttparty-ruby (>= 0.4.3)
DEBUG: type=runtime
DEBUG: req = libactivesupport-ruby (>= 2.2.2)
DEBUG: type=runtime
Successfully built Debian source package from gemspec
Name: a2ws
Version: 0.1.9
PackageName: liba2ws-ruby
clint@ubuntu:~/testgem$ cat liba2ws-ruby-0.1.9/debian/control
Source: liba2ws-ruby
Section: ruby
Priority: optional
Maintainer: foo
Build-Depends: ruby, debhelper (>= 7), dh-rubygems,
Standards-Version: 3.9.1

Package: liba2ws-ruby
Section: ruby
Architecture: all
Depends: ruby, ${shlibs:Depends}, libhttparty-ruby (>= 0.4.3), libactivesupport-ruby (>= 2.2.2)
Description: Wrapper for Amazon Associates Web Service (A2WS).

clint@ubuntu:~/testgem$ cat liba2ws-ruby-0.1.9/debian/rules
#!/usr/bin/make -f
# This file was generated by 'gem debsrc'
#
%:
dh $@

override_dh_auto_build::
dh_rubygems build

override_dh_install::
dh_rubygems install

override_dh_clean::
dh_rubygems clean
dh_clean
clint@ubuntu:~/testgem$ ls -l liba2ws-ruby-0.1.9/debian
total 20
-rw-r--r-- 1 clint clint 151 2010-09-07 15:58 changelog
-rw-r--r-- 1 clint clint 2 2010-09-07 15:58 compat
-rw-r--r-- 1 clint clint 410 2010-09-07 15:58 control
-rw-r--r-- 1 clint clint 2078 2010-09-07 15:58 liba2ws-ruby.gemspec
-rw-r--r-- 1 clint clint 213 2010-09-07 15:58 rules

It also includes the dh_rubygems tool and dh-rubygems package you see mentioned above.

Given this tool, its relatively easy to create .deb files and focus on the real work of creating packages, which is reviewing licensing and code, rather than turning them into the actual .deb. Sure you still have to update the maintainer field, and will probably want to check those dependencies, but for the most part, this works and gets the gem into an installable state.

I do hope someone finds this useful, it was great fun implementing it.