use strict;
use FindBin;
use lib "$FindBin::Bin/lib";
use Date::Calc qw{Delta_DHMS This_Year};
use DBI;
use Getopt::Long;
my $help = 0;
my $create = 0;
my $id = '';
my $file = '';
my $verbose = 0;
my $dryrun = 0;
GetOptions((
'create!' => \$create,
'file=s' => \$file,
'id=s' => \$id,
'help!' => \$help,
'verbose!' => \$verbose,
'dryrun!' => \$dryrun,
));
if ($help||!$file)
{
print <<_EOH;
bitops
Executes operations on the BIT db
Usage: bitops.pl [-c|-i ID] -f FILE
Options:
-h, --help Show this help message and exit
-c, --create Create entry for a new build then set the attributes to
the values provided in FILE. Returns the build id for
the newly created build.
-i ID, --id ID Update entry for build number ID with the values
provided in FILE.
-f FILE, --file FILE Use attributes in FILE to create/update the build info
See below for file format.
-v, --verbose Increase info level
-d, --dryrun Only show what would happen, do not actually interact
with the DB
File format:
File must be a list of attribute-value-pairs. One avp per line, on each line
attribute and value are separated by a tab.
These are the supported attributes (in brackets the syntax of the value):
- build_id_string
- package (VALUE)
- platform (VALUE)
- started (VALUE)
- finished (VALUE)
- creator (VALUE)
- machine (VALUE)
- build_brag (VALUE)
- test_brag (VALUE)
- baseline_short (VALUE)
- sources_short (VALUE)
- envinfo (TOOL,VERSION)
- failure (CATEGORY,COUNT)
- report (NAME,URL,TYPE)
- content (NAME,URL,REVISION)
- baseline (TYPE,PATH)
- label (VALUE)
_EOH
exit(0);
}
my $db = undef;
my $builds_entry = {};
my $envinfo = [];
my $failures = [];
my $reports = [];
my $content = [];
my $baselines = [];
my $labels = [];
my $testing_entry = {};
sub ConnectToDB()
{
$db = DBI->connect('DBI:mysql:bit:v800016:3306','fbf','mysql')
or die("Couldn't connect to database: " . DBI->errstr()) if (!$dryrun);
}
sub DisconnectFromDB()
{
$db->disconnect() if (!$dryrun);
}
sub parse_file
{
my ($file) = @_;
print "Reading $file...\n" if ($verbose);
open(FILE, $file) or die "Can't open file $file";
while (<FILE>)
{
my $line = $_;
chomp $line;
$line =~ s/^\s//g;
$line =~ s/\s$//g;
next if ($line !~ /[^\s]/);
if ($line =~ /([^\t]+)\t([^\t]+)/)
{
my $attr = $1;
my $value = $2;
if ($attr =~ /^(build_id_string|package|platform|started|finished|creator|machine|build_brag|test_brag|baseline_short|sources_short)$/i)
{
$attr = lc($attr);
print " found ($attr,$value) for table 'build'\n" if ($verbose);
$builds_entry->{$attr}=$value;
}
elsif ($attr =~ /^(envinfo)$/i)
{
$attr = lc($attr);
if ($value =~ /([^,]*),([^,]*)/)
{
my $tool = $1;
my $version = $2;
if (!$tool || !$version)
{
print "ERROR: Tool or version empty: \"$value\"\n";
return 1;
}
print " found ($tool,$version) for table 'envinfo'\n" if ($verbose);
push(@{$envinfo}, {tool=>$tool, version=>$version});
}
else
{
print "ERROR: Could not understand value of envinfo: \"$value\"\n";
return 1;
}
}
elsif ($attr =~ /^(failure)$/i)
{
$attr = lc($attr);
if ($value =~ /([^,]*),([^,]*)/)
{
my $category = $1;
my $count = $2;
if (!$category || !defined $count || $count eq '')
{
print "ERROR: Category or count empty: \"$value\"\n";
return 1;
}
print " found ($category,$count) for table 'failures'\n" if ($verbose);
push(@{$failures}, {category=>$category, count=>$count});
}
else
{
print "ERROR: Could not understand value of failure: \"$value\"\n";
return 1;
}
}
elsif ($attr =~ /^(report)$/i)
{
$attr = lc($attr);
if ($value =~ /([^,]*),([^,]*),([^,]*)/)
{
my $name = $1;
my $url = $2;
my $type = $3;
if (!$name || !$url || !$type)
{
print "ERROR: Name, url or type empty: \"$value\"\n";
return 1;
}
print " found ($name,$url,$type) for table 'reports'\n" if ($verbose);
push(@{$reports}, {name=>$name, url=>$url, type=>$type});
}
else
{
print "ERROR: Could not understand value of report: \"$value\"\n";
return 1;
}
}
elsif ($attr =~ /^(content)$/i)
{
$attr = lc($attr);
if ($value =~ /([^,]*),([^,]*),([^,]*)/)
{
my $name = $1;
my $url = $2;
my $revision = $3;
if (!$name || !$url || !$revision)
{
print "ERROR: Name, url or revision empty: \"$value\"\n";
return 1;
}
print " found ($name,$url,$revision) for table 'content'\n" if ($verbose);
push(@{$content}, {name=>$name, url=>$url, revision=>$revision});
}
else
{
print "ERROR: Could not understand value of content: \"$value\"\n";
return 1;
}
}
elsif ($attr =~ /^(baseline)$/i)
{
$attr = lc($attr);
if ($value =~ /([^,]*),([^,]*)/)
{
my $type = $1;
my $path = $2;
if (!$type || !$path)
{
print "ERROR: Type or path empty: \"$value\"\n";
return 1;
}
print " found ($type,$path) for table 'baselines'\n" if ($verbose);
push(@{$baselines}, {type=>$type, path=>$path});
}
else
{
print "ERROR: Could not understand value of baseline: \"$value\"\n";
return 1;
}
}
elsif ($attr =~ /^(label)$/i)
{
print " found ($attr,$value) for table 'labels'\n" if ($verbose);
push(@{$labels}, {label=>$value});
}
else
{
print "ERROR: Could not understand avp: \"$line\"\n";
return 1;
}
}
else
{
print "WARNING: line \"$line\" does not seem a correctly formed attribute-value-pair (tab-separated)\n";
return 1;
}
}
close(FILE);
return 0;
}
# MAIN PROGRAM
my $r=parse_file($file);
if ($r)
{
print "Error while parsing file $file\n";
exit(1);
}
print "Executing SQL commands...\n" if ($verbose);
ConnectToDB();
my $newbuildid = -1;
if ($create)
{
if (keys %{$builds_entry})
{
my $field_list = '';
my $qm_list = '';
my @fields = ();
for my $field (keys %{$builds_entry})
{
$field_list .= "$field,";
$qm_list .= "?,";
push(@fields,$builds_entry->{$field});
}
$field_list =~ s/,$//;
$qm_list =~ s/,$//;
my $query = $db->prepare("insert into builds ($field_list) values ($qm_list)")
or die("Couldn't prepare query insert into builds: " . $db->errstr()) if (!$dryrun);
$query->execute(@fields)
or print "WARNING: Couldn't execute insert into builds (@fields): " . $db->errstr() . "\n" if (!$dryrun);
$newbuildid = $db->last_insert_id(undef, undef, undef, undef) if (!$dryrun);
}
if (@{$envinfo})
{
my $query = $db->prepare_cached("insert into envinfo (build_id,tool,version) values ($newbuildid,?,?)")
or die("Couldn't prepare query insert into envinfo: " . $db->errstr()) if (!$dryrun);
for my $entry (@{$envinfo})
{
my $tool = $entry->{tool};
my $version = $entry->{version};
$query->execute($tool, $version)
or print "WARNING: Couldn't execute insert into envinfo ($tool,$version): " . $db->errstr() . "\n" if (!$dryrun);
}
}
if (@{$failures})
{
print " prepare_cached 'insert into failures (build_id,category,count) values ($newbuildid,?,?)'\n" if ($verbose);
my $query = $db->prepare_cached("insert into failures (build_id,category,count) values ($newbuildid,?,?)")
or die("Couldn't prepare query insert into failures: " . $db->errstr()) if (!$dryrun);
for my $entry (@{$failures})
{
my $category = $entry->{category};
my $count = $entry->{count};
print " execute '$category, $count'\n" if ($verbose);
$query->execute($category, $count)
or print "WARNING: Couldn't execute insert into failures ($category,$count): " . $db->errstr() . "\n" if (!$dryrun);
}
}
if (@{$reports})
{
print " prepare_cached 'insert into reports (build_id,name,url,type) values ($newbuildid,?,?,?)'\n" if ($verbose);
my $query = $db->prepare_cached("insert into reports (build_id,name,url,type) values ($newbuildid,?,?,?)")
or die("Couldn't prepare query insert into reports: " . $db->errstr()) if (!$dryrun);
for my $entry (@{$reports})
{
my $name = $entry->{name};
my $url = $entry->{url};
my $type = $entry->{type};
print " execute '$name, $url, $type'\n" if ($verbose);
$query->execute($name, $url, $type)
or print "WARNING: Couldn't execute insert into reports ($name,$url,$type): " . $db->errstr() . "\n" if (!$dryrun);
}
}
if (@{$content})
{
print " prepare_cached 'insert into content (build_id,name,url,revision) values ($newbuildid,?,?,?)'\n" if ($verbose);
my $query = $db->prepare_cached("insert into content (build_id,name,url,revision) values ($newbuildid,?,?,?)")
or die("Couldn't prepare query insert into content: " . $db->errstr()) if (!$dryrun);
for my $entry (@{$content})
{
my $name = $entry->{name};
my $url = $entry->{url};
my $revision = $entry->{revision};
print " execute '$name, $url, $revision'\n" if ($verbose);
$query->execute($name, $url, $revision)
or print "WARNING: Couldn't execute insert into content ($name,$url,$revision): " . $db->errstr() . "\n" if (!$dryrun);
}
}
if (@{$baselines})
{
print " prepare_cached 'insert into baselines (build_id,type,path) values ($newbuildid,?,?)'\n" if ($verbose);
my $query = $db->prepare_cached("insert into baselines (build_id,type,path) values ($newbuildid,?,?)")
or die("Couldn't prepare query insert into baselines: " . $db->errstr()) if (!$dryrun);
for my $entry (@{$baselines})
{
my $type = $entry->{type};
my $path = $entry->{path};
print " execute '$type, $path'\n" if ($verbose);
$query->execute($type, $path)
or print "WARNING: Couldn't execute insert into baselines ($type,$path): " . $db->errstr() . "\n" if (!$dryrun);
}
}
if (@{$labels})
{
print " prepare_cached 'insert into labels (build_id,label) values ($newbuildid,?)'\n" if ($verbose);
my $query = $db->prepare_cached("insert into labels (build_id,label) values ($newbuildid,?)")
or die("Couldn't prepare query insert into labels: " . $db->errstr()) if (!$dryrun);
for my $entry (@{$labels})
{
my $label = $entry->{label};
print " execute '$label'\n" if ($verbose);
$query->execute($label)
or print "WARNING: Couldn't execute insert into revision ($label): " . $db->errstr() . "\n" if (!$dryrun);
}
}
print "new build id: $newbuildid\n";
}
else
{
print "Updating build $id\n";
if (keys %{$builds_entry})
{
my $field_list = '';
my @fields = ();
for my $field (keys %{$builds_entry})
{
$field_list .= "$field=?,";
push(@fields,$builds_entry->{$field});
}
$field_list =~ s/,$//;
print " prepare 'update builds set $field_list where id=$id'\n" if ($verbose);
my $query = $db->prepare("update builds set $field_list where id=$id")
or die("Couldn't prepare query update builds: " . $db->errstr()) if (!$dryrun);
print " execute '@fields'\n" if ($verbose);
$query->execute(@fields)
or print "WARNING: Couldn't execute update builds (@fields): " . $db->errstr() . "\n" if (!$dryrun);
}
if (@{$envinfo})
{
print " prepare 'delete from envinfo where build_id=$id'\n" if ($verbose);
my $delete_query = $db->prepare("delete from envinfo where build_id=$id")
or die("Couldn't prepare query delete from envinfo: " . $db->errstr()) if (!$dryrun);
print " execute ''\n" if ($verbose);
$delete_query->execute()
or print "WARNING: Couldn't execute delete from envinfo: " . $db->errstr() . "\n" if (!$dryrun);
print " prepare 'insert into envinfo (build_id,tool,version) values ($id,?,?)'\n" if ($verbose);
my $query = $db->prepare_cached("insert into envinfo (build_id,tool,version) values ($id,?,?)")
or die("Couldn't prepare query insert into envinfo: " . $db->errstr()) if (!$dryrun);
for my $entry (@{$envinfo})
{
my $tool = $entry->{tool};
my $version = $entry->{version};
print " execute '$tool,$version'\n" if ($verbose);
$query->execute($tool, $version)
or print "WARNING: Couldn't execute insert into envinfo ($tool,$version): " . $db->errstr() . "\n" if (!$dryrun);
}
}
if (@{$failures})
{
print " prepare 'delete from failures where build_id=$id'\n" if ($verbose);
my $delete_query = $db->prepare("delete from failures where build_id=$id")
or die("Couldn't prepare query delete from failures: " . $db->errstr()) if (!$dryrun);
print " execute ''\n" if ($verbose);
$delete_query->execute()
or print "WARNING: Couldn't execute delete from failures: " . $db->errstr() . "\n" if (!$dryrun);
print " prepare 'insert into failures (build_id,category,count) values ($id,?,?)'\n" if ($verbose);
my $query = $db->prepare_cached("insert into failures (build_id,category,count) values ($id,?,?)")
or die("Couldn't prepare query insert into failures: " . $db->errstr()) if (!$dryrun);
for my $entry (@{$failures})
{
my $category = $entry->{category};
my $count = $entry->{count};
print " execute '$category,$count'\n" if ($verbose);
$query->execute($category, $count)
or print "WARNING: Couldn't execute insert into failures ($category,$count): " . $db->errstr() . "\n" if (!$dryrun);
}
}
if (@{$reports})
{
print " prepare 'delete from reports where build_id=$id'\n" if ($verbose);
my $delete_query = $db->prepare("delete from reports where build_id=$id")
or die("Couldn't prepare query delete from reports: " . $db->errstr()) if (!$dryrun);
print " execute ''\n" if ($verbose);
$delete_query->execute()
or print "WARNING: Couldn't execute delete from reports: " . $db->errstr() . "\n";
print " prepare 'insert into reports (build_id,name,url,type) values ($id,?,?,?)'\n" if ($verbose);
my $query = $db->prepare_cached("insert into reports (build_id,name,url,type) values ($id,?,?,?)")
or die("Couldn't prepare query insert into failures: " . $db->errstr()) if (!$dryrun);
for my $entry (@{$reports})
{
my $name = $entry->{name};
my $url = $entry->{url};
my $type = $entry->{type};
print " execute '$name,$url,$type'\n" if ($verbose);
$query->execute($name, $url, $type)
or print "WARNING: Couldn't execute insert into reports ($name,$url,$type): " . $db->errstr() . "\n" if (!$dryrun);
}
}
if (@{$content})
{
print " prepare 'delete from content where build_id=$id'\n" if ($verbose);
my $delete_query = $db->prepare("delete from content where build_id=$id")
or die("Couldn't prepare query delete from content: " . $db->errstr()) if (!$dryrun);
print " execute ''\n" if ($verbose);
$delete_query->execute()
or print "WARNING: Couldn't execute delete from content: " . $db->errstr() . "\n" if (!$dryrun);
print " prepare 'insert into content (build_id,name,url,revision) values ($id,?,?,?)'\n" if ($verbose);
my $query = $db->prepare_cached("insert into content (build_id,name,url,revision) values ($id,?,?,?)")
or die("Couldn't prepare query insert into content: " . $db->errstr()) if (!$dryrun);
for my $entry (@{$content})
{
my $name = $entry->{name};
my $url = $entry->{url};
my $revision = $entry->{revision};
print " execute '$name,$url,$revision'\n" if ($verbose);
$query->execute($name, $url, $revision)
or print "WARNING: Couldn't execute insert into content ($name,$url,$revision): " . $db->errstr() . "\n" if (!$dryrun);
}
}
if (@{$baselines})
{
print " prepare 'delete from baselines where build_id=$id'\n" if ($verbose);
my $delete_query = $db->prepare("delete from baselines where build_id=$id")
or die("Couldn't prepare query delete from baselines: " . $db->errstr()) if (!$dryrun);
print " execute ''\n" if ($verbose);
$delete_query->execute()
or print "WARNING: Couldn't execute delete from baselines: " . $db->errstr() . "\n" if (!$dryrun);
print " prepare 'insert into baselines (build_id,type,path) values ($id,?,?)'\n" if ($verbose);
my $query = $db->prepare_cached("insert into baselines (build_id,type,path) values ($id,?,?)")
or die("Couldn't prepare query insert into baselines: " . $db->errstr()) if (!$dryrun);
for my $entry (@{$baselines})
{
my $type = $entry->{type};
my $path = $entry->{path};
print " execute '$type,$path'\n" if ($verbose);
$query->execute($type, $path)
or print "WARNING: Couldn't execute insert into baselines ($type,$path): " . $db->errstr() . "\n" if (!$dryrun);
}
}
if (@{$labels})
{
print " prepare 'delete from labels where build_id=$id'\n" if ($verbose);
my $delete_query = $db->prepare("delete from labels where build_id=$id")
or die("Couldn't prepare query delete from labels: " . $db->errstr()) if (!$dryrun);
print " execute ''\n" if ($verbose);
$delete_query->execute()
or print "WARNING: Couldn't execute delete from labels: " . $db->errstr() . "\n" if (!$dryrun);
print " prepare 'insert into labels (build_id,label) values ($id,?)'\n" if ($verbose);
my $query = $db->prepare_cached("insert into label (build_id,label) values ($id,?)")
or die("Couldn't prepare query insert into label: " . $db->errstr()) if (!$dryrun);
for my $entry (@{$labels})
{
my $label = $entry->{label};
print " execute '$label'\n" if ($verbose);
$query->execute($label)
or print "WARNING: Couldn't execute insert into labels ($label): " . $db->errstr() . "\n" if (!$dryrun);
}
}
}
DisconnectFromDB();