Dr Nic

8 steps for fixing other people’s code

Before or after you’re sharing your own code as open-source, you might find yourself itching to fix someone else’s code.

Twelve months ago I made my first contribution to someone else’s project – I added some auto-generated tests to the AjaxScaffold project (now ActiveScaffold and no longer a rails generator). It was the first RubyGem I really investigated. It was the first Rails Generator I investigated. It was the first OSS project I think I’ve ever submitted a patch to. It took days.

Its always the same process

Yesterday I created a patch for Merb: an update to their README file so it converted to RDoc nicely. The whole patching process: spotting the ugly README, checking out merb trunk, changing its README, testing, creating a patch, and submitting it to Merb’s trac, took about 30 minutes whilst also doing other things.

The process was the same, I’m just better at it.

Step-by-step

So here’s how to fix other people’s code. It has Ruby-specific examples, but I’m sure the process is the same in all OSS communities. Its also worth checking out the slides from Josh Susser’s Railsconf talk on contributing to Rails Core.

1. Get annoyed by a defect or missing feature

Open source software isn’t written by an army of coders, with a back up army of testers, documenters, and “Dummies Guide” book authors. Rather, its code that fixed the author’s problem; and they were nice enough to flesh it out generically so you could use it. Or they were seeking fame and glory.

So you find problems. The project owner and all its users will be super grateful if you fix it for them.

2. Finding the source

The modern Ruby community uses subversion/svn for their source repositories. So now is your excuse to install it and start to learn how to use it.

The tricky part is “where is the repository?”

If the project has a RubyForge project go to (if its URL is http://XYZ.rubyforge.org, then its project page is http://rubyforge.org/projects/XYZ) then try the “SCM” tab on the project page. If the project isn’t hosting on RubyForge SVN, hopefully they have disabled this menu tab. If not, you’ll get version 0 when you do the checkout to tell you the project’s not hosted here.

Alternately, the project’s homepage/README file should tell you where the repository is.

Finally, email the project owner. And tell them to get their act together and publicise their SVN repos.

3. Checkout the source

Hopefully you’re told the complete URL to the trunk of the project. For anonymous access to the newgem RubyForge project the URL is svn://rubyforge.org/var/svn/newgem/trunk

A project SVN repository might contain multiple projects, and may or may not use the common trunk/branches/tags root folders. So you may need to navigate around the repository and til you find the trunk of the project’s code.

So for a generic RubyForge project, the root URL for anonymous access is svn://rubyforge.org/var/svn/XYZ.

$ svn list svn://rubyforge.org/var/svn/newgem
branches/
tags/
trunk/
$ svn list svn://rubyforge.org/var/svn/newgem/trunk
History.txt
...

[Thx to Seth - originally I suggested doing a checkout; but list is cleaner.]

If there is a trunk root folder, then do the following:

rm -rf XYZ
svn co svn://rubyforge.org/var/svn/XYZ/trunk XYZ
cd XYZ

And now you’ve checked out the trunk or “edge” of the project. The latest and greatest.

4. Snoop around

Load up the project into your editor and poke around.

If it has test cases (!) try running them. You may need to create some databases and/or modify the Rakefile/connection details to work with your database. Hopefully the project comes with rake tasks to create/drop the databases. rake -T should find them.

If its a RubyGem, try installing the gem locally (on top of the existing defective gem that you’re about to fix). Again, run rake -T and hopefully there is a task install_gem or similar to build and install the gem from source. If not, send hate mail to the author. And then fix the Rakefile to use the Hoe gem. And then send a patch to the author with the fixed Rakefile.

rake install_gem

5. Make changes

Finally, you get to change their code.

If the project has a suite of test cases, please make an effort to add “failing test cases”. That is, add test cases that demonstrate the defect by failing (unless the project includes your fix).

Run the tests to ensure they are working.

6. Refresh the code from the repository (svn up)

The original repository may have changed since you did the checkout, so update your version.

svn up

If there are any conflicts, go fix them and delete any helper files created by SVN.

7. Create the patch

First, you need to tell subversion about any folders/files you’ve added (svn add) or deleted (svn remove).

Then, from the root folder of the trunk:

svn diff > i_fixed_a_bug.patch

Give the patch file a useful, readable name. Like readme_updated_for_rdoc_syntax.patch.

8a. Submit patch to trac

[link to 8a]

Each project may have a different preferred way to submit patches.

If the project uses trac then:

  1. Register an account (normally a link at the top right of the page) if available. Some trac installations require an account (e.g. Rails) and others allow anonymous tickets.
  2. Click “New Ticket
  3. Fill in details (note, there is nowhere initially to add your patch). Prefix the subject with [PATCH]
  4. Save the ticket (check the box “Attach files”)
  5. Attach the patch file and save

8b. Submit patch to Google Groups

[link to 8b]

Projects hosted on rubyforge SVN cannot use trac. I personally use Google Groups for my projects – the project communities are all small enough such that its manageable.

  1. Join the Group (using Google Account)
  2. Add a picture to your Google Groups account; I cannot communicate how relatively unnecessary this step truly is
  3. Go to Files section (link on right hand side)
  4. Attach your patch file to the group
  5. Get the URL for the uploaded file
  6. Post a note/write an email to the group describing your patch, and include the URL for the patch file

8c. Submit patch to RubyForge Tracker

[link to 8c] [Thx Chris Martin]

RubyForge offers a bug/patch/feature request tracker for each Project. It is enabled by default for new projects:

  1. Login or Create new Rubyforge account
  2. Go to project page and click “Tracker“ from sub-menu
  3. Click “Submit New
  4. Fill in details (each RubyForge Project can contain many sub-projects/gems – pick from Category drop-down)
  5. Check the box “Check to Upload & Attach File”
  6. Browse and select your patch file; put file name in File Description field as you’ve already made it human readable, because you’re a champion.
  7. Save the ticket

8d. Submit patch to LaunchPad Tracker

[link to 8d]

“I have to say I quite like Launchpad, now that I’ve got used to it. If you’re an Ubuntu guy like me then it is perfect.” – from Neil Wilson

  1. Login to/Register for your Launchpad account
  2. From The Launchpad bug tracker click the Report a bug button.
  3. Enter the name of the project, or select it from the list.
  4. The project in question will almost certainly provide its own bug reporting link that takes you directly to the Report a New bug page.
  5. Enter a one line summary and click Continue
  6. Fill in the comment box and click Submit Bug Report
  7. Then click the link “Add a comment/attachment”, and Browse for the patch file. Check “This attachment is a patch” and add a Description if required.
  8. Click Save Changes

8z. Email the project owner

[link to 8z]

See title: Email the project owner. Prefix the subject with [PATCH].

Why 8z? I figured readers might want to share other ways they coordinate within a project, like Google Code, etc. I haven’t used it. So, (c) – (y) are placeholders :)

