#!/usr/bin/perl -w
# $Id: faum-bugreport.in,v 1.2 2004/06/21 18:55:42 simimeie Exp $
# vim:tabstop=8:shiftwidth=8:textwidth=72

# Elements of a Bug Description
#    category :                  get_category
#	possible categories are:
#		frontend
#		kernel
#		configuration
#		network bridge to real network
#		fault injection
#		X/graphics
#		expect
#		none of the above
#    FAUmachine Version :           get_faumachine_version
#    FAUmachine-kernel-version :    get_faumachine_kernel_versions
#    Compiler Version used :     get_compiler_version
#			 (we get compiler from makefile)
#    host-kernel version :       get_os_version
#    host-distribution version : get_distro
#    short title :               get_title
#    auto-generated bug-id (date/time?) : make_id
#    textual bug description :   get_bug_description 
#    bug-description author :    get_username
#    bug-date :                  get_date

#    assigned to
#    assigned by
#    assigned date

#    status

#    fixed date
#    fixed by


# bugreport: have this as a make target
# first step use only locally and check into cvs
# first step use commandline interface, perhaps start editor for bug-description
# when finished, check into cvs

# bugassign: have this as a make target
# update buglist from cvs, display bug info, let user assign

# bugfixed: have this as a make target
# update buglist from cvs,
# enter fix-description
# commit to cvs

use Getopt::Long ;
use vars qw($prefix $bindir $libdir $mandir $docdir $xpmdir $vhdldir
	$kernelsdir $toolsdir $loadersdir $package $rootdir);
BEGIN {
$rootdir="";
$prefix     ="/usr";
$bindir     ="/usr/bin";
$libdir     ="/usr/lib";
$mandir     ="/usr/share/man";
$docdir     ="/usr/share/doc/faumachine";
$xpmdir     ="/usr/share/faumachine/xpm";
$vhdldir    ="/usr/share/faumachine/vhdl";
$kernelsdir ="/usr/lib/faumachine/kernels";
$toolsdir   ="/usr/lib/faumachine/tools";
$loadersdir ="/usr/lib/faumachine/loaders";
$package    ="FAUmachine";
sub chompslash($){
	local $/;
	$/ = '/';
	return chomp($_[0]); #explicitly change parameter!
}
sub findlibs {
	my $dir = $0;
	my $roottmp = "";
	my $scriptname = "";
	# find script name
	if(0<=(my $slash=rindex($dir, "/"))){
		$scriptname=substr($dir,$slash+1);
		$dir = substr($dir, 0, $slash);
	}
	# absolute path
	if (0< (my $i = rindex($dir, $bindir))) {
		$dir = substr($dir, 0, $i);
		chompslash($dir);
		if(0==index($dir, "/")) {
			$roottmp = $dir;
		} elsif (0<length($dir)) {
			chomp($roottmp= `pwd`);
			if ($dir ne ".") {
				$roottmp .= "/$dir";
			}
		} else { # empty $dir
			my @binpaths= split /:/, $ENV{PATH};
			foreach my $p (@binpaths) {
				if (-x "$p/$scriptname" and -r "$p/$scriptname"){
					$roottmp=$p;
					last;
				}
			}
			
		}
	}
	chompslash($roottmp);
	my $tmp = reverse($toolsdir);
	chompslash($toolsdir);
	$toolsdir=reverse($tmp);
#	print "scriptname = $scriptname\n";
#	print "dir = $dir\n";
#	print "rootdir = $roottmp\n";
	$rootdir=$roottmp;
	return ($roottmp . "/$toolsdir");
}
	push @INC, findlibs();
}
use FAUmachineBugList () ;
use FAUmachineBugReport qw(:status) ;
use strict ;
########################################################################
# Constants
########################################################################
my $HELP=<<EOF;
Usage: $0 [options]
One of either --new, --assign, --help, --list or --change-status must be used!
Supported options are (when long options take arguments, so do corresponding
short options):
        -a, --assign=<name>
		If no name is given, it will be asked for interactively.
		Assign bug to somebody (takes -f, -l). Assigning a bug
		will automatically set the status to "open".
	-b, --sort-by=<string>
		List bugs sorted by <string>, where possible values are
		"status", "date", "category", "assigned", "user".
        -c, --compiler-version=<string>
		Compiler version. If not given, will try to figure it
		out myself.
	-e, --edit
		Add to bug description.
        -f, --faum-home=<string>
		Where to look for "config.h", faum-* etc. (default
		is current working directory).
        -h, --help
		Print this help.
	-g, --category
		Change category.
	-l, --list=<string>
		List only those bugs matching <string> (specify fields
		to search with -w). <string> is optional, if not given
		-w will be ignored and all bugs will be listed.
        -n, --new
		Add a new bug (can take -c, -t, -f). Bug information
		will be asked for interactively (title and
		compiler-version may be passed on command line).
	-o, --offline
		Don't do cvs updates/commits. Use this option, when you do
		not have access to the FAUmachine developer's cvs tree. It
		can be used together with any other option.
        -s, --change-status
		Change the status of a bug (takes -f, -l). If status is
		changed to "fixed", a fix-description will be asked for
		interactively.
        -t, --title=<string>
		Short title or one-line summary of bug (if not given
		will be asked for interactively).
	-w, --where=<string>
		Which fields to search (use several times to search a
		number of fields). Possible values are "status",
		"assigned", "title", "description", "category". If not
		given, all fields are searched.
	--check-ascii
		Check whether bug descriptions conform to bug-syntax ;-)
