Howto Integrate CVS with GNATS


This article explains howto integrate CVS with GNATS so that when a CVS commit is for fixing a bug, the bug's state as well as its Audit-Trail fields can be updated by the CVS server to reflect the progress towards resolving the bug.


Overview

CVS has hooks that allows its integration with other tools. The integration of CVS with bug tracking systems is very common when developers want to keep track of what has been done to resolve some software issue. For a background on CVS hooks, refer to this article: Running Arbitrary Scripts Under CVS.

As described in the begining of this chapter, we want to be able to change the state field as well as append log information to the Audit-Trail field of a PR. For this, we will make the developer provide the PR number, the database and the new state if the sate has changed. The CVS hook mechanism that we will use, will allow us to pass the commit log message (including the database and state information) as well as file changes to a script that will update GNATS accordingly. The steps for achieving this are as follows :


Install a commit template

A commit template is what the developer sees in her editor when she performs a cvs check-in or commit.


Create a template file

We need to create a file say /path/to/CVSROOT/template, with something like this in it :

>Number:
>Database:
>State:

Update /path/to/CVSROOT/rcsinfo

The “rcsinfo” file is used to control templates with which the editor is invoked on commit and import. Add something like this :

ALL /path/to/CVSROOT/template

Install a CVS hook that updates GNATS


Add a commit/check-in hook in /path/to/CVSROOT/loginfo

The “loginfo” file controls where “cvs commit” log information is sent. Add something like this

ALL /path/to/CVSROOT/gnats-pr %{sVv}

This will call the script /path/to/CVSROOT/gnats-pr for each checked in directory/sub-directory. The log message will be written to the stdin of the hook script (gnats-pr). For each file in the committed directory the hook will add the file name, the old version number and the new version number to the call arguments when invoking the hook script gnats-pr.


Create the hook script

Create a script that reads the commit log message, as well as the directory checked in from its stdin, then process files names and versions from its arguments. The script extracts the PR number, the Sate and the database from the log message then update the PR by changing the State if a new state was indicated and appending log in the Audit-Trail field.

Note: This script requires Net::Gnats

#!/usr/bin/perl
 
use     Net::Gnats;
 
my $user="user";
my $pass="pass";
my $server="localhost";
my $prot="1529";
 
my $prid;
my $category;
my $database;
my $inlog = 0;
my $number=0;
my $dir="";
my $state="";
my $database="default";
 
foreach my $line(<STDIN>)
{
 
        chomp;
 
        if ($inlog) {
            if ($line =~ />Number:/) {
                    ($number) = $line =~ m/>Number:(.*)$/;
                    if(!$number) { exit 0; }
 
            } elsif($line =~ />State:/) {
                    ($state) = $line =~ m/>State:(.*)$/;
 
            } elsif($line =~ />Database:/) {
                    ($match) = $line =~ m/>Database:(.*)$/;
                    if($match) {
                        $database=$match;
                    }
            }
            else { $comment = $comment.$line; }
 
        }
 
        if ($line =~ /Update of/) {
                ($dir) = $line =~ m/Update\sof(.*)$/;
        }
 
        if ($line =~ /Log Message/) {
                $inlog = 1;
        }
 
}
$message = $message."\n\n== Commit by ".getlogin()." on ".localtime(time)." =====\n";
$message = $message."\nIn directory: \n\t$dir\n";
$message = $message."\nFiles modified: \n";
 
while ($argnum < $#ARGV) {
 
        $file = $ARGV[$argnum];
        $old = $ARGV[++$argnum];
        $new = $ARGV[++$argnum];
        $message = $message."\t$file \t: $old -> $new\n";
        $argnum++;
 
}
 
$message = $message."\nCommit Log:\n";
$message = $message.$comment."\n";
 
$g=Net::Gnats->new($server,$port);
 
if(!$g->connect()){
        print "Could not connect to $server:$port\n";
        exit -1;
}
 
if(!$g->login($database, $user, $pass)){
        print "Could not log-in to database ".$database." : ".$g->getErrorMessage()."\n";
        exit -1;
}
 
if ($state && !$g->replaceField($number, "State", $state, "No reason indicated")) {
        printf "Could not update State to ".$state." : ".$g->getErrorMessage()."\n";
        exit -1;
 
}
 
if ($message && !$g->appendToField($number, "Audit-Trail", $message)){
        printf "Could not append log entry to PR : ".$g->getErrorMessage()."\n";
        exit -1;
}
 
 
exit 0;


Labels: , , Wireless Internet Security Coding Network Monitoring

Comment

Enter your comment (wiki syntax is allowed):
DMMVC

Wireless Internet Security Performance RADIUS server Wireless Internet Security Performance RADIUS server