source: trunk/lib/first_page.cc @ 978

Last change on this file since 978 was 978, checked in by Peter Johansson, 12 years ago

refs #429. Convert copyright statements to UTF-8

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 7.3 KB
Line 
1// $Id: first_page.cc 978 2009-12-12 20:09:41Z peter $
2
3/*
4  Copyright (C) 2006 Peter Johansson
5  Copyright (C) 2007, 2008, 2009 Jari Häkkinen, Peter Johansson
6
7  This file is part of svndigest, http://dev.thep.lu.se/svndigest
8
9  svndigest is free software; you can redistribute it and/or modify it
10  under the terms of the GNU General Public License as published by
11  the Free Software Foundation; either version 3 of the License, or
12  (at your option) any later version.
13
14  svndigest is distributed in the hope that it will be useful, but
15  WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  General Public License for more details.
18
19  You should have received a copy of the GNU General Public License
20  along with svndigest. If not, see <http://www.gnu.org/licenses/>.
21*/
22
23#include "first_page.h"
24
25#include "Commitment.h"
26#include "Configuration.h"
27#include "Date.h"
28#include "HtmlStream.h"
29#include "html_utility.h"
30#include "Stats.h"
31#include "SVNlog.h"
32#include "Trac.h"
33#include "utility.h"
34#include <config.h> // this header file is created by configure
35
36#include <algorithm>
37#include <cassert>
38#include <fstream>
39#include <iostream>
40#include <sstream>
41#include <stdexcept>
42#include <string>
43#include <sys/param.h>
44#include <unistd.h>
45#include <vector>
46
47namespace theplu{
48namespace svndigest{
49
50  void print_main_page(const std::string& dir, const SVNlog& log,
51                       const StatsCollection& stats, std::string url)
52  {
53    std::string filename="index.html";
54    std::ofstream os(filename.c_str());
55    print_header(os, dir, 0, "all", "main", "index.html", "none");
56
57    using namespace std;
58    set<string> authors;
59    std::transform(log.commits().begin(), log.commits().end(),
60                   std::inserter(authors, authors.begin()), 
61                   std::mem_fun_ref(&Commitment::author));
62    // erase invalid authors
63    authors.erase("");
64    authors.erase("no author");
65
66    vector<Commitment> latest_commit;
67    latest_commit.reserve(authors.size());
68    for (set<string>::const_iterator i(authors.begin()); i!=authors.end(); ++i)
69      latest_commit.push_back(log.latest_commit(*i));
70
71    print_summary_plot(os, stats["classic"]);
72    print_general_information(os, log, authors.size(), url);
73    sort(latest_commit.begin(), latest_commit.end(), GreaterRevision());
74    print_authors(os, latest_commit, stats["classic"]);
75    print_recent_logs(os, log, stats);
76    os << "<hr width=100% />";
77    print_footer(os);
78    os.close();
79  }
80
81  void print_general_information(std::ostream& os, const SVNlog& log, 
82                                 size_t nof_authors, std::string url)
83  { 
84    assert(log.commits().size());
85    Date begin(log.commits().begin()->date());   
86    Date end(log.latest_commit().date());
87    std::string timefmt("%a %b %e %H:%M:%S %Y");
88
89    os << "<div class=\"main\">" 
90       << "<table class=\"main\"><thead><tr><th colspan=\"2\">" 
91       << "General Information"
92       << "</th></tr></thead>\n"
93       << "<tbody>\n"
94       << "<tr><td>URL:</td><td>"; 
95    if (url.size()>=4 && url.substr(0,4)=="http")
96      os << anchor(url, url);
97    else
98      os << url;
99    os << "</td></tr>\n"
100       << "<tr><td>First Revision Date:</td><td>" 
101       << begin(timefmt) << "</td></tr>\n"
102       << "<tr><td>Latest Revision Date:</td><td>" 
103       << end(timefmt) << "</td></tr>\n"
104       << "<tr><td>Age:</td><td>"; 
105    os << end.difftime(begin);
106    os << "</td></tr>\n"
107       << "<tr><td>Smallest Revision:</td><td>" 
108       << log.commits().begin()->revision() 
109       << "</td></tr>\n"
110       << "<tr><td>Largest Revision:</td><td>" << log.latest_commit().revision() 
111       << "</td></tr>\n"
112       << "<tr><td>Revision Count:</td><td>" << log.commits().size() 
113       << "</td></tr>\n"
114       << "<tr><td>Number of Authors:</td><td>" << nof_authors
115       << "</td></tr>\n"
116       << "</tbody>\n"
117       << "</table></div>\n";
118  }
119
120
121  void print_authors(std::ostream& os, 
122                     const std::vector<Commitment>& lc,
123                     const Stats& stats)
124  {
125    HtmlStream hs(os);
126    os << "<div class=\"main\">"
127       << "<table class=\"main\"><thead><tr><th colspan=\"2\">" 
128       << "Authors"
129       << "</th></tr></thead>\n";
130
131    os << "<tr><td>Author</td>" 
132       << "<td>Number of Lines</td>"
133       << "<td>Code Lines</td>"
134       << "<td>Comment Lines</td>"
135       << "<td>Latest Commitment</td>"
136       <<"</tr>";
137
138    std::string timefmt("%Y-%m-%d  %H:%M");
139    using namespace std;
140    for (vector<Commitment>::const_iterator i=lc.begin(); i!=lc.end(); ++i) {
141      os << "<tr><td>"; 
142      if (!stats.lines(i->author()))
143        os << i->author();
144      else
145        os << anchor(std::string("classic/"+i->author()+"/total/index.html"),
146                     i->author());
147      os << "</td><td>" << stats.lines(i->author()) << " (" 
148         << 100*stats.lines(i->author())/(stats.lines()?stats.lines():1)
149         << "%)</td><td>" << stats.code(i->author()) << " (" 
150         << 100*stats.code(i->author())/(stats.code()?stats.code():1)
151         << "%)</td><td>" << stats.comments(i->author()) << " (" 
152         << 100*stats.comments(i->author())/(stats.comments()?stats.comments():1)
153         << "%)</td><td>";
154      hs << Date(i->date())(timefmt);
155      os << "</td>" <<"</tr>";
156    }
157    os << "<tr><td>Total</td>";
158    os << "<td>" << stats.lines() << "</td>"
159       << "<td>" << stats.code() << "</td>"
160       << "<td>" << stats.comments() << "</td>"
161       <<"</tr>";
162
163    os << "</table></div>\n";
164  }
165
166
167  void print_recent_logs(std::ostream& os, const SVNlog& log,
168                         const StatsCollection& stats)
169  {
170    os << "<div class=\"main\">\n"
171       << "<table class=\"main\"><thead><tr><th colspan=\"2\">" 
172       << "Recent Log"
173       << "</th></tr></thead>\n";
174
175    os << "<tr><td>Author</td><td>Date</td><td>Rev</td><td>Added</td>"
176       << "<td>Removed</td><td>Message</td></tr>\n";
177    HtmlStream hs(os);
178    std::string timefmt("%Y-%m-%d  %H:%M");
179    const size_t maxlength = 80;
180    const Configuration& conf = Configuration::instance();
181    typedef SVNlog::container::const_reverse_iterator iter;
182    size_t count = 0;
183    for (iter i=log.commits().rbegin(); 
184         i != log.commits().rend() && count<10; ++i) {
185      os << "<tr><td>" 
186         << anchor(std::string("classic/")+i->author()+"/total/index.html",
187                   i->author()) 
188         << "</td>";
189      Date date(i->date());
190      os << "<td>";
191      hs << date(timefmt); 
192      os << "</td>";
193      os << "<td>"; 
194      os << trac_revision(i->revision());
195      os << "</td>";
196      os << "<td>";
197      int added = stats["add"](LineTypeParser::total, "all", i->revision()) -
198        stats["add"](LineTypeParser::total, "all", i->revision() - 1); 
199      os << added;
200      os << "</td>";
201      os << "<td>";
202      os << added-(stats["blame"](LineTypeParser::total, "all", i->revision()) -
203                   stats["blame"](LineTypeParser::total,"all",i->revision()-1)); 
204      os << "</td>";
205      os << "<td>";
206      std::string mess = i->message();
207      // replace newlines with space
208      std::replace(mess.begin(), mess.end(), '\n', ' ');
209      mess = htrim(mess);
210
211      if (conf.trac_root().empty()) {
212        // truncate message if too long
213        if (mess.size()>maxlength)
214          mess = mess.substr(0,maxlength-3) + "...";
215        hs << mess;
216      }
217      else {// make anchors to trac
218        Trac trac(hs);
219        trac.print(mess, maxlength);
220      }
221
222      os << "</td></tr>\n";
223      ++count;
224    }
225    os << "</table></div>\n";
226  }
227
228
229  void print_summary_plot(std::ostream& os, const Stats& stats)
230  {
231    std::string name("summary_plot.svg");
232    stats.plot_summary(name);
233    os << "<div class=\"main\">\n";
234    os << "<object data='" << name << "' type='image/svg+xml' width='600'>\n"
235       << "<embed src='" << name << "' type='image/svg+xml' width='600' />\n"
236       << "</object>\n";
237    os << "</div>";
238
239
240  }
241
242}} // end of namespace svndigest and namespace theplu
Note: See TracBrowser for help on using the repository browser.