/*
* aegis - project change supervisor
* Copyright (C) 1998, 2000-2003, 2005-2008 Peter Miller
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see
* .
*/
auto script_name;
script_name = getenv("SCRIPT_NAME");
if (script_name == "")
script_name = "http://localhost/cgi-bin/aegis.cgi";
auto pn, p;
pn = project_name();
p = project[pn];
auto legend_used;
legend_used = { };
columns({width = 1000; });
print("Content-Type: text/html");
print("");
print("");
print("
");
print("");
print("");
print("");
print("");
/*
* Netscape 4.x has numerous CSS bugs, two of which need mentioning.
* 1. If a style sheet is not present Netscape says 404 Not found, when
* it should silently ignore it. 2. Style sheets who's media is not
* "screen" will be ignored. Fortunately we can use (2) to get around (1).
*/
print("");
auto stack, depth, n;
depth=0;
stack[depth] = project[pn].state.name;
while ("" != ( n = project[stack[depth]].state.parent_name )) {
stack[++depth] = n;
}
while ( depth >= 0) {
print("");
}
print("");
auto cause_map;
cause_map =
{
chain = "255+0+0";
internal_bug = "255+255+0";
external_bug = "192+192+0";
internal_enhancement = "0+255+0";
external_enhancement = "0+192+0";
internal_improvement = "0+255+255";
external_improvement = "0+192+192";
};
auto size_map;
size_map =
{
create = 12;
modify = 16;
remove = 8;
};
/*
* use the file prefix named on the command line
* or the top level if not specified
*/
auto prefix;
if (count(arg) == 0)
prefix = "";
else
prefix = arg[0] ## "/";
print("Project " ## quote_html(pn) ## " Change Density by File" ##
(prefix == "" ? "" : (", Directory " ## quote_html(prefix))));
print("
");
auto href;
print("Project");
auto long_project_name;
auto prj_name_parts;
prj_name_parts = split(pn, '.');
href = script_name ## "?file@proj_menu+project@"
## quote_url(prj_name_parts[0]);
long_project_name = ""
## quote_html(prj_name_parts[0]) ## "";
auto j;
for (j=1; j"
## quote_html(prj_name_parts[j]) ## "";
};
long_project_name = "“" ## long_project_name ## "”, ";
/* HTTP limits lines to 510 characters */
for (j in wrap(long_project_name, 510))
print(j);
auto long_dir_name, dir_parts;
if (prefix != "")
{
href = script_name ## "?file@file_densi+project@" ## quote_url(pn);
print("Change Density by File ");
long_dir_name = "Directory “";
href ##= "+";
dir_parts = split(prefix, '/');
for (j = 0; j < count(dir_parts) - 1; j++)
{
href ##= dir_parts[j];
long_dir_name ##=
"" ##
quote_html(dir_parts[j]) ## "/";
href ##= "/";
};
long_dir_name ##= quote_html(dir_parts[count(dir_parts) - 1]) ## "”";
/* HTTP limits lines to 510 characters */
for (j in wrap(long_dir_name, 510))
print(j);
}
else
print("Change Density by File");
print("
");
print("
");
auto ps;
ps = project[project_name()].state;
/*
* This will hold the cumulative statistics
* history[filename].is_a_directory
* history[filename].count[cause][action]
*/
auto remember;
remember = {};
/*
* scan the project files for context
*/
auto ph, cs, cf, max, filename, is_a_directory;
for (cf in ps.src)
{
if (cf.usage == build)
continue;
filename = cf.file_name;
if (prefix != "")
{
if (substr(filename, 0, length(prefix)) != prefix)
continue;
filename = substr(filename, length(prefix), 99999);
}
filename = split(filename, "/");
is_a_directory = (count(filename) > 1);
filename = filename[0];
if (typeof(remember[filename]) == "nul")
remember[filename] = { count = {}; total = 0; };
if (is_a_directory)
remember[filename].is_a_directory = true;
}
/*
* scan all completed changes
* for any of the named files
*/
max = 1;
for (ph in ps.branch.history)
{
cs = ps.branch.change[ph.change_number];
for (cf in cs.src)
{
if (cf.usage == build && cf.action == modify)
continue;
filename = cf.file_name;
if (prefix != "")
{
if (substr(filename, 0, length(prefix)) != prefix)
continue;
filename = substr(filename, length(prefix), 99999);
}
filename = split(filename, "/");
is_a_directory = (count(filename) > 1);
filename = filename[0];
if (typeof(remember[filename]) == "nul")
remember[filename] = { count = {}; total = 0; };
if (is_a_directory)
remember[filename].is_a_directory = true;
if (typeof(remember[filename].count[cs.cause]) == "nul")
remember[filename].count[cs.cause] = { total = 0; };
remember[filename].count[cs.cause].total++;
remember[filename].count[cs.cause][cf.action]++;
remember[filename].total++;
if (remember[filename].total > max)
max = remember[filename].total;
legend_used[cs.cause] = true;
}
}
/*
* print the accumulated history
*/
max = 300.0 / max;
auto cause, action;
auto width, height, clr;
print("