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 = "“" ## long_project_name ## "”,<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 “" ## quote_html(arg[0]) ## "”,<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> </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