Corollary: Tell users how to fix problems

If you administer some OSS projects, you are doing yourself a disservice not telling your users how to quickly, easily submit patches.

Either copy and paste the relevant sections above, and/or link them to this “8 steps” page.

Make it really clear on your project website that patches are welcome and will be rewarded with free t-shirts and other complimentary items of stationary, and watch those patches roll in.

For example, on the New Gem Generator site (and in all default project websites), there is a link to this page and a reference to section on Google Groups as the default.

How to submit patches

Read the 8 steps for fixing other people’s code and for section 8b, use the Google Group above..

The trunk repository is svn://rubyforge.org/var/svn/newgem/trunk for anonymous access.

New Gem Generator gets RSpec [video]

slide.007

One day you will be able to write a human description of a RubyGem and it will make it for you. Ok, that’s crap. But the New Gem Generator is doing more and more cooler things lately; so let’s take a peek…

RSpec

For a growing number of people, RSpec is the way to go, over the Test::Unit test suite. Now, thanks to a contribution from Robby Russell and Graeme Nelson during Railsconf.

$ newgem my_cool_gem -t rspec
$ cd my_cool_gem
$ rake  # runs specs

Bonus website

New gems now have a website folder with an index.txt file (redcloth format). Put your glorious promotional materials and tutorials here (plus add additional .txt files as well) and the rake website task will convert them to html files and upload them to your rubyforge website.

The standard template looks like this (you’re encouraged to change some colours or fonts!)

Deploying gems

Ready to release a new X.Y.Z version of your gem? It takes 3 minutes.

  1. Set the version number in lib//version.rb.
  2. Check your Manifest.txt that it includes all new files (via rake check_manifest)
  3. Update History.txt with changes. The default supported format is 2 paragraphs – a header and group of bullet points; these look nice when converted to rdoc format.
  4. Commit the new version to repository.
  5. Deploy/release gem
$ rake deploy VERSION=X.Y.Z

This will release your RubyGem to rubyforge so people can install it; plus upload your website and your rdocs.

You’ll then be prompted to commit a copy of the trunk as a tag REL-X.Y.Z. This could be very useful one day!

Video of NewGem at RejectConf

You can read the pdf slides and/or watch the presentation from RejectConf: