1/*
2 *	aegis - project change supervisor
3 *	Copyright (C) 1997, 1998, 2002, 2003, 2005-2008 Peter Miller
4 *
5 *	This program is free software; you can redistribute it and/or modify
6 *	it under the terms of the GNU General Public License as published by
7 *	the Free Software Foundation; either version 3 of the License, or
8 *	(at your option) any later version.
9 *
10 *	This program is distributed in the hope that it will be useful,
11 *	but WITHOUT ANY WARRANTY; without even the implied warranty of
12 *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 *	GNU General Public License for more details.
14 *
15 *	You should have received a copy of the GNU General Public License
16 *	along with this program. If not, see
17 *	<http://www.gnu.org/licenses/>.
18 */
19
20auto script_name;
21script_name = getenv("SCRIPT_NAME");
22if (script_name == "")
23	script_name = "http://localhost/cgi-bin/aegis.cgi";
24auto pn;
25pn = project_name();
26
27columns({width = 1000; });
28print("Content-Type: text/html");
29print("");
30print("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\"");
31print("                      \"http://www.w3.org/TR/REC-html40/loose.dtd\">");
32
33print("<html><head>");
34print("<meta name=\"ROBOTS\" content=\"NOINDEX, NOFOLLOW\">");
35print("<meta name=\"GENERATOR\" content=\"" ## script_name ## "\">");
36print("<meta http-equiv=\"Content-Type\" "
37	## "content=\"text/html; charset=ISO-8859-1\">");
38print("<style type=\"text/css\"> "
39	## "tr.even-group { background-color: #CCCCCC; } "
40	## "body { background-color: white; } "
41	## "</style>");
42/*
43 * Netscape 4.x has numerous CSS bugs, two of which need mentioning.
44 * 1. If a style sheet is not present Netscape says 404 Not found, when
45 * it should silently ignore it.  2. Style sheets who's media is not
46 * "screen" will be ignored.  Fortunately we can use (2) to get around (1).
47 */
48print("<link rel=\"stylesheet\" type=\"text/css\" href=\"/aedefault.css\" "
49	## "media=\"all\">");
50auto stack, depth, n;
51depth=0;
52stack[depth] = project[pn].state.name;
53while ("" != ( n = project[stack[depth]].state.parent_name )) {
54  stack[++depth] = n;
55}
56while ( depth >= 0) {
57    print("<link rel=\"stylesheet\" type=\"text/css\" href=\"/" ##
58      stack[depth--] ## ".css\" " ## "media=\"all\">");
59}
60print("<title>");
61
62print("Project " ## quote_html(pn) ## ",");
63print("File History Report");
64print("</title></head><body><h1 align=center>");
65
66auto href;
67print("<a href=\"" ## script_name ## "\">Project</a>");
68auto long_project_name;
69auto prj_name_parts;
70prj_name_parts = split(pn, '.');
71href = script_name ## "?file@proj_menu+project@"
72	## quote_url(prj_name_parts[0]);
73long_project_name = "<a href=\"" ## href ## "\" >"
74	## quote_html(prj_name_parts[0]) ## "</a>";
75auto j;
76for (j = 1; j < count(prj_name_parts); j++)
77{
78    href ##= '.' ## prj_name_parts[j];
79    long_project_name ##= ".<a href=\"" ## href ## "\" >"
80    	## quote_html(prj_name_parts[j]) ## "</a>";
81};
82long_project_name = "&ldquo;" ## long_project_name ## "&rdquo;,<br>";
83/* HTTP limits lines to 510 characters */
84for (j in wrap(long_project_name, 510))
85    print(j);
86
87if (change_number_set())
88{
89    href = script_name ## "?file@chan_menu+project@" ## quote_url(pn)
90	## "+change@" ## change_number();
91    print("Change <a href=\"" ## href ## "\">" ## change_number() ##
92	"</a>,<br>");
93}
94if (count(arg) == 1)
95    print("File &ldquo;" ## quote_html(arg[0]) ## "&rdquo;,<br>");
96print("File History");
97print("</h1>");
98print("<div class=\"information\">");
99
100print("<table align=center>");
101
102auto ps;
103ps = project[project_name()].state;
104
105/*
106 * use the files named on the command line,
107 * or all project files if not specified
108 */
109auto file, cs;
110if (count(arg) == 0)
111{
112    if (change_number_set())
113    {
114	cs = ps.branch.change[change_number()];
115	for (file in cs.src)
116	    arg ##= file.file_name;
117    }
118    else
119    {
120	for (file in ps.src)
121	    arg ##= file.file_name;
122    }
123}
124
125/*
126 * create an empty history for each file
127 */
128auto hist;
129for (file in arg)
130    hist[file] = [];
131auto metname, m;
132metname = { };
133
134/*
135 * scan all completed changes
136 * for any of the named files
137 */
138auto ph, cf;
139for (ph in ps.branch.history)
140{
141    cs = ps.branch.change[ph.change_number];
142    for (cf in cs.src)
143    {
144	if (cf.file_name in arg)
145	{
146	    if (cf.usage == build && cf.action == modify)
147		continue;
148	    hist[cf.file_name] ##=
149		{
150		    usage = cf.usage;
151		    action = cf.action;
152		    edit = cf.edit.revision;
153		    delta = ph.delta_number;
154		    when = cs.history[count(cs.history) - 1].when;
155		    change = ph.change_number;
156		    description = cs.brief_description;
157		    move = cf.move;
158		    metrics = cf.metrics;
159		};
160	    if (count(cf.metrics))
161	    {
162		for (m in cf.metrics)
163		    metname[m.name] = true;
164	    }
165	}
166    }
167}
168
169/*
170 * print the accumulated history
171 */
172auto fh, actions, usages, rownum;
173for (file in sort(keys(hist)))
174{
175    href = script_name ## "?file@file_menu+" ## quote_url(file);
176    href ##= "+project@" ## quote_url(project_name());
177
178    print("<tr><td colspan=8><br><p>");
179    print("<a href=\"" ## href ## "\">");
180    print("<span class=\"filename\">" ## quote_html(file) ## "</span></a>");
181    print("</td></tr>");
182
183    print("<tr class=\"even-group\">");
184    print("<th></th><th>Type</th><th>Action</th><th>Delta</th>");
185    print("<th>When</th>");
186    print("<th>Change</th><th>Edit</th><th>Description</th>");
187    for (m in sort(keys(metname)))
188    {
189        print("<th>");
190	auto msplit, ms2;
191	msplit = split(m, "_");
192	for (ms2 in msplit)
193	    print(capitalize(ms2) ## "<br>");
194	print("</th>");
195    }
196    print("</tr>");
197    rownum = 0;
198
199    actions = "BS";
200    usages = "BS";
201    for (fh in hist[file])
202    {
203	if (rownum % 6 < 3)
204	    print("<tr class=\"odd-group\">");
205	else
206	    print("<tr class=\"even-group\">");
207	++rownum;
208	print("<td>&nbsp;&nbsp;</td><td valign=top>");
209	if (fh.usage != usages)
210	    print(fh.usage);
211	print("</td><td valign=top>");
212	if (fh.action != actions)
213	    print(fh.action);
214	print("</td><td valign=top align=right>");
215	print(fh.delta);
216	print("</td><td valign=top>");
217	print(fh.when);
218	print("</td><td valign=top align=right>");
219	href = script_name ## "?file@chan_menu";
220	href ##= "+project@" ## quote_url(project_name());
221	href ##= "+change@" ## fh.change;
222	print("<a href=\"" ## href ## "\">");
223	print(fh.change ## "</a>");
224	print("</td><td valign=top align=right>");
225	href = script_name ## "?file@file_menu";
226	href ##= "+project@" ## quote_url(project_name());
227	href ##= "+change@" ## fh.change ## "+" ## quote_html(file);
228	print("<a href=\"" ## href ## "\">");
229	print(fh.edit ## "</a>");
230	print("</td><td valign=top>");
231	auto part;
232	for (part in wrap_html(quote_html(fh.description), 80))
233	    print(part);
234	if (fh.move != "")
235	{
236	    href = script_name ## "?file@file_menu+" ## quote_url(fh.move);
237	    href ##= "+project@" ## quote_url(project_name());
238
239	    print("<br>Moved");
240	    if (fh.action == create)
241		print("from");
242	    else
243		print("to");
244	    print("<a href=\"" ## href ## "\">");
245	    print("<span class=\"filename\">" ## quote_html(fh.move)
246		## "</span></a>");
247	}
248	print("</td>");
249
250	auto met;
251	for (m in sort(keys(metname)))
252	{
253	    for (met = 0; met < count(fh.metrics); met++)
254	    {
255		if (fh.metrics[met].name == m)
256		{
257		    print("<td valign=top align=right>");
258		    print(sprintf("%4.2f", fh.metrics[met].value));
259		    print("</td>");
260		}
261	    }
262	}
263	print("</tr>");
264	actions = fh.action;
265	usages = fh.usage;
266    }
267}
268print("<tr><td colspan=8><br><p>");
269print("Listed " ## count(keys(hist)) ## " files.");
270print("</td></tr>");
271print("</table>");
272print("</div>");
273
274print("<hr>");
275print("<div class=\"report-cmd\">");
276print("A similar report may be obtained from the command line, with");
277print("<blockquote><samp>aer file_history [ <i>filename</i> ] -p " ##
278    quote_html(project_name()) ## "</samp></blockquote>");
279print("</div>");
280
281print("<hr>");
282print("<p align=center class=\"navbar\">[");
283print("<a href=\"" ## script_name ## "\">Project List</a> |");
284href = script_name ## "?file@proj_menu+project@" ## quote_url(pn);
285print("<a href=\"" ## href ## "\">Project Menu</a> |");
286href = script_name ## "?file@changes+project@" ## quote_url(pn);
287print("<a href=\"" ## href ## "\">Change List</a>");
288if (change_number_set())
289{
290    href = script_name ## "?file@chan_menu+project@" ## quote_url(pn) ##
291	"+change@" ## change_number();
292    print("| <a href=\"" ## href ## "\">Change Menu</a>");
293}
294print("]</p>");
295
296print("<hr>");
297print("This page was generated " ## now() ## ".");
298print("</body></html>");
299