#!/usr/bin/perl

use strict;
use warnings;

# A script to update the status of an issue in a Roundup bug tracker
# based on the format of a darcs patch name.
# It is intended to be run from a darcs posthook.

# The format we look for is:
#   resolved issue123 
# in the first line of the patch. 

# Can be called with --branch=stable to resolve items as "resolved-in-stable".
# By default we would mark them "resolved-in-unstable"

use Getopt::Long;
my $branch = 'unstable';
GetOptions ( "branch=s"   => \$branch );

# TODO: validate branch to only be exactly 'unstable' or 'stable'


use MIME::Lite;
use XML::Simple;

unless ($ENV{DARCS_PATCHES_XML}) {
    die "DARCS_PATCHES_XML was expected to be set in the environment, but was not found. 
          Are you running this from a Darcs 2.0 or newer posthook?"
}

my $xml = eval { XMLin($ENV{DARCS_PATCHES_XML}); };
die "hmmm.. we couldn't parse your XML. The error was: $@"  if $@;

# $xml structure returned looks like this: 
#  'patch' => {
#    'resolved issue123: adding t.t' => {
#        'hash' => '20080215033723-20bb4-54f935f89817985a3e98f3de8e8ac9dad5e8e0e5.gz',
#        'inverted' => 'False',
#        'date' => '20080215033723',
#        'author' => 'Mark Stosberg <mark@summersault.com>',
#        'local_date' => 'Thu Feb 14 22:37:23 EST 2008'
#        },
#     'some other patch' => { ... }, 

for my $patch_name (keys %{ $xml->{patch} }) {
    my $status_issue_re = qr/(resolved?) \s+ (issue\d+)/msxi;

    next unless ($patch_name =~ $status_issue_re);
    my ($status,$issue) = ($1,$2);
    $status =~ s/resolve$/resolved/;
    my $patch = $xml->{patch}{$patch_name};

    # Using the Command Line would be a simpler alternative. 
    # my $out = `roundup-admin -i /var/lib/roundup/trackers/darcs set $issue status=$status`;
    # warn "unexpected output: $out" if $out;

    my $author = $patch->{author};
    # If the Author name contains an @ sign, we take it to be an e-mail address.
    # Otherwise, we default to darcs-devel as the sender. 
    my $email = ($author =~ m/\@/) ? $author : 'darcs-devel@darcs.net';

    my $full_status = "${status}-in-$branch";

    my $comment = $patch->{comment} ? "\n$patch->{comment}" : '';

    my $patch_name_minus_status = $patch_name; 
    $patch_name_minus_status =~ s/$status_issue_re(:?\s?)//;

     # Each patches can potentially update the status of a different issue, so generates a different e-mail
    my $msg = MIME::Lite->new(
         From     => $email, 
         To      =>'bugs@darcs.net',
         #To       =>'mark@stosberg.com',
         Subject  =>"[$issue] $patch_name_minus_status [status=$full_status]",
         Type     =>'text/plain',
         Data     => qq!The following patch updated the status of $issue to be $status in the $branch branch:

* $patch_name $comment

You can view the patch details online here: 
http://darcs.net/cgi-bin/darcs.cgi/$branch/?c=annotate&p=$patch->{hash}

!
     );
     $msg->send;
     # An alternative to actually sending, for debugging. 
     # use File::Slurp;
     # write_file("msg-$patch->{hash}.out",$msg->as_string);
}


