source: trunk/lib/first_page.cc @ 687

Last change on this file since 687 was 687, checked in by Peter Johansson, 13 years ago

Merged patch release 0.6.6 to trunk. Delta 0.6.6 - 0.6.5

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 7.1 KB
RevLine 
[177]1// $Id: first_page.cc 687 2008-08-04 19:37:10Z peter $
2
3/*
[408]4  Copyright (C) 2006 Peter Johansson
5  Copyright (C) 2007 Jari Häkkinen, Peter Johansson
[177]6
[687]7  This file is part of svndigest, http://dev.thep.lu.se/svndigest
[177]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 2 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 this program; if not, write to the Free Software
21  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
22  02111-1307, USA.
23*/
24
[285]25#include "first_page.h"
26
[256]27#include "Commitment.h"
[274]28#include "Configuration.h"
[235]29#include "Date.h"
[234]30#include "HtmlStream.h"
[400]31#include "html_utility.h"
[223]32#include "Stats.h"
[234]33#include "SVNlog.h"
[286]34#include "Trac.h"
[177]35#include "utility.h"
[200]36#include <config.h> // this header file is created by configure
[177]37
[234]38#include <algorithm>
[263]39#include <cassert>
[177]40#include <fstream>
[200]41#include <iostream>
[177]42#include <sstream>
43#include <stdexcept>
44#include <string>
45#include <sys/param.h>
46#include <unistd.h>
[201]47#include <vector>
[177]48
49namespace theplu{
50namespace svndigest{
51
[234]52  void print_main_page(const std::string& dir, const SVNlog& log,
[556]53                       const StatsCollection& stats, std::string url)
[201]54  {
[207]55    std::string filename="index.html";
[201]56    std::ofstream os(filename.c_str());
[546]57    print_header(os, dir, 0, "all", "main", "index.html", "none");
[234]58
59    using namespace std;
[256]60    set<string> authors;
[642]61    std::transform(log.commits().begin(), log.commits().end(),
[647]62                   std::inserter(authors, authors.begin()), 
63                   std::mem_fun_ref(&Commitment::author));
[234]64    // erase invalid authors
[256]65    authors.erase("");
66    authors.erase("no author");
[234]67
[256]68    vector<Commitment> latest_commit;
69    latest_commit.reserve(authors.size());
70    for (set<string>::const_iterator i(authors.begin()); i!=authors.end(); ++i)
71      latest_commit.push_back(log.latest_commit(*i));
[234]72
[556]73    print_summary_plot(os, stats["classic"]);
[312]74    print_general_information(os, log, authors.size(), url);
[256]75    sort(latest_commit.begin(), latest_commit.end(), GreaterRevision());
[556]76    print_authors(os, latest_commit, stats["classic"]);
77    print_recent_logs(os, log, stats);
[234]78    os << "<hr width=100% />";
79    print_footer(os);
80    os.close();
81  }
82
83  void print_general_information(std::ostream& os, const SVNlog& log, 
[312]84                                 size_t nof_authors, std::string url)
[234]85  { 
[642]86    assert(log.commits().size());
87    Date begin(log.commits()[0].date());
88    Date end(log.commits().back().date());
[363]89    std::string timefmt("%a, %e %b %Y  %H:%M:%S");
[223]90
[234]91    os << "<div class=\"main\">" 
[223]92       << "<table class=\"main\"><thead><tr><th colspan=\"2\">" 
93       << "General Information"
[234]94       << "</th></tr></thead>\n"
[378]95       << "<tbody>\n"
[312]96       << "<tr><td>URL:</td><td>" 
97       << url << "</td></tr>\n"
[363]98       << "<tr><td>First Revision Date:</td><td>" 
[235]99       << begin(timefmt) << "</td></tr>\n"
[363]100       << "<tr><td>Latest Revision Date:</td><td>" 
[235]101       << end(timefmt) << "</td></tr>\n"
[363]102       << "<tr><td>Age:</td><td>"; 
103    os << end.difftime(begin);
[223]104    os << "</td></tr>\n"
[642]105       << "<tr><td>Smallest Revision:</td><td>" << log.commits()[0].revision() 
[363]106       << "</td></tr>\n"
[642]107       << "<tr><td>Largest Revision:</td><td>" <<log.commits().back().revision() 
[363]108       << "</td></tr>\n"
[642]109       << "<tr><td>Revision Count:</td><td>" << log.commits().size() 
[363]110       << "</td></tr>\n"
[234]111       << "<tr><td>Number of Authors:</td><td>" << nof_authors
[223]112       << "</td></tr>\n"
[378]113       << "</tbody>\n"
[201]114       << "</table></div>\n";
115  }
116
117
[234]118  void print_authors(std::ostream& os, 
[256]119                     const std::vector<Commitment>& lc,
120                     const Stats& stats)
[234]121  {
122    os << "<div class=\"main\">"
123       << "<table class=\"main\"><thead><tr><th colspan=\"2\">" 
124       << "Authors"
125       << "</th></tr></thead>\n";
126
127    os << "<tr><td>Author</td>" 
128       << "<td>Number of Lines</td>"
129       << "<td>Code Lines</td>"
130       << "<td>Comment Lines</td>"
131       << "<td>Latest Commitment</td>"
132       <<"</tr>";
133
[556]134    std::string timefmt("%Y %b %d %H:%M:%S");
[234]135    using namespace std;
[256]136    for (vector<Commitment>::const_iterator i=lc.begin(); i!=lc.end(); ++i) {
[310]137      os << "<tr><td>"; 
[311]138      if (!stats.lines(i->author()))
[310]139        os << i->author();
140      else
[497]141        os << anchor(std::string("classic/"+i->author()+"/total/index.html"),
142                     i->author());
[310]143      os << "</td><td>" << stats.lines(i->author()) << " (" 
[492]144         << 100*stats.lines(i->author())/(stats.lines()?stats.lines():1)
145         << "%)</td><td>" << stats.code(i->author()) << " (" 
146         << 100*stats.code(i->author())/(stats.code()?stats.code():1)
147         << "%)</td><td>" << stats.comments(i->author()) << " (" 
148         << 100*stats.comments(i->author())/(stats.comments()?stats.comments():1)
149         << "%)</td><td>" << Date(i->date())(timefmt) << "</td>" <<"</tr>";
[234]150    }
[362]151    os << "<tr><td>Total</td>";
152    os << "<td>" << stats.lines() << "</td>"
153       << "<td>" << stats.code() << "</td>"
154       << "<td>" << stats.comments() << "</td>"
155       <<"</tr>";
[234]156
157    os << "</table></div>\n";
158  }
159
160
[556]161  void print_recent_logs(std::ostream& os, const SVNlog& log,
162                         const StatsCollection& stats)
[234]163  {
164    os << "<div class=\"main\">\n"
165       << "<table class=\"main\"><thead><tr><th colspan=\"2\">" 
166       << "Recent Log"
167       << "</th></tr></thead>\n";
168
[556]169    os << "<tr><td>Author</td><td>Date</td><td>Rev</td><td>Added</td>"
170       << "<td>Removed</td><td>Message</td></tr>\n";
[234]171    HtmlStream hs(os);
[556]172    std::string timefmt("%Y %b %d %H:%M:%S");
[235]173    const size_t maxlength = 80;
[289]174    const Configuration& conf = Configuration::instance();
[642]175    typedef std::vector<Commitment>::const_reverse_iterator iter;
176    for (iter i=log.commits().rbegin(); 
[651]177         i < std::min(log.commits().rbegin()+10,log.commits().rend()); ++i) {
[497]178      os << "<tr><td>" 
[642]179         << anchor(std::string("classic/")+i->author()+"/total/index.html",
180                   i->author()) 
[497]181         << "</td>";
[642]182      Date date(i->date());
[235]183      os << "<td>" << date(timefmt) << "</td>";
[274]184      os << "<td>"; 
[642]185      os << trac_revision(i->revision());
[274]186      os << "</td>";
[234]187      os << "<td>";
[642]188      int added = stats["add"](LineTypeParser::total, "all", i->revision()) -
189        stats["add"](LineTypeParser::total, "all", i->revision() - 1); 
[556]190      os << added;
191      os << "</td>";
192      os << "<td>";
[642]193      os << added-(stats["blame"](LineTypeParser::total, "all", i->revision()) -
194                   stats["blame"](LineTypeParser::total,"all",i->revision()-1)); 
[556]195      os << "</td>";
196      os << "<td>";
[642]197      std::string mess = i->message();
[235]198      // replace newlines with space
199      std::replace(mess.begin(), mess.end(), '\n', ' ');
200      mess = htrim(mess);
[274]201
[317]202      if (conf.trac_root().empty()) {
203        // truncate message if too long
204        if (mess.size()>maxlength)
205          mess = mess.substr(0,maxlength-3) + "...";
[274]206        hs << mess;
[317]207      }
[286]208      else {// make anchors to trac
209        Trac trac(hs);
[317]210        trac.print(mess, maxlength);
[274]211      }
212
[400]213      os << "</td></tr>\n";
[234]214    }
215    os << "</table></div>\n";
216  }
217
[274]218
[345]219  void print_summary_plot(std::ostream& os, const Stats& stats)
220  {
221    std::string name("summary_plot.png");
222    stats.plot_summary(name);
223    os << "<div class=\"main\">\n";
[400]224    os << "<img src='" << name << "' alt='[plot]'/>"; 
[345]225    os << "</div>";
226  }
227
[177]228}} // end of namespace svndigest and namespace theplu
Note: See TracBrowser for help on using the repository browser.