lib/first_page.cc

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