зеркало из https://github.com/mozilla/gecko-dev.git
add support for the Req Ticketing system.
This commit is contained in:
Родитель
930b59df79
Коммит
6bc80bec3b
|
@ -0,0 +1,242 @@
|
|||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
|
||||
# ReqData.pm - the configuration file which describes the local
|
||||
# configuration for the Req Bug Tracking system
|
||||
# (http://www.draga.com/~jwise/minireq/) and its relationship to the
|
||||
# tinderbox trees.
|
||||
|
||||
|
||||
# $Revision: 1.1 $
|
||||
# $Date: 2001/11/16 20:43:27 $
|
||||
# $Author: kestes%walrus.com $
|
||||
# $Source: /home/hwine/cvs_conversion/cvsroot/mozilla/webtools/tinderbox2/src/default_conf/ReqData.pm,v $
|
||||
# $Name: $
|
||||
|
||||
|
||||
# The contents of this file are subject to the Mozilla Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is the Tinderbox build tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
|
||||
# complete rewrite by Ken Estes:
|
||||
# kestes@staff.mail.com Old work.
|
||||
# kestes@tradinglinx.com New work.
|
||||
# kestes@walrus.com Home.
|
||||
# Contributor(s):
|
||||
|
||||
|
||||
# This package is used for configuring the Generic Bug Tracking system
|
||||
# module. I belive that this will handle most bug tracking systems.
|
||||
# We assume that bugs are stored in a database (each bug has a known
|
||||
# list of field names) and that a subset of the fields will be of
|
||||
# interest to the tinderbox users (tinderbox is not the correct place
|
||||
# to display any sort of long comment field). Tinderbox will display
|
||||
# the bug number and a popup window showing relevant fields discribing
|
||||
# this bug. If the users wishes more information they may click on
|
||||
# the link and be taken directly to the bugtracking system for more
|
||||
# information about the bug. Bugs have their state change as the bug
|
||||
# is worked on and users of tinderbox wish to see information about
|
||||
# the bug as the state changes. We divide state changes into two
|
||||
# types: 'Progress', 'Slippage'. Most important is to get a feel for
|
||||
# the number of bugs which move into bad/backward states ('REOPENED').
|
||||
|
||||
# Users will certainly need to configure the tables in this module for
|
||||
# their needs. Additionally users need to define how to convert
|
||||
# information about each bug to the correct tinderbox tree that this
|
||||
# bug belongs. This is handled by defining the update2tree() function
|
||||
# as appropriate.
|
||||
|
||||
|
||||
|
||||
package ReqData;
|
||||
|
||||
# This package must not use any tinderbox specific libraries. It is
|
||||
# intended to be a base class.
|
||||
|
||||
|
||||
$VERSION = '#tinder_version#';
|
||||
|
||||
|
||||
|
||||
$REQ_URL = ($TinderConfig::REQ_URL ||
|
||||
'http://buildweb.reefedge.com/cgi-bin/req');
|
||||
|
||||
$REQ_HOME = ($TinderConfig::REQ_HOME ||
|
||||
"/home/req");
|
||||
|
||||
$REQ_URL = "http://buildweb.reefedge.com/cgi-bin/";
|
||||
|
||||
|
||||
$REQ_HOME = "/home/req";
|
||||
|
||||
# the name of the bug tracking field which shows bug_id
|
||||
|
||||
$BUGID_FIELD_NAME = 'Ticket_Num';
|
||||
|
||||
$STATUS_FIELD_NAME = 'Action';
|
||||
|
||||
|
||||
# The values of the status field wich denote that the ticket is moving
|
||||
# forward. Notice that this list may not be complete as we are only
|
||||
# interested in displaying Developer progress. If the ticket is moving
|
||||
# through QA tinderbox may not be the correct place to see that
|
||||
# change. In particular newly opend tickets are not particularly
|
||||
# interesting when monitoring the development process.
|
||||
|
||||
# All status values are converted to lower case for ease of
|
||||
# processing. Each value of this table corresponds to a bug column in
|
||||
# the tinderbox status page. You may have as many bug columns as you
|
||||
# like. If you wish to indicate that certain states are possible but
|
||||
# should not be displayed then indicate the state with a null string.
|
||||
|
||||
%STATUS_PROGRESS = (
|
||||
'commented' => 'Progress',
|
||||
'created' => 'Progress',
|
||||
'given' => 'Progress',
|
||||
'killed' => 'Progress',
|
||||
'notified' => 'Progress',
|
||||
'opened' => 'Progress',
|
||||
'resolved' => 'Progress',
|
||||
'stalled' => 'Progress',
|
||||
'subject_changed' => 'Progress',
|
||||
'taken' => 'Progress',
|
||||
'untaken' => 'Progress',
|
||||
'user_set' => 'Progress',
|
||||
);
|
||||
|
||||
|
||||
# Uncomment only the fields you wish displayed in the popup window,
|
||||
# The fields will be displayed in the order they are listed here.
|
||||
# Only uncomment fields which are interesting. Fields which are empty
|
||||
# will still be displayed.
|
||||
|
||||
@DISPLAY_FIELDS = (
|
||||
'Subject',
|
||||
'Ticket_Num',
|
||||
'Complete_Action',
|
||||
'Author',
|
||||
);
|
||||
|
||||
|
||||
# turn a tree name into a Req queue name.
|
||||
|
||||
sub tree2queue {
|
||||
my ($tree_name) = @_;
|
||||
|
||||
my $queue_name = lc($tree_name);
|
||||
$queue_name =~ s/^b-//;
|
||||
|
||||
return $queue_name;
|
||||
}
|
||||
|
||||
|
||||
# turn a tree name into the name of a its file.
|
||||
|
||||
sub tree2logfile {
|
||||
my ($tree_name) = @_;
|
||||
|
||||
my $queue_name = tree2queue($tree_name);
|
||||
my $req_log = "$REQ_HOME/releng-${queue_name}/etc/req-log";
|
||||
|
||||
return $req_log;
|
||||
}
|
||||
|
||||
|
||||
# Given a pointer to a bug update hash, return the name of the tree to
|
||||
# which this bug report belongs. Typically this will be the contents
|
||||
# of a field like 'Product', (if you have one tinderbox page for each
|
||||
# product in your bug database) however some projects may be more
|
||||
# compicated.
|
||||
|
||||
# One example of a complex function to determine tree name would be if
|
||||
# each of the product product types listed in the bug tracking data
|
||||
# base refers to one development project, except for a particular
|
||||
# feature/platform of one particular project which is being developed
|
||||
# by a separate group of developers. So the version control notion of
|
||||
# trees (a set of modules on a branch) may not have a direct map into
|
||||
# the bug tracking database at all times.
|
||||
|
||||
# This function should return the null list '()' if the bug report
|
||||
# should be ignored by the tinderbox server. The function returns a
|
||||
# list of trees which should display the data about this bug update.
|
||||
|
||||
sub update2tree {
|
||||
my ($tinderbox_ref) = @_;
|
||||
|
||||
my ($out);
|
||||
|
||||
my @out = (
|
||||
'ALL',
|
||||
$tinderbox_ref->{'Tree'},
|
||||
);
|
||||
|
||||
# It might be a good idea to call TreeData::tree_exists() and ensure
|
||||
# that this tree is valid, but this would make it harder for testing
|
||||
# using genbugs.
|
||||
|
||||
return (@out);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# Given a bug id return a URL ('href') to the bug.
|
||||
# If the bug tracker does not support URL's to a bug number,
|
||||
# return a 'mailto: ' to someone who cares about the bug.
|
||||
|
||||
sub bug_id2bug_url {
|
||||
my ($tinderbox_ref) = @_;
|
||||
|
||||
|
||||
$url = (
|
||||
$REQ_URL.
|
||||
"/".
|
||||
$tinderbox_ref->{'Queue'}.
|
||||
"-req/req.cgi/show/".
|
||||
$tinderbox_ref->{'Ticket_Num'}.
|
||||
"");
|
||||
|
||||
return $url;
|
||||
}
|
||||
|
||||
|
||||
sub get_all_progress_states {
|
||||
|
||||
my (@progress_states) = main::uniq( values %BTData::STATUS_PROGRESS );
|
||||
|
||||
# If the first element is null ignore it.
|
||||
($progress_states[0]) ||
|
||||
(shift @progress_states);
|
||||
|
||||
return @progress_states;
|
||||
}
|
||||
|
||||
|
||||
sub is_status_valid {
|
||||
my ($status) = @_;
|
||||
|
||||
|
||||
# hard code for now
|
||||
return 1;
|
||||
|
||||
my $out = defined($STATUS_PROGRESS{$status});
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
1;
|
||||
|
|
@ -0,0 +1,485 @@
|
|||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
|
||||
# TinderDB::BT_Req - A modified version of BT_Generic to allow
|
||||
# tinderbox to interface with the Req bug tracking system.
|
||||
# (http://www.draga.com/~jwise/minireq/) eventually the common code
|
||||
# should be factrored out into separate classes but I do not have time
|
||||
# now and the files are only about 400 lines long. The main
|
||||
# difference is that Req requires us to parse a log file for each
|
||||
# tree. Thus we pull the data into our datastructures instead of
|
||||
# having the mail system push it in.
|
||||
|
||||
# The current design of these BT modules does not allow me to have two
|
||||
# copies of the same module (ie two colums both of thehm BT but
|
||||
# configured to use different bug tracking system. This is due to
|
||||
# global variables in the module and the way we configure the system
|
||||
# in TinderConfig and BTData.
|
||||
|
||||
# The contents of this file are subject to the Mozilla Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is the Tinderbox build tool.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape Communications
|
||||
# Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
|
||||
# complete rewrite by Ken Estes:
|
||||
# kestes@staff.mail.com Old work.
|
||||
# kestes@reefedge.com New work.
|
||||
# kestes@walrus.com Home.
|
||||
# Contributor(s):
|
||||
|
||||
|
||||
|
||||
package TinderDB::BT_Req;
|
||||
|
||||
|
||||
# We store the hash of all names who modified the tree at a
|
||||
# particular time as follows:
|
||||
|
||||
# $DATABASE{$tree}{$timenow}{$status}{$bug_id} = $record;
|
||||
|
||||
# Where $rec is an anoymous hash of name vaule pairs from the bug
|
||||
# tracking system.
|
||||
|
||||
# we also store information in the metadata structure
|
||||
|
||||
# $METADATA{$tree}{'updates_since_trim'} += 1;
|
||||
#
|
||||
|
||||
# Load standard perl libraries
|
||||
use Time::Local;
|
||||
|
||||
# Load Tinderbox libraries
|
||||
|
||||
use lib '#tinder_libdir#';
|
||||
|
||||
use HTMLPopUp;
|
||||
use MailProcess;
|
||||
use TinderDB::BasicTxtDB;
|
||||
use TreeData;
|
||||
use ReqData;
|
||||
use Utils;
|
||||
use VCDisplay;
|
||||
|
||||
|
||||
|
||||
$VERSION = ( qw $Revision: 1.1 $ )[1];
|
||||
|
||||
@ISA = qw(TinderDB::BasicTxtDB);
|
||||
|
||||
# Add an empty object, of this DB subclass, to end of the set of all
|
||||
# HTML columns. This registers the subclass with TinderDB and defines
|
||||
# the order of the HTML columns.
|
||||
|
||||
push @TinderDB::HTML_COLUMNS, TinderDB::BT_Req->new();
|
||||
|
||||
|
||||
# name of the bug tracking system
|
||||
$REQ_NAME = $TinderConfig::REQ_NAME || "Req";
|
||||
|
||||
# Return the oldest time we have data for.
|
||||
# This should not be older then the time we would keep if we
|
||||
# were to trim the database now.
|
||||
|
||||
sub find_last_data {
|
||||
my ($tree) = @_;
|
||||
|
||||
my $oldest_allowed_time = $main::TIME - $TinderDB::TRIM_SECONDS;
|
||||
|
||||
my $last_tree_data = (sort keys %{ $DATABASE{$tree} })[0];
|
||||
|
||||
($last_tree_data < $oldest_allowed_time) &&
|
||||
($last_tree_data = $oldest_allowed_time);
|
||||
|
||||
return $last_tree_data;
|
||||
}
|
||||
|
||||
|
||||
# untaint the variable and values parsed from trouble ticket mail.
|
||||
|
||||
sub clean_bug_input {
|
||||
my ($var, $value) = @_;
|
||||
|
||||
# untaint data for safety
|
||||
|
||||
$var = main::extract_printable_chars($var);
|
||||
|
||||
# the input is HTML so it is a good idea to escape it
|
||||
|
||||
$value = main::extract_html_chars($value);
|
||||
$value = HTMLPopUp::escapeHTML($value);
|
||||
|
||||
# remove spaces at beginning and end of lines
|
||||
|
||||
$value =~ s/\s+$//;
|
||||
$value =~ s/^\s+//;
|
||||
|
||||
$var =~ s/\s+$//;
|
||||
$var =~ s/^\s+//;
|
||||
|
||||
|
||||
# There are spaces in some of the variable names,
|
||||
# convert these to underlines to make processing easier.
|
||||
|
||||
$var =~ s/\s+/_/g;
|
||||
|
||||
return ($var, $value);
|
||||
}
|
||||
|
||||
|
||||
# remove all records from the database which are older then last_time.
|
||||
|
||||
sub trim_db_history {
|
||||
my ($self, $tree,) = (@_);
|
||||
|
||||
my ($last_time) = $main::TIME - $TinderDB::TRIM_SECONDS;
|
||||
|
||||
# sort numerically ascending
|
||||
my (@times) = sort {$a <=> $b} keys %{ $DATABASE{$tree} };
|
||||
foreach $time (@times) {
|
||||
($time >= $last_time) && last;
|
||||
|
||||
delete $DATABASE{$tree}{$time};
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
# get the recent data from the Req log file. There is one log file
|
||||
# per tree.
|
||||
|
||||
|
||||
sub apply_db_updates {
|
||||
my ($self, $tree, ) = @_;
|
||||
|
||||
my $queue_name = ReqData::tree2queue($tree);
|
||||
my $req_log = ReqData::tree2logfile($tree);
|
||||
my $added_lines = 0;
|
||||
my $last_tree_data = find_last_data($tree);
|
||||
my $year = 1900 + (localtime(time()))[5];
|
||||
|
||||
# We may not have req running on every branch so the log files may
|
||||
# not exist.
|
||||
|
||||
(-r $req_log) ||
|
||||
next;
|
||||
|
||||
open (REQ_LOG, "<$req_log") ||
|
||||
die("Could not open req logfile: $req_log\n");
|
||||
|
||||
foreach $line (<REQ_LOG>) {
|
||||
|
||||
|
||||
# the log file looks like this.
|
||||
|
||||
# FW: CVS update: reef/distrib/sets (#2) created via mail by Rich@reefedge.com. 12:32:37, Nov 15
|
||||
# FW: CVS update: reef/distrib/sets (#2) given to rich by jim. 13:46:13, Nov 15
|
||||
|
||||
|
||||
if ( $line =~ m!
|
||||
^(.+) # the subject can contain spaces
|
||||
\s+\(\#(\d+)\)\s+ # bug number in parentheses
|
||||
(.*) # the action taken, can contain spaces
|
||||
\s+by\s+ #
|
||||
([A-Za-z0-9\.\@]+)\.\s+ # author (may contain '@', '.',)
|
||||
# with a period terminator
|
||||
(\d+)\:(\d+)\:(\d+)\,\s # time in colon delimited format
|
||||
# with coma terminator
|
||||
(\w+)\s(\d+)\n$ # three letter month and month day
|
||||
!x ) {
|
||||
|
||||
my %tinderbox = (
|
||||
'Subject' => $1,
|
||||
'Ticket_Num' => $2,
|
||||
'Complete_Action' => $3,
|
||||
'Action' => $3,
|
||||
'Author' => $4,
|
||||
'Hour' => $5,
|
||||
'Minute' => $6,
|
||||
'Second' => $7,
|
||||
'Month' => $8,
|
||||
'Month_Day' => $9,
|
||||
|
||||
'Tree' => $tree,
|
||||
'Queue' => $queue_name,
|
||||
);
|
||||
|
||||
my $month = MailProcess::monthstr2mon($tinderbox{'Month'});
|
||||
|
||||
my ($timenow) = timelocal
|
||||
(
|
||||
$tinderbox{'Second'},
|
||||
$tinderbox{'Minute'},
|
||||
$tinderbox{'Hour'},
|
||||
$tinderbox{'Month_Day'},
|
||||
$month,
|
||||
$year,
|
||||
);
|
||||
|
||||
$tinderbox{'Timenow'} = $timenow;
|
||||
|
||||
# we wish for all actions to be listed in our progress table
|
||||
# so they can not encode user names.
|
||||
# Examples of actions as parsed above:
|
||||
# given to rich
|
||||
# user set to jim@reefedge.com
|
||||
|
||||
$tinderbox{'Action'} =~ s/ to .*$//;
|
||||
$tinderbox{'Action'} =~ s/ via mail//;
|
||||
|
||||
# skip records which are already in the database.
|
||||
|
||||
($timenow >= $last_tree_data) ||
|
||||
next;
|
||||
|
||||
# remove special characters and convert any spaces to '_'
|
||||
|
||||
foreach $key (keys %tinderbox) {
|
||||
$value = $tinderbox{$key};
|
||||
($key, $value) = clean_bug_input($key, $value);
|
||||
$tinderbox{$key} = $value;
|
||||
}
|
||||
|
||||
$tinderbox{'tinderbox_timenow'} = $timenow;
|
||||
$tinderbox{'tinderbox_status'} = $tinderbox{'Action'};
|
||||
$tinderbox{'tinderbox_bug_id'} = $tinderbox{'Ticket_Num'};
|
||||
|
||||
$DATABASE
|
||||
{$tree}
|
||||
{$timenow}
|
||||
{$tinderbox{'Action'}}
|
||||
{$tinderbox{'Ticket_Num'}} = \%tinderbox;
|
||||
|
||||
$added_lines++;
|
||||
|
||||
} # if matches regexp
|
||||
|
||||
} # foreach $line
|
||||
|
||||
close(REQ_LOG) ||
|
||||
die("Could not close req logfile: $req_log\n");
|
||||
|
||||
($added_lines) ||
|
||||
return 0;
|
||||
|
||||
$METADATA{$tree}{'updates_since_trim'}+= $added_lines;
|
||||
|
||||
if ( ($METADATA{$tree}{'updates_since_trim'} >
|
||||
$TinderDB::MAX_UPDATES_SINCE_TRIM)
|
||||
) {
|
||||
$METADATA{$tree}{'updates_since_trim'}=0;
|
||||
trim_db_history(@_);
|
||||
}
|
||||
|
||||
$self->savetree_db($tree);
|
||||
|
||||
return $added_lines;
|
||||
}
|
||||
|
||||
|
||||
sub status_table_legend {
|
||||
my ($out)='';
|
||||
|
||||
# I am not sure the best way to explain this to our users
|
||||
|
||||
return ($out);
|
||||
}
|
||||
|
||||
|
||||
sub status_table_header {
|
||||
my $out = '';
|
||||
|
||||
my (@progress_states) = ReqData::get_all_progress_states();
|
||||
|
||||
foreach $progress (@progress_states) {
|
||||
$out .= "\t<th>$REQ_NAME $progress</th>\n";
|
||||
}
|
||||
|
||||
return ($out);
|
||||
}
|
||||
|
||||
|
||||
|
||||
# clear data structures in preparation for printing a new table
|
||||
|
||||
sub status_table_start {
|
||||
my ($self, $row_times, $tree, ) = @_;
|
||||
|
||||
# create an ordered list of all times which any data is stored
|
||||
|
||||
# sort numerically descending
|
||||
@DB_TIMES = sort {$b <=> $a} keys %{ $DATABASE{$tree} };
|
||||
|
||||
# adjust the $NEXT_DB to skip data which came after the first cell
|
||||
# at the top of the page. We make the first cell bigger then the
|
||||
# rest to allow for some overlap between pages.
|
||||
|
||||
my ($first_cell_seconds) = 2*($row_times->[0] - $row_times->[1]);
|
||||
my ($earliest_data) = $row_times->[0] + $first_cell_seconds;
|
||||
|
||||
$NEXT_DB = 0;
|
||||
while ( ($DB_TIMES[$NEXT_DB] > $earliest_data) &&
|
||||
($NEXT_DB < $#DB_TIMES) ) {
|
||||
$NEXT_DB++
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
sub status_table_row {
|
||||
my ($self, $row_times, $row_index, $tree, ) = @_;
|
||||
|
||||
my (@outrow) = ();
|
||||
|
||||
# find all the bug_ids which changed at any point in this cell.
|
||||
|
||||
my (%bug_ids) = ();
|
||||
|
||||
while (1) {
|
||||
my ($time) = $DB_TIMES[$NEXT_DB];
|
||||
|
||||
# find the DB entries which are needed for this cell
|
||||
($time < $row_times->[$row_index]) && last;
|
||||
|
||||
$NEXT_DB++;
|
||||
|
||||
foreach $status (keys %{ $DATABASE{$tree}{$time} }) {
|
||||
|
||||
# do not display bugs whos status_progres is null, these have
|
||||
# been deemed uninteresting.
|
||||
|
||||
($ReqData::STATUS_PROGRESS{$status}) ||
|
||||
next;
|
||||
|
||||
my ($query_links) = '';
|
||||
foreach $bug_id (sort keys %{ $DATABASE{$tree}{$time}{$status} }) {
|
||||
|
||||
my ($table) = '';
|
||||
my ($num_rows) = 0;
|
||||
my ($max_length) = 0;
|
||||
my ($rec) = $DATABASE{$tree}{$time}{$status}{$bug_id};
|
||||
|
||||
# display all the interesting fields
|
||||
|
||||
foreach $field (@ReqData::DISPLAY_FIELDS) {
|
||||
|
||||
my ($value) = $rec->{$field};
|
||||
|
||||
# many fields tend to be empty because it diffs the bug
|
||||
# reports and only reports the lines which change and a few
|
||||
# lines of context.
|
||||
|
||||
($value) ||
|
||||
next;
|
||||
|
||||
# $max_length = main::max($max_length , length($value));
|
||||
$num_rows++;
|
||||
$table .= (
|
||||
"\t".
|
||||
"<tt>$field</tt>".
|
||||
": ".
|
||||
$value.
|
||||
"<br>\n".
|
||||
"");
|
||||
} # foreach $field
|
||||
|
||||
($table) ||
|
||||
next;
|
||||
|
||||
$table = (
|
||||
"Ticket updated at: ".
|
||||
localtime($time).
|
||||
"<br>\n".
|
||||
$table.
|
||||
"");
|
||||
|
||||
# fix the size so that long summaries do not cause our window
|
||||
# to get too large.
|
||||
|
||||
$max_length = 40;
|
||||
|
||||
# a link to the cgibin page which displays the bug
|
||||
|
||||
my ($href) = ReqData::bug_id2bug_url($rec);
|
||||
my ($window_title) = "$REQ_NAME Info bug_id: $bug_id";
|
||||
|
||||
# we display the list of names in 'teletype font' so that the
|
||||
# names do not bunch together. It seems to make a difference if
|
||||
# there is a <cr> between each link or not, but it does make a
|
||||
# difference if we close the <tt> for each author or only for
|
||||
# the group of links.
|
||||
my ($query_link) =
|
||||
HTMLPopUp::Link(
|
||||
"linktxt" => "<tt>$bug_id</tt>",
|
||||
"href" => $href,
|
||||
|
||||
"windowtxt" => $table,
|
||||
"windowtitle" => $window_title,
|
||||
"windowheight" => ($num_rows * 25) + 100,
|
||||
"windowwidth" => ($max_length * 15) + 100,
|
||||
);
|
||||
|
||||
# put each link on its own line and add good comments so we
|
||||
# can debug the HTML.
|
||||
|
||||
$query_link = "\t\t".$query_link."\n";
|
||||
|
||||
$query_links .= (
|
||||
"\t\t<!-- Req: ".("bug_id: $bug_id, ".
|
||||
"Time: '".localtime($time)."', ".
|
||||
"Progress: $progress, ".
|
||||
"Status: $status, ".
|
||||
"Tree: $tree, ".
|
||||
"").
|
||||
" -->\n".
|
||||
"");
|
||||
|
||||
$query_links .= $query_link;
|
||||
} # foreach $bug_id
|
||||
|
||||
my ($progress) = $ReqData::STATUS_PROGRESS{$status};
|
||||
$bug_ids{$progress} .= $query_links;
|
||||
} # foreach $status
|
||||
} # while (1)
|
||||
|
||||
|
||||
my (@progress_states) = ReqData::get_all_progress_states();
|
||||
|
||||
foreach $progress (@progress_states) {
|
||||
|
||||
if ($bug_ids{$progress}) {
|
||||
push @outrow, (
|
||||
"\t<td align=center>\n".
|
||||
$bug_ids{$progress}.
|
||||
"\t</td>\n".
|
||||
"");
|
||||
} else {
|
||||
|
||||
push @outrow, ("\t<!-- skipping: Req: Progress: $progress tree: $tree -->".
|
||||
"<td align=center>$HTMLPopUp::EMPTY_TABLE_CELL</td>\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return @outrow;
|
||||
}
|
||||
|
||||
1;
|
Загрузка…
Ссылка в новой задаче