source: trunk/lib/first_page.cc @ 1513

Last change on this file since 1513 was 1513, checked in by Peter Johansson, 9 years ago

remove trailing whitespace

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