EOF
########################################################################
# Main
########################################################################
MAIN:{
my $faum_home = undef ;

my $new = 0 ; # 0/1
my $assign = undef ; # undef/def
my $list = undef ; # undef/""/string
my $status = 0 ; # 0/1
my $category = 0 ; # 0/1
my $edit = 0 ; # 0/1
my $help = 0 ; # 0/1

my $offline = 0 ; # 0/1

my $title = undef ;
my $compiler = undef ;
my $sortby = "" ;
my $check_ascii = 0;
my @where = () ;
my $ret = Getopt::Long::GetOptions(
	"assign|a:s" => \$assign,
	"sort-by|b=s" => \$sortby,
	"compiler|c=s" => \$compiler,
	"edit|e" => \$edit,
	"faum-home|f=s" => \$faum_home,
	"help|h" => \$help,
	"category|g" => \$category,
	"list|l:s" => \$list,
	"new|n" => \$new,
	"offline|o" => \$offline, 
	"change-status|s" => \$status,
	"title|t=s" => \$title,
	"where|w=s" => \@where,
	"check-ascii" => \$check_ascii,
	) ;
if (0) {
	print STDERR
		"where = @where\n",
		"ret =    >|$ret|<\n" ,
		"help =   >|$help|<\n",
		"status = >|$status|<\n",
		"new =    >|$new|<\n",
		defined $assign? "assign = >|$assign|<\n": "assign = >|undef|<\n",
		defined $list?   "list =   >|$list|<\n":   "list =   >|undef|<\n";
}
if (($ret != 1)
	or $help
	or (not($status or $new or $edit or $category
		or $check_ascii)
		and (not defined $assign)
		and (not defined $list))) {
	print STDERR $HELP ;
	exit(1) ;
}

# Change to FAUmachine-Home-Directory #####################################
chomp(my $cwd = `pwd`) ;
if (not defined $cwd or not -d $cwd) {
	die "Could not get current working directory" ;
}
if (not $faum_home) {
	$faum_home = $cwd ;
}
chdir($faum_home) or # FIXME kb
	die "Could not change to ", $faum_home, "!\n" ;

# Initialize BugList ###################################################
if ($offline) {
	FAUmachineBugList->offline(1) ;
}
my $buglist = FAUmachineBugList->new_ascii() ;
if (not defined $buglist) {
	exit 1 ;
}
if  ($check_ascii) {
	my $buglistascii = FAUmachineBugList->new_ascii();
	$buglistascii->list("");
	last MAIN;
}
### Add new bug ########################################################
if ($new) {
	my $bugreport = FAUmachineBugReport->new({
		$FAUmachineBugReport::O_COMPILER => $compiler,
		$FAUmachineBugReport::O_BUG_TITLE => $title,
		}) ;
	my $file = $buglist->add($bugreport) ;
	print $file;
        if (defined($ENV{'EDITOR'})) {
                system($ENV{'EDITOR'}, $file);
        } else {
		system('vi', $file);
	}
#	$bugreport->page() ;
	print STDOUT "done!\n";
	last MAIN ;
}
### List, Assign, Edit and Change-Status ###############################
### Buglist will be displayed in all cases. ############################
my $displaylist ;
my $message = "" ;
if ($list) {
	$displaylist = $buglist->grep_list($list, \@where) ;
} else {
	$displaylist = $buglist->copy() ;
}
if ($sortby) {
	$displaylist->sortby($sortby)
}
if ((defined $assign) or $status or $edit or $category) {
	$message = "Please copy ID of Bug you want to change" .
		" (to paste later)!\n" ;
}
$displaylist->list($message) ;
my $bug = undef ;
if (not ((defined $assign) or $status or $edit or $category)) {
	last MAIN ;
} else { # more to do

### Assign, Edit and Change-Status #####################################
### Bug-ID must be input in all cases. #################################
	print STDOUT "Please input ID of Bug you want to change!\n" ;
	chomp(my $id = <STDIN>) ;
	$bug = $buglist->get_by_id($id) ;
}
if (defined $assign) {
	if (not $assign) {
		print STDOUT
			"Please input login-name of person to assign bug to: " ;
		chomp($assign = <STDIN>) ;
	} 
	$bug->assignto($assign) ;
}
if ($status) {
	my $oldstatus = $bug->status() ;
	$bug->change_status() ;
	if ($bug->status() eq $oldstatus) {
		print STDERR "Nothing changed!\n" ;
		last MAIN ;
	}
	if ($bug->status() eq STATUS_FIXED) {
		$bug->add_fix_description() ;
	}
}
if ($edit) {
	$bug->edit_bug_description() ;
}
if ($category) {
	$bug->change_category() ;
}
print STDOUT "\nNew value of Bug:\n" ;
print STDOUT "=====================\n" ;
$bug->page() ;
} # MAIN
