[rt-users] Importing from Mantis

Andy Lester andy at petdance.com
Wed Aug 7 14:46:17 EDT 2002


I just made the switch from Mantis (mantisbt.sf.net) to RT, and I'm
loving RT more and more every day.  To switch over, I had to write a
convert script which I present below.  Use it as you like.

xoxo,
Andy


#!/usr/bin/perl -w
#$Id: import-mantis,v 1.18 2002/08/02 01:51:19 alester Exp $

# import-mantis
# Created by: Andy Lester <andy at petdance.com>
# Hacked from Jesse's import-gnats script
#
# Please go thru and change all the values to what's appropriate.

use strict;
use Carp qw( cluck confess );

my $EMAILDOMAIN = "flr.follett.com"; # user_id at EMAILDOMAIN for missing RT1 emails
my $DEFAULTQUEUE = 'general'; # Qeuue to put tickets from deleted queues in.

# IF YOU DO NOT SET THE ABOVE VALUE TO A VALID QUEUE NAME, YOUR IMPORT WILL
# FAIL AND YOU'LL BE REALLY REALLY UNHAPPY.

# Mantis DB variables
my $dbname = "bugtracker";
my $dbuser = "root";
my $dbpass = "fish";

my $Debug = 1;

our %mantis_name_by_id;


# Replace this with the path to your RT lib directory
use lib "/usr/local/rt2/lib/";

# Replace this with the path to your RT etc directory
use lib "/usr/local/rt2/etc/";

use Data::Dumper;
use RT::Interface::CLI qw( CleanEnv LoadConfig DBConnect GetCurrentUser GetMessageContent );
use Date::Format;
use MIME::Entity;
use Mail::Internet;
use MIME::Parser;
use RT::User;
use RT::Queue;
use RT::Ticket;
use RT::Transaction;
warn "Loaded modules\n";
#Clean out all the nasties from the environment
CleanEnv();
warn "CleanEnv() done\n";

#Load etc/config.pm and drop privs
LoadConfig();
warn "LoadConfig() done\n";

# This is an inlined version of RT::Init(). 
# Calling RT::Init() would lock up, but pulling the guts out here
# worked.  I don't know why.
use RT;
    #Get a database connection
    $RT::Handle = new RT::Handle($RT::DatabaseType);
    $RT::Handle->Connect();
    
    #RT's system user is a genuine database user. its id lives here
    $RT::SystemUser = new RT::CurrentUser();
    $RT::SystemUser->LoadByName('RT_System');
    
    #RT's "nobody user" is a genuine database user. its ID lives here.
    $RT::Nobody = new RT::CurrentUser();
    $RT::Nobody->LoadByName('Nobody');

warn "Did DBConnect();\n";

# Mantis-specific handle
our $dbh = 
    DBI->connect( 
	"DBI:mysql:host=localhost;database=$dbname",
	$dbuser, $dbpass,
	{PrintError => 0, RaiseError => 1}
    );
warn "Created Mantis DBH\n";

# Returns a queue object based on a Mantis project name
sub get_queue {
    my $name = shift;

    my $queue = new RT::Queue($RT::SystemUser);
    $queue->Load($name);

    my ($val,$msg);
    unless ($queue->Id) {
	($val, $msg) =
	    $queue->Create( 
		Name => $name, 
		Description => $name . " imported from Mantis",
		CorrespondAddress => $name.'@'. $EMAILDOMAIN ); 
	warn "Fired up the RT queue $name\n";
    }


    unless ($queue->Id) {
	die "Couldn't create a queue called '$name'\n$msg";
    } 

    return $queue;
}
 


IMPORT_USERS: {
    my $sql = q{
	select  id, username, email
        from	mantis_user_table
    };
    my $sth = $dbh->prepare( $sql ) or die;
    $sth->execute() or die; 

    my $root = new RT::User($RT::SystemUser);
    $root->Load('root');
    
    while ( my $row = $sth->fetchrow_hashref ) {
	my $name = $row->{username};
	my $result = $root->Create( 
	    Name => $name,
	    RealName => $name,
	    Gecos => $name,
	    EmailAddress => $row->{email},
	    Privileged => 1,
	);
	$mantis_name_by_id{ $row->{id} } = $name;

	warn "Created $name: $result\n";
    }
    $sth->finish;
}


# Import all the top-level bugs
IMPORT_BUGS: {
    my $sql = q{
	select 	B.*, T.*, P.name as project_name
	from	mantis_bug_table B, mantis_bug_text_table T, mantis_project_table P
	where	B.id = T.id
		    and
		    P.id = B.project_id
	order by B.id
    };
    my $sth = $dbh->prepare( $sql ) or die;
    $sth->execute() or die; 

    while ( my $row = $sth->fetchrow_hashref ) {
	my $ticket = bug_to_ticket( $row );
    }
    $sth->finish;
}


