Luke Melia

software dev

September 18, 2007

A rake task to apply a patch from a Trac ticket

Tracks uses a Trac for a bug tracker, and the awesome Tracks community helpfully attaches patches to tickets for a committer (me) to review and apply. I wanted an easy way to do this, so I whipped up this rake task that let's you select a ticket and attachment to apply to the app as a patch:

RUBY:
  1. namespace :trac do
  2.   desc 'Apply a patch from a trac ticket.'
  3.   task :patch => :environment do
  4.     require 'hpricot'
  5.     require 'open-uri'
  6.     require 'rubygems'
  7.     require 'action_view/helpers/text_helper'
  8.     include ActionView::Helpers::TextHelper
  9.     trac_url = "http://dev.rousette.org.uk"
  10.     unless ENV['TICKET']
  11.       print "Enter the ticket number: "
  12.       ENV['TICKET'] = STDIN.gets.chomp
  13.     end
  14.     doc = Hpricot(open("#{trac_url}/ticket/#{ENV['TICKET']}"))
  15.     attachments_dts = doc/"#attachments"/"dt"
  16.     attachment_index = 0
  17.     if attachments_dts.length> 1
  18.       print "\nThere are multiple attachments for this ticket.\n"
  19.       attachments_dds = doc/"#attachments"/"dd"
  20.       attachments_dts.each_with_index do |dt, i|
  21.         print "\n[#{i + 1}] " + strip_tags(dt.inner_html) + " - " + attachments_dds[i].inner_html
  22.       end
  23.       print "\n\nEnter the number of the attachment you want to apply as a patch: "
  24.       attachment_index = STDIN.gets.to_i - 1
  25.     end
  26.     filename = attachments_dts[attachment_index].search("a").inner_html
  27.     patch_url = "#{trac_url}/attachment/ticket/#{ENV['TICKET']}/#{filename}?format=raw"
  28.    
  29.     patch = open(patch_url).read
  30.  
  31.     File.open('patch.diff', 'w+') do |f|
  32.       f.puts patch
  33.     end
  34.  
  35.     `patch -p0 <patch.diff && rm patch.diff`
  36.  
  37.     print "\nPatched with #{filename} from Trac ticket #{ENV['TICKET']}.\n"
  38.   end
  39. end

Here's a sample shell session demonstrating the case when there is more than one patch attached:

CODE:
  1. $ rake trac:patch
  2. Enter the ticket number: 560
  3.  
  4. There are multiple attachments for this ticket.
  5.  
  6. [1] cleanup_stats_controler.diff (25.9 kB) - added by foo@barcom on 09/16/07 19:32:35. - cleanup of stats_controller
  7. [2] cleanup_stats_controler.2.diff (25.9 kB) - added by foo@barcom on 09/16/07 19:46:51. - whoeps old patch introduced an error. fixed with this patch
  8.  
  9. Which number attachment do you want to use as the patch to apply: 2
  10.  
  11. Patched with cleanup_stats_controler.2.diff from Trac ticket 560.

If there is only one attachment, it will be applied without you having to make a selection. Also, you can specify the ticket number on the command line (i.e. rake trac:patch TICKET=155).

That's it. Hope this is useful!

Thanks to Chris Wansrath of err.the_blog for the inspiration via pastie:patch.

Leave a Reply

LukeMelia.com created 1999. ··· Luke Melia created 1976. ··· Live With Passion!