Downloading RT patches from the command line

I love it when people post patches to RT, but I don't really like the work required to download them from the web interface. I know there's an rt command line client somewhere, but the last time I tried it, it didn't work very well for me. Thankfully, with the help of RT::Client::REST, I whipped up a short program that will take a ticket number, pluck my credentials from my .pause file, and save the attachments into the current directory.

#!/usr/bin/env perl
use 5.010;
use strict;
use warnings;
use autodie;
use Encode qw/decode/;
use Error qw(:try);
use Path::Class;
use RT::Client::REST;
use RT::Client::REST::Ticket;

my %credential = split " ", file($ENV{HOME}, '.pause')->slurp;
my $user = lc $credential{user};
my $pass = $credential{password};
my $id = shift(@ARGV) || die "No ticket # provided";
$id =~ s{^(?:rt#?)}{};
die "Ticket must be an integer" if $id =~ /\D/;

my $rt = RT::Client::REST->new(
  server => '',
  timeout => 30,

try {
  $rt->login(username => $user, password => $pass);
} catch Exception::Class::Base with {
  die "problem logging in: ", shift->message;

my $ticket;
try {
  $ticket = RT::Client::REST::Ticket->new( rt => $rt, id => $id);
} catch RT::Client::REST::UnauthorizedActionException with {
  print "You are not authorized to view ticket $id\n";
} catch RT::Client::REST::Exception with {
  die "problem getting $id, ", shift->message;

try {
  my $iter = $ticket->attachments->get_iterator;
  while ( my $i = $iter->() ) {
    my $name = $i->file_name or next;
    my $encoding = $i->content_encoding;
    $encoding = '' if $encoding eq 'none';
    my $string = $encoding ? 
      decode( $encoding, $i->content, 1 ) : $i->content; 
    say "Writing $name";
} catch RT::Client::REST::Exception with {
  die "problem getting attachments from $id, ", shift->message;

This is mostly just some cut/paste/modify work with the relevant synopses in the documentation. There was a little trial-and-error required, particularly in how encoding was being passed through, but it seems to work. I was able to download a patch while connected via ssh, which is exactly what I was looking for.

Update: I fixed a hardcoded "#10" in an error message.

This entry was posted in perl programming and tagged , . Bookmark the permalink. Both comments and trackbacks are currently closed.


  1. Posted July 1, 2010 at 12:42 am | Permalink

    Cool! Haven't used it yet, but you hardcode ticket #10 in one of your error messages.

    • dagolden
      Posted July 1, 2010 at 6:39 am | Permalink

      Good catch. That was left over from my copy/paste of the example code. Fixed above and in the code I actually use.

  2. Posted July 1, 2010 at 6:24 am | Permalink

    Nice one, I'll definitely find this useful and it worked like a treat when I worked out what your .pause file looked like.

    • dagolden
      Posted July 1, 2010 at 6:44 am | Permalink

      Of course! I forget that not everyone automates CPAN uploads with cpan_upload. (And actually, I now let Dist::Zilla do it for me.)

  3. Posted July 1, 2010 at 9:28 am | Permalink

    hmm.... it downloads attachments... I'll have to see if I can modify it to download the email with full headers for git am patches. which are great if you use git ;)

    • dagolden
      Posted July 1, 2010 at 10:28 am | Permalink

      That would be great. I did see that there are "attachments" without names, which looked like it might have been an email, but I didn't really investigate.

  4. Posted July 1, 2010 at 9:29 am | Permalink

    why on earth does this... 'name' field ( for posting comments ) either not allow spaces, or perhaps parenthesis.... and while denying it it gives no error...

  5. Dolmen
    Posted July 6, 2010 at 12:37 pm | Permalink

    The next step would be to create have a tool that can generate a distropref from an RT ticket.
    Distroprefs are metadata that can be used by to apply a patch to a distribution before building it.

One Trackback