# Import all the notes
IMPORT_NOTES: {
    my $sql = q{
	select 	*	
	from	mantis_bugnote_table N, mantis_bugnote_text_table T
	where	N.id = T.id
        order by bug_id
    };
    my $sth = $dbh->prepare( $sql ) or die;
    $sth->execute() or die; 

    while ( my $row = $sth->fetchrow_hashref ) {
	my $id = $row->{bug_id};
	my $ticket = new RT::Ticket( $RT::SystemUser );
	if ( $ticket->Load( $id ) ) {
	    my $email = username_from_mantis_id( $row->{reporter_id} );
	    add_comment( $ticket, $email, $row->{note}, $row->{date_submitted} );
	    warn "Attached to bug $id\n";
	} else {
	    warn "***>>> Couldn't load $id";
	}
    }
    $sth->finish;
}

sub bug_to_ticket {
    my $bug = shift;

    my $queue = get_queue( $bug->{project_name} );

    my $ticket = new RT::Ticket( $RT::SystemUser );

    my $status = status_convert( $bug->{status} );
    my ($id,$error);

{   # Needed a more verbose dump if anything went wrong here.
    local $SIG{__WARN__} = \&confess;
    ($id,$error) = 
	$ticket->Import(
	    id => 	$bug->{id},
	    Subject => 	clean( $bug->{summary} ),
	    Queue => 	$queue->id,
	    Priority =>	$bug->{priority},
	    Status => 	$status,
	);
}

    warn $error unless $id;
    warn "Created ticket #$id as $status\n" if $id;

    my $email = username_from_mantis_id( $bug->{reporter_id} );
    for my $field ( qw( description steps_to_reproduce additional_information ) ) {
	my $text = $bug->{$field};
	if ( $text ) {
	    my $header = ucfirst $field;
	    $header =~ s/_/ /g;
	    add_comment( $ticket, $email, "$header:\n$text", $bug->{date_submitted} );
	    warn "  Added $header\n";
	}
    }
    warn " \n";

    return $ticket;
}

sub add_comment {
    my $ticket = shift;
    my $email = shift;
    my $text = shift;
    my $date = shift;

    $text = clean( $text );

    # Squeeze the user info into the top of the text
    my $mime = MIME::Entity->build( 
	Data => "From: $email\nDate: $date\n$text" 
    );
    $ticket->Comment( MIMEObj => $mime );
}


sub username_from_mantis_id {
    my $mantis_id = shift;

    return $mantis_name_by_id{ $mantis_id } || "Unknown Mantis user #$mantis_id";
}


# Undo all the goofy stuff that Mantis does with its text fields.
sub clean {
    my $str = shift;

    $str =~ s/</</g;
    $str =~ s/>/>/g;
    $str =~ s/"/"/g;
    $str =~ s/&/\&/g;

    # The order of translation is important here.
    $str =~ s/\\\\/\\/g;
    $str =~ s/\\'/'/g;
    $str =~ s/\\"/"/g;

    return $str;
}


#$g_access_levels_enum_string      = "10:viewer,25:reporter,40:updater,55:developer,70:manager,90:administrator";
#$g_project_status_enum_string     = "10:development,30:release,50:stable,70:obsolete";
#$g_priority_enum_string           = "10:none,20:low,30:normal,40:high,50:urgent,60:immediate";
#$g_severity_enum_string           = "10:feature,20:trivial,30:text,40:tweak,50:minor,60:major,70:crash,80:block";
#$g_reproducibility_enum_string    = "10:always,30:sometimes,50:random,70:have not tried,90:unable to duplicate,100:N/A";
#$g_status_enum_string             = "10:new,20:feedback,30:acknowledged,40:confirmed,50:assigned,80:resolved,90:closed";
#$g_resolution_enum_string         = "10:open,20:fixed,30:reopened,40:unable to duplicate,50:not fixable,60:duplicate,70:not a bug,80:suspended,90:won't fix";

sub status_convert {
    my $status = shift;

    my %map = (
	10 => 'new',
	20 => 'open',
	30 => 'open',
	40 => 'open',
	50 => 'open',
	80 => 'resolved',
	90 => 'resolved',
    );

    return $map{$status} or die "Unknown status \"$status\"";
}

-- 
'Andy Lester        andy at petdance.com
 Programmer/author  petdance.com
 Daddy              parsley.org/quinn   Jk'=~/.+/s;print((split//,$&)
                            [unpack'C*',"n2]3%+>\"34.'%&.'^%4+!o.'"])




More information about the rt-users mailing list