gecko-dev/webtools/tinderbox3/server/Tinderbox3/ShowBuilds.pm
2003-02-03 03:44:56 +00:00

260 lines
8.2 KiB
Perl
Executable File

package Tinderbox3::ShowBuilds;
use strict;
use Date::Format;
use Tinderbox3::Header;
use Tinderbox3::TreeColumns;
use Tinderbox3::BonsaiColumns;
use Tinderbox3::BuildTimeColumn;
sub print_showbuilds {
my ($p, $dbh, $fh, $tree, $start_time, $end_time) = @_;
#
# Get tree and patch info
#
my $tree_info = $dbh->selectrow_arrayref("SELECT field_short_names, field_processors, header, footer, special_message, sheriff, build_engineer, cvs_co_date, status, min_row_size, max_row_size FROM tbox_tree WHERE tree_name = ?", undef, $tree);
if (!$tree_info) {
die "Tree $tree does not exist!";
}
my ($field_short_names, $field_processors_str, $header, $footer,
$special_message, $sheriff, $build_engineer, $cvs_co_date, $status,
$min_row_size, $max_row_size) = @{$tree_info};
my %field_processors;
# Create the handlers for the different fields
require Tinderbox3::FieldProcessors::default;
my %field_handlers = ( default => new Tinderbox3::FieldProcessors::default );
foreach my $field_processor (split /,/, $field_processors_str) {
my ($field, $processor) = split /=/, $field_processor;
$field_processors{$field} = $processor;
# Check if the processor is OK to put in an eval statement
if ($processor =~ /^([A-Za-z]+)$/) {
my $code = "require Tinderbox3::FieldProcessors::$processor; \$field_handlers{$processor} = new Tinderbox3::FieldProcessors::$processor();";
eval $code;
}
}
# Get sizes in seconds for easy comparisons
$min_row_size *= 60;
$max_row_size *= 60;
#
# Construct the a href and such for the patches
# XXX do this lazily in case there are no patches
#
my %patch_str;
{
my $sth = $dbh->prepare("SELECT patch_id, patch_name, patch_ref, patch_ref_url, in_use FROM tbox_patch WHERE tree_name = ?");
$sth->execute($tree);
while (my $row = $sth->fetchrow_arrayref) {
my $str;
my $class;
if (!$row->[4]) {
$class = " class=obsolete";
} else {
$class = "";
}
$str = "<span$class><a href='get_patch.pl?patch_id=$row->[0]'>$row->[1]</a>";
if ($row->[2]) {
$str .= " (";
$str .= "<a href='$row->[3]'>" if ($row->[3]);
$str .= $row->[2];
$str .= "</a>" if ($row->[3]);
$str .= ")";
}
$str .= "</span>";
$patch_str{$row->[0]} = $str;
}
}
print $fh "",insert_dynamic_data($header, $tree, $sheriff, $build_engineer, $cvs_co_date, $status, \%patch_str, $start_time, $end_time);
print $fh "",insert_dynamic_data($special_message, $tree, $sheriff, $build_engineer, $cvs_co_date, $status, \%patch_str, $start_time, $end_time);
print_tree($p, $dbh, $fh, $tree, $start_time, $end_time, $field_short_names,
\%field_processors, \%field_handlers, $min_row_size, $max_row_size);
print $fh "",insert_dynamic_data($footer, $tree, $sheriff, $build_engineer, $cvs_co_date, $status, \%patch_str, $start_time, $end_time);
}
sub insert_dynamic_data {
my ($str, $tree, $sheriff, $build_engineer, $cvs_co_date, $status, $patch_str, $start_time, $end_time) = @_;
$str =~ s/#TREE#/$tree/g;
my $time = time2str("%c %Z", time);
$str =~ s/#TIME#/$time/g;
$str =~ s/#SHERIFF#/$sheriff/g;
$str =~ s/#BUILD_ENGINEER#/$build_engineer/g;
$cvs_co_date = 'current' if !$cvs_co_date;
$str =~ s/#CVS_CO_DATE#/$cvs_co_date/g;
$str =~ s/#STATUS#/$status/g;
$str =~ s/#START_TIME_MINUS\((\d+)\)#/$start_time - $1/eg;
$str =~ s/#END_TIME#/$end_time/g;
if ($str =~ /#PATCHES#/) {
my $patches_str = "";
if (keys %{$patch_str}) {
$patches_str = join(', ', values %{$patch_str});
} else {
$patches_str = "None";
}
$str =~ s/#PATCHES#/$patches_str/g;
}
return $str;
}
sub print_tree {
my ($p, $dbh, $fh, $tree, $start_time, $end_time, $field_short_names,
$field_processors, $field_handlers, $min_row_size, $max_row_size) = @_;
# Get the information we will be laying out in the table
my @event_queues;
push @event_queues, new Tinderbox3::BuildTimeColumn($p, $dbh);
push @event_queues, Tinderbox3::BonsaiColumns::get_bonsai_column_queues($p, $dbh, $start_time, $end_time, $tree);
push @event_queues, Tinderbox3::TreeColumns::get_tree_column_queues($p, $dbh, $start_time, $end_time, $tree, $field_short_names, $field_processors, $field_handlers);
my $row_num = -1;
my @rows;
EVENTLOOP:
while (1) {
#
# Get the oldest event from a queue
#
my ($event_time, $event, $please_split);
my $column;
{
my $most_recent_queue = -1;
my $most_recent_time = -1;
for (my $queue_num = 1; $queue_num < @event_queues; $queue_num++) {
my $queue = $event_queues[$queue_num];
if (!$queue->is_empty()) {
if ($most_recent_time == -1 ||
$queue->first_event_time() < $most_recent_time) {
$most_recent_queue = $queue_num;
$most_recent_time = $queue->first_event_time();
}
}
}
# Break if there were no non-empty queues
if ($most_recent_time < 0) {
last EVENTLOOP;
}
($event_time, $event, $please_split) = $event_queues[$most_recent_queue]->pop_first();
if ($event_time != $most_recent_time) {
die "Event time not what was expected!";
}
$column = $most_recent_queue;
}
#
# If there are no rows yet, create the first row with this event time
#
if ($row_num == -1) {
push @rows, [ $event_time ];
$row_num++;
} else {
#
# If event is outside the maximum boundary, start adding rows of
# max_row_size to compensate
#
# XXX potential problem: one really wants cells to start at events
# whenever possible, and when we use this algorithm, if the event in
# question happens to be inside the minimum row time, we will not split
# for it so the cell will not start at the event. This can be compensated
# for by building these new cells *down* from the cell in question, but
# it would require more strange cases than I care to deal with right now
# so I'm not coding it. JBK
#
if ($max_row_size > 0) {
while ($event_time > ($rows[$row_num][0] + $max_row_size)) {
push @rows, [ $rows[$row_num][0] + $max_row_size ];
$row_num++;
}
}
#
# If event has asked to split, and is outside the minimum boundary (so
# that we *can* split, split the row.
#
if ($please_split && $event_time > ($rows[$row_num][0] + $min_row_size)) {
push @rows, [ $event_time ];
$row_num++;
}
}
#
# Finally, add the event to the current row.
#
push @{$rows[$row_num][$column]}, $event;
}
#
# Ensure there is at least one row
#
if ($row_num < 0) {
push @rows, [ $start_time ];
$row_num++;
}
#
# Add extra rows if the tinderbox does not go up to the end time
#
if ($max_row_size > 0) {
while ($end_time > ($rows[$row_num][0] + $max_row_size)) {
push @rows, [ $rows[$row_num][0] + $max_row_size ];
$row_num++;
}
}
#
# Add extra rows if the tinderbox does not start at the start time
#
if ($start_time < $rows[0][0]) {
if ($max_row_size > 0) {
do {
unshift @rows, [ $rows[0][0] - $max_row_size ];
} while ($start_time < $rows[0][0]);
# Fix the last row to be start time ;)
if ($rows[0][0] < $start_time) {
$rows[0][0] = $start_time;
}
} else {
unshift @rows, [ $start_time ];
}
}
#
# Print head of table
#
print $fh "<table class=tinderbox>\n";
print $fh "<thead><tr>\n";
for (my $queue_num = 0; $queue_num < @event_queues; $queue_num++) {
print $fh $event_queues[$queue_num]->column_header(\@rows, $queue_num);
}
print $fh "</tr>\n";
print $fh "<tr>\n";
for (my $queue_num = 0; $queue_num < @event_queues; $queue_num++) {
print $fh $event_queues[$queue_num]->column_header_2(\@rows, $queue_num);
}
print $fh "</tr></thead>\n";
#
# Print body of table
#
print $fh "<tbody>\n";
for(my $row_num = (@rows - 1); $row_num >= 0; $row_num--) {
print $fh "<tr>";
for (my $queue_num = 0; $queue_num < @event_queues; $queue_num++) {
print $fh $event_queues[$queue_num]->cell(\@rows, $row_num, $queue_num);
}
print $fh "</tr>\n";
}
print $fh "</tbody>\n";
print $fh "</table>\n";
}
1