Changeset 234


Ignore:
Timestamp:
Apr 9, 2007, 2:08:26 PM (16 years ago)
Author:
Peter Johansson
Message:

fixes #87 and #95 and #103 and #104 and #80 and #108, and refs #69

Location:
trunk
Files:
4 added
17 edited

Legend:

Unmodified
Added
Removed
  • trunk/bin/Parameter.cc

    r229 r234  
    2424
    2525#include "Parameter.h"
     26
     27#include "ColumnStream.h"
    2628#include "utility.h"
    2729#include <config.h> // this header file is created by configure
     
    4345      bool ok=false;
    4446      std::string myargv(argv[i]);
    45       if (myargv=="-c" || myargv=="--config"){
     47      if (myargv=="--config-file"){
    4648        if (++i<argc){
    4749          config_file_= std::string(argv[i]);
     
    136138
    137139    if (config_file_.empty())
    138       runtime_error(string("svndigest: Parameter --config requires argument."));
     140      runtime_error(string("svndigest: Parameter --config-file requires argument."));
    139141
    140142  }
     
    157159  {
    158160    defaults();
    159     std::cout << "\n"
    160               << "usage: svndigest [options]\n"
    161               << "\n"
    162               << "svndigest traverses a directory structure (controlled by\n"
    163               << "subversion) and calculates developer statistics entries.\n"
    164               << "The top level directory of the directory structure to\n"
    165               << "traverse is set with the -r option. The result is written to\n"
    166               << "the current working directory or a directory set with the\n"
    167               << "-t option.\n"
    168               << "\n"
    169               << "Valid options:\n"
    170               << "  --copyright    : update copyright statement\n"
    171               << "  -c [--config] arg : configuration file ["
    172               << config_file_ << "]\n"
    173               << "  -f [--force]   : remove target directory/file if it exists\n"
    174               << "                   [no force]. NOTE recursive delete.\n"
    175               << "  -g [--generate-config] : write configuration file "
    176               << "to standard output and exit\n"
    177               << "  -h [--help]    : display this help and exit\n"
    178               << "  -r [--root] arg : svn controlled directory to perform\n"
    179               << "                    statistics calculation on ["
    180               << root_ << "]\n"
    181               << "  -rev [--revisions]: Use revision numbers as time scale\n"
    182               << "                      instead of dates [dates].\n"
    183               << "  -t [--target] arg : output directory ["
    184               << targetdir_ << "]\n"
    185               << "  -v [--verbose] : explain what is being done\n"
    186               << "  --version      : print version information and exit\n"
    187               << std::endl;
     161
     162    ColumnStream cs(std::cout, 1);
     163    cs.width(0)=68;
     164    cs.margin(0)=2;
     165    ColumnStream cs2(std::cout, 3);
     166    cs2.width(0)=24;
     167    cs2.width(1)=2;
     168    cs2.width(2)=50;
     169    cs2.margin(0)=2;
     170
     171    std::cout << "usage: svndigest [options]\n"
     172              << "\n";
     173
     174    cs << "svndigest traverses a directory structure (controlled by "
     175       << "subversion) and calculates developer statistics entries. "
     176       << "The top level directory of the directory structure to "
     177       << "traverse is set with the -r option. The result is written to "
     178       << "the current working directory or a directory set with the "
     179       << "-t option.\n";
     180    std::cout << "\nValid options:\n";
     181
     182    cs2  << "--copyright\t:\tupdate copyright statement\n"
     183         << "--config-file arg\t:\tconfiguration file ["
     184         << config_file_ << "]\n"
     185         << "-f [--force]\t:\tremove target directory/file if it exists "
     186         << "[no force]. NOTE recursive delete.\n"
     187         << "-g [--generate-config]\t:\twrite configuration file "
     188         << "to standard output and exit\n"
     189         << "-h [--help]\t:\tdisplay this help and exit\n"
     190         << "-r [--root] arg\t:\tsvn controlled directory to perform "
     191         << "statistics calculation on [" << root_ << "]\n"
     192         << "-rev [--revisions]\t:\tUse revision numbers as time scale "
     193         << "instead of dates [dates].\n"
     194         << "-t [--target] arg\t:\toutput directory [" << targetdir_ << "]\n"
     195         << "-v [--verbose]\t:\texplain what is being done\n"
     196         << "--version\t:\tprint version information and exit\n";
     197    std::cout << std::endl;
    188198  }
    189199
  • trunk/bin/svndigest.cc

    r230 r234  
    3232#include "SVN.h"
    3333#include "SVNinfo.h"
     34#include "SVNlog.h"
    3435#include "utility.h"
    3536
     
    129130  stats+=tree.parse(option->verbose());
    130131
    131   // Retrieve commit dates.
    132   std::vector<std::string> commit_dates;
     132  // Retrieve commit dates etc from SVNlog.
    133133  try {
    134134    if (option->verbose())
    135135      std::cout << "Retrieving commit dates" << std::endl;
    136136    svn->setup_ra_session(repo);
    137     commit_dates=svn->commit_dates(repo);
    138137  }
    139138  catch (SVNException e) {
     
    141140    exit(-1);
    142141  }
    143   // Is this line needed?
    144   svn->setup_ra_session(repo);
    145   std::vector<std::string> authors=svn->authors(repo);
     142  SVNlog svnlog(repo);
    146143
    147144  // remove target if needed
     
    155152    std::cout << "Generating output" << std::endl;
    156153  if (!option->revisions())
    157     GnuplotFE::instance()->set_dates(commit_dates);
     154    GnuplotFE::instance()->set_dates(svnlog.date());
    158155  chdir(option->targetdir().c_str());
    159156  mkdir(tree.name());
     
    162159                                 +tree.name()+"'");
    163160  print_css("svndigest.css");
    164   print_main_page(tree.name(), commit_dates, stats);
     161  print_main_page(tree.name(), svnlog, stats);
    165162  mkdir("all");
    166163  for (std::set<std::string>::const_iterator i = stats.authors().begin();
     
    180177        std::cout << "Updating copyright statements" << std::endl;
    181178      std::map<std::string, std::string> alias(config->copyright_alias());
    182       tree.print_copyright(commit_dates, authors, alias);
     179      tree.print_copyright(alias);
    183180    }
    184181    catch (const std::runtime_error& x) {
  • trunk/lib/Directory.cc

    r230 r234  
    157157    assert(os.good());
    158158    if (local_path().empty())
    159       print_header(os, name(), level_+2, line_type, "index.html");
     159      print_header(os, name(), level_+2, user, line_type, "index.html");
    160160    else
    161       print_header(os, name(), level_+2, line_type, local_path()+"/index.html");
     161      print_header(os, name(), level_+2, user, line_type,
     162                   local_path()+"/index.html");
    162163    path_anchor(os);
    163164    os << "<p align=center>\n<img src='"
     
    177178    os << "<tbody>";
    178179
    179     bool dark=false;
     180    std::string color("light");
    180181    if (level_){
    181182      os << "<tr class=\"light\">\n";
     
    183184      anchor(os, "../index.html", "../");
    184185      os << "</td>\n</tr>\n";
    185       dark=!dark;
     186      color = "dark";
    186187    }
    187188
    188189    // print html links to daughter nodes
    189190    for (NodeConstIterator d = daughters_.begin(); d!=daughters_.end(); ++d) {
    190       if (dark)
    191         (*d)->html_tablerow(os,"dark", user);
     191      (*d)->html_tablerow(os,color, user);
     192      if (color=="dark")
     193        color = "light";
    192194      else
    193         (*d)->html_tablerow(os,"light", user);
    194       dark = !dark;
    195     }
    196     if (dark)
    197       os << "<tr class=\"dark\">\n";
    198     else
    199       os << "<tr class=\"light\">\n";
     195        color = "dark";
     196    }
     197    os << "<tr class=\"" << color << "\">\n";
    200198    os << "<td>Total</td>\n";
    201199    if (user=="all"){
     
    215213    os << "</tr>\n";
    216214    os << "</table>\n";
     215    print_author_summary(os);
    217216    os << "</p>\n";
    218217    print_footer(os);
    219218    os.close();
    220 
    221 
    222 
    223219  }
    224220
    225221
    226222  void Directory::print_copyright
    227   (const std::vector<std::string>& dates,
    228    const std::vector<std::string>& authors,
    229    std::map<std::string, std::string>& alias) const
    230   {
     223  (std::map<std::string, std::string>& alias) const {
    231224    if (!ignore()){
    232225      // print daughter nodes, i.e, this function is recursive
    233226      for (NodeConstIterator i = daughters_.begin(); i!=daughters_.end(); ++i)
    234         (*i)->print_copyright(dates, authors, alias);
     227        (*i)->print_copyright(alias);
    235228    }
    236229  }
  • trunk/lib/Directory.h

    r230 r234  
    66/*
    77  Copyright (C) 2005, 2006 Jari Häkkinen, Peter Johansson
     8  Copyright (C) 2007 Peter Johansson
    89
    910  This file is part of svndigest, http://lev.thep.lu.se/trac/svndigest
     
    8081    void print(const bool verbose=false) const;
    8182
    82     void print_copyright(const std::vector<std::string>& dates,
    83                          const std::vector<std::string>& author,
    84                          std::map<std::string, std::string>&) const;
     83    void print_copyright(std::map<std::string, std::string>&) const;
    8584
    8685  private:
  • trunk/lib/File.cc

    r232 r234  
    2626#include "html_utility.h"
    2727#include "Stats.h"
    28 #include "SVN.h"
     28#include "SVNlog.h"
    2929
    3030#include <cassert>
     
    6666    std::string html_name(outpath + ".html");
    6767    std::ofstream os(html_name.c_str());
    68     print_header(os, name(), level_+2, line_type, local_path()+".html");
     68    print_header(os, name(), level_+2, user, line_type, local_path()+".html");
    6969    path_anchor(os);
    7070    os << "<p align=center>\n<img src='"
     
    7272       << "' alt='[plot]' border=0>\n</p>";
    7373
    74     os << "<table class=\"listings\">\n";
    75     os << "<thead>";
    76     os << "<tr>\n";
    77     os << "<th>Author</th>\n";
    78     os << "<th>Lines</th>\n";
    79     os << "<th>Code</th>\n";
    80     os << "<th>Comments</th>\n";
    81     os << "</tr>\n</thead>\n";
    82     os << "<tbody>";
    83 
    84     bool dark=false;
    85     os << "<tr class=\"light\">\n";
    86     os << "<td class=\"directory\" colspan=\"5\">";
    87     anchor(os, "index.html", "../");
    88     os << "</td>\n</tr>\n";
    89     dark=!dark;
    90    
    91     // print authors
    92     for (std::set<std::string>::const_iterator i=stats_.authors().begin();
    93          i!=stats_.authors().end(); ++i){
    94       if (dark)
    95         os << "<tr class=\"dark\"><td>" << *i
    96            << "</td><td>" << stats_.lines(*i)
    97            << "</td><td>" << stats_.code(*i)
    98            << "</td><td>" << stats_.comments(*i)
    99            << "</td></tr>\n";
    100       else
    101         os << "<tr class=\"light\"><td>" << *i
    102            << "</td><td>" << stats_.lines(*i)
    103            << "</td><td>" << stats_.code(*i)
    104            << "</td><td>" << stats_.comments(*i)
    105            << "</td></tr>\n";
    106       dark=!dark;
    107     }
    108     if (dark)
    109       os << "<tr class=\"dark\">\n";
    110     else
    111       os << "<tr class=\"light\">\n";
    112     os << "<td>Total</td>\n";
    113     os << "<td>" << stats_.lines() << "</td>\n";
    114     os << "<td>" << stats_.code() << "</td>\n";
    115     os << "<td>" << stats_.comments() << "</td>\n";
    116     os << "</tr>\n";
    117     os << "</table>\n";
     74    print_author_summary(os);
    11875    os << "</p>\n";
    11976
     
    154111
    155112
    156   void File::print_copyright
    157   (const std::vector<std::string>& dates,
    158    const std::vector<std::string>& authors,
    159    std::map<std::string, std::string>& alias) const
    160   {
     113  void File::print_copyright (std::map<std::string,std::string>& alias) const{
    161114    if (ignore())
    162115      return;
    163     assert(dates.size()==authors.size());
    164116    using namespace std;
    165     SVN* svn=SVN::instance();
    166     vector<size_t> rev=svn->revisions(path());
     117
     118    SVNlog log(path());
    167119
    168120    typedef map<int, set<string> > Container;
    169121    Container copyright;
    170     for (vector<size_t>::iterator i=rev.begin(); i!=rev.end(); ++i) {
    171       assert(*i<dates.size());
    172       time_t sec = str2time(dates[*i]);
     122
     123   
     124    assert(log.author().size()==log.date().size());
     125    vector<string>::const_iterator author=log.author().begin();
     126    for (vector<string>::const_iterator date=log.date().begin();
     127         date!=log.date().end(); ++date, ++author) {
     128      time_t sec = str2time(*date);
    173129      tm* timeinfo = gmtime(&sec);
    174130
    175131      // find username in map of aliases
    176       map<string, string>::iterator name = alias.lower_bound(authors[*i]);
     132      map<string, string>::iterator name = alias.lower_bound(*author);
    177133      // if alias exist insert alias
    178       if (name != alias.end() && name->first==authors[*i])
     134      if (name != alias.end() && name->first==*author)
    179135        copyright[timeinfo->tm_year].insert(name->second);
    180136      else {
    181137        // else insert user name
    182         copyright[timeinfo->tm_year].insert(authors[*i]);
    183         std::cerr << "Warning: no alias found for `" << authors[*i] << "`\n";
     138        copyright[timeinfo->tm_year].insert(*author);
     139        std::cerr << "Warning: no alias found for `" << *author << "`\n";
    184140        // insert alias to avoid multiple warnings.
    185         alias.insert(name, std::make_pair(authors[*i], authors[*i]));
     141        alias.insert(name, std::make_pair(*author, *author));
    186142      }
    187143    }
    188    
     144
     145
    189146    // Code copied from Gnuplot -r70
    190147    char tmpname[]="/tmp/svndigestXXXXXX";
     
    197154    // already open for writing.
    198155    std::ofstream tmp(tmpname);
    199      
    200 
    201 
    202156
    203157    ifstream is(path().c_str());
     158    assert(is.good());
    204159    string line;
    205160    bool found_copyright = false;
     
    223178        // check whether copyright starts on this line
    224179        string::iterator i = search(line.begin(), line.end(), "Copyright (C)");
    225        
    226         if (i==line.end())
     180        if (i==line.end()) {
    227181          tmp << line << "\n";
     182        }     
    228183        else {
    229184          prefix = line.substr(0, distance(line.begin(), i));
    230185          found_copyright = true;
    231           if (!found_copyright)
    232             tmp << line << "\n";
    233           else {
    234             // Printing copyright statement
    235             for (Container::const_iterator i=copyright.begin();
    236                  i!=copyright.end();) {
    237               tmp << prefix << "Copyright (C) "
    238                    << 1900+i->first;
    239               Container::const_iterator j = i;
    240               while (++j!=copyright.end() && i->second == j->second){
    241                 tmp << ", " << 1900+j->first;
    242               }
    243               // printing authors
    244               for (set<string>::iterator a=i->second.begin();
    245                    a!=i->second.end(); ++a){
    246                 if (a!=i->second.begin())
    247                   tmp << ",";
    248                 tmp << " " << *a;
    249               }
    250               tmp << "\n";
    251               i = j;
     186          // Printing copyright statement
     187          for (Container::const_iterator i=copyright.begin();
     188               i!=copyright.end();) {
     189            tmp << prefix << "Copyright (C) "
     190                << 1900+i->first;
     191            Container::const_iterator j = i;
     192            assert(i!=copyright.end());
     193            while (++j!=copyright.end() && i->second == j->second){
     194              tmp << ", " << 1900+(j->first);
    252195            }
     196            // printing authors
     197            for (set<string>::iterator a=i->second.begin();
     198                 a!=i->second.end(); ++a){
     199              if (a!=i->second.begin())
     200                tmp << ",";
     201              tmp << " " << *a;
     202            }
     203            tmp << "\n";
     204            i = j;
    253205          }
    254206        }
  • trunk/lib/File.h

    r230 r234  
    7171    void print_blame(std::ofstream&, const std::string line_type) const;
    7272
    73     void print_copyright(const std::vector<std::string>& dates,
    74                          const std::vector<std::string>& author,
    75                          std::map<std::string, std::string>&) const;
     73    void print_copyright(std::map<std::string, std::string>&) const;
    7674
    7775  private:
  • trunk/lib/Makefile.am

    r233 r234  
    2626noinst_LTLIBRARIES = libsvndigest.la
    2727
    28 noinst_HEADERS = Configuration.h Directory.h File.h Gnuplot.h GnuplotFE.h \
    29   html_utility.h Node.h Parser.h rmdirhier.h Stats.h SVN.h SVNblame.h \
     28noinst_HEADERS = ColumnStream.h Configuration.h
     29  Directory.h File.h Gnuplot.h GnuplotFE.h \
     30  HtmlStream.h html_utility.h Node.h Parser.h rmdirhier.h \
     31  Stats.h SVN.h SVNblame.h  \
    3032  SVNinfo.h SVNlog.h SVNproperty.h utility.h
    3133
    32 libsvndigest_la_SOURCES = Configuration.cc Directory.cc File.cc \
    33   Gnuplot.cc GnuplotFE.cc \
     34libsvndigest_la_SOURCES = ColumnStream.cc Configuration.cc \
     35  Directory.cc File.cc \
     36  Gnuplot.cc GnuplotFE.cc HtmlStream.cc \
    3437  html_utility.cc Node.cc Parser.cc rmdirhier.cc Stats.cc SVN.cc        \
    3538  SVNblame.cc SVNinfo.cc SVNlog.cc SVNproperty.cc utility.cc
  • trunk/lib/Node.cc

    r213 r234  
    33/*
    44  Copyright (C) 2005, 2006 Jari Häkkinen, Peter Johansson
     5  Copyright (C) 2007 Peter Johansson
    56
    67  This file is part of svndigest, http://lev.thep.lu.se/trac/svndigest
     
    9697    else if (binary())
    9798      os << name() << " (<i>binary</i>)";
     99    // there is no output for nodes when user has zero contribution
     100    else if (user!="all" && !stats_.lines(user))
     101      os << name();
    98102    else
    99103      anchor(os,href(), name());
     
    117121
    118122
     123  void Node::print_author_summary(std::ostream& os) const
     124  {
     125    os << "<table class=\"listings\">\n";
     126    os << "<thead>";
     127    os << "<tr>\n";
     128    os << "<th>Author</th>\n";
     129    os << "<th>Lines</th>\n";
     130    os << "<th>Code</th>\n";
     131    os << "<th>Comments</th>\n";
     132    os << "</tr>\n</thead>\n";
     133    os << "<tbody>";
     134
     135    os << "<tr class=\"light\">\n";
     136    os << "<td class=\"directory\" colspan=\"5\">";
     137    anchor(os, "index.html", "../");
     138    os << "</td>\n</tr>\n";
     139       
     140    // print authors
     141    std::string color("dark");
     142    for (std::set<std::string>::const_iterator i=stats_.authors().begin();
     143         i!=stats_.authors().end(); ++i){
     144      os << "<tr class=\"" << color << "\"><td>" << *i
     145         << "</td><td>" << stats_.lines(*i)
     146         << "</td><td>" << stats_.code(*i)
     147         << "</td><td>" << stats_.comments(*i)
     148         << "</td></tr>\n";
     149      if (color=="dark")
     150        color="light";
     151      else
     152        color="dark";
     153    }
     154
     155    os << "<tr class=\"" << color << "\">\n";
     156    os << "<td>Total</td>\n";
     157    os << "<td>" << stats_.lines() << "</td>\n";
     158    os << "<td>" << stats_.code() << "</td>\n";
     159    os << "<td>" << stats_.comments() << "</td>\n";
     160    os << "</tr>\n";
     161    os << "</table>\n";
     162
     163  }
     164
    119165}} // end of namespace svndigest and namespace theplu
  • trunk/lib/Node.h

    r230 r234  
    142142    virtual void print(const bool verbose=false) const=0;
    143143
     144    void print_author_summary(std::ostream&) const;
     145
    144146    virtual void
    145     print_copyright(const std::vector<std::string>& dates,
    146                     const std::vector<std::string>& author,
    147                     std::map<std::string, std::string>&) const=0;
     147    print_copyright(std::map<std::string, std::string>&) const=0;
    148148
    149149    /**
  • trunk/lib/Parser.cc

    r222 r234  
    143143
    144144
     145  void Parser::markup_mode(std::istream& is)
     146  {
     147    bool block_com=false;
     148    std::string str;
     149    while(getline(is,str)) {
     150      line_type lt=empty;
     151      for (std::string::iterator iter=str.begin(); iter!=str.end(); ++iter){
     152        if (!block_com && match_begin(iter,str.end(), "<!--")){
     153          block_com=true;
     154          continue;
     155        }
     156        if (block_com && match_begin(iter,str.end(), "-->")){
     157          block_com=false;
     158          continue;
     159        }
     160        if (isalnum(*iter))
     161          if (!block_com)
     162            lt = code;
     163          else if (lt==empty)
     164            lt = comment;
     165      }
     166      type_.push_back(lt);
     167    }
     168  }
     169
     170
    145171  void Parser::text_mode(std::istream& is)
    146172  {
  • trunk/lib/Parser.h

    r218 r234  
    66/*
    77  Copyright (C) 2006 Jari Häkkinen, Peter Johansson
     8  Copyright (C) 2007 Peter Johansson
    89
    910  This file is part of svndigest, http://lev.thep.lu.se/trac/svndigest
     
    7273    void line_com_mode(std::istream& is, const std::string& com_start);
    7374
     75    void markup_mode(std::istream&);
     76
    7477    void text_mode(std::istream&);
    7578
  • trunk/lib/SVN.cc

    r233 r234  
    178178    }
    179179    svn_pool_destroy(subpool);
    180   }
    181 
    182 
    183   std::vector<std::string> SVN::commit_dates(const std::string& path)
    184   {
    185     // Allocate space in subpool to pool_ for apr_path (here a string).
    186     apr_pool_t *subpool = svn_pool_create(pool_);
    187     apr_array_header_t* apr_path=apr_array_make(subpool,1,4);
    188     // Copy path to apr_path.
    189     (*((const char **) apr_array_push(apr_path))) =
    190       apr_pstrdup(subpool, svn_path_internal_style(path.c_str(),subpool));
    191 
    192     // Setup to retrieve all commit logs.
    193     svn_opt_revision_t peg, start, head;
    194     peg.kind=svn_opt_revision_unspecified;
    195     start.kind=svn_opt_revision_number;
    196     start.value.number=0;
    197     head.kind=svn_opt_revision_head;
    198     svn_error_t* err=NULL;
    199     // Retrieving the last revision is only needed for the reserve
    200     // call below, not needed for the functionality here.
    201     if ((err=svn_ra_get_latest_revnum(ra_session_, &(head.value.number),
    202                                       subpool)))
    203       cleanup(err, subpool, "commit_dates: svn_ra_get_latest_revnum failed");
    204     // The struct we want to pass through to all log_message_receiver
    205     // calls, here we only want to push all commit dates into a
    206     // std::vector<std::string>.
    207     struct log_receiver_baton lb;
    208     lb.commit_dates.reserve(head.value.number+1); // revision 0 is also stored.
    209     lb.authors.reserve(head.value.number+1); // revision 0 is also stored.
    210     lb.rev.reserve(head.value.number+1); // revision 0 is also stored.
    211     if ((err=svn_client_log3(apr_path, &peg, &start, &head, 0, false, false,
    212                              log_message_receiver, static_cast<void*>(&lb),
    213                              context_, subpool)))
    214       // cleanupp will throw an exception
    215       cleanup(err, subpool, "commit_dates: svn_client_log3 failed");
    216     svn_pool_destroy(subpool);
    217     return lb.commit_dates;
    218180  }
    219181
     
    255217
    256218
    257   std::vector<std::string> SVN::authors(const std::string& path)
    258   {
    259     // Allocate space in subpool to pool_ for apr_path (here a string).
    260     apr_pool_t *subpool = svn_pool_create(pool_);
    261     apr_array_header_t* apr_path=apr_array_make(subpool,1,4);
    262     // Copy path to apr_path.
    263     (*((const char **) apr_array_push(apr_path))) =
    264       apr_pstrdup(subpool, svn_path_internal_style(path.c_str(),subpool));
    265 
    266     // Setup to retrieve all commit logs.
    267     svn_opt_revision_t peg, start, head;
    268     peg.kind=svn_opt_revision_unspecified;
    269     start.kind=svn_opt_revision_number;
    270     start.value.number=0;
    271     head.kind=svn_opt_revision_head;
    272     svn_error_t* err=NULL;
    273     // Retrieving the last revision is only needed for the reserve
    274     // call below, not needed for the functionality here.
    275     if ((err=svn_ra_get_latest_revnum(ra_session_, &(head.value.number),
    276                                       subpool)))
    277       cleanup(err, subpool, "commit_dates: svn_ra_get_latest_revnum failed");
    278     // The struct we want to pass through to all log_message_receiver
    279     // calls, here we only want to push all commit dates into a
    280     // std::vector<std::string>.
    281     struct log_receiver_baton lb;
    282     lb.commit_dates.reserve(head.value.number+1); // revision 0 is also stored.
    283     lb.authors.reserve(head.value.number+1); // revision 0 is also stored.
    284     lb.rev.reserve(head.value.number+1); // revision 0 is also stored.
    285     if ((err=svn_client_log3(apr_path, &peg, &start, &head, 0, false, false,
    286                              log_message_receiver, static_cast<void*>(&lb),
    287                              context_, subpool)))
    288       // cleanupp will throw an exception
    289       cleanup(err, subpool, "commit_dates: svn_client_log3 failed");
    290     svn_pool_destroy(subpool);
    291     return lb.authors;
    292   }
    293 
    294 
    295   std::vector<size_t> SVN::revisions(const std::string& path)
    296   {
    297     // Allocate space in subpool to pool_ for apr_path (here a string).
    298     apr_pool_t *subpool = svn_pool_create(pool_);
    299     apr_array_header_t* apr_path=apr_array_make(subpool,1,4);
    300     // Copy path to apr_path.
    301     (*((const char **) apr_array_push(apr_path))) =
    302       apr_pstrdup(subpool, svn_path_internal_style(path.c_str(),subpool));
    303 
    304     // Setup to retrieve all commit logs.
    305     svn_opt_revision_t peg, start, head;
    306     peg.kind=svn_opt_revision_unspecified;
    307     start.kind=svn_opt_revision_number;
    308     start.value.number=0;
    309     head.kind=svn_opt_revision_head;
    310     svn_error_t* err=NULL;
    311     // Retrieving the last revision is only needed for the reserve
    312     // call below, not needed for the functionality here.
    313     if ((err=svn_ra_get_latest_revnum(ra_session_, &(head.value.number),
    314                                       subpool)))
    315       cleanup(err, subpool, "commit_dates: svn_ra_get_latest_revnum failed");
    316     // The struct we want to pass through to all log_message_receiver
    317     // calls, here we only want to push all commit dates into a
    318     // std::vector<std::string>.
    319     struct log_receiver_baton lb;
    320     lb.commit_dates.reserve(head.value.number+1); // revision 0 is also stored.
    321     lb.authors.reserve(head.value.number+1); // revision 0 is also stored.
    322     lb.rev.reserve(head.value.number+1); // revision 0 is also stored.
    323     if ((err=svn_client_log3(apr_path, &peg, &start, &head, 0, false, false,
    324                              log_message_receiver, static_cast<void*>(&lb),
    325                              context_, subpool)))
    326       // cleanupp will throw an exception
    327       cleanup(err, subpool, "commit_dates: svn_client_log3 failed");
    328     svn_pool_destroy(subpool);
    329     return lb.rev;
    330   }
    331 
    332 
    333219  void SVN::cleanup(svn_error_t *err,apr_pool_t *pool,
    334220                    const std::string& message)
     
    366252      lb->authors.push_back("");
    367253    lb->rev.push_back(rev);
     254    if (msg)
     255      lb->msg.push_back(std::string(msg));
     256    else
     257      lb->msg.push_back(std::string(""));
    368258    return SVN_NO_ERROR;
    369259  }
  • trunk/lib/SVN.h

    r233 r234  
    143143    /// API.
    144144    ///
    145     std::vector<std::string> commit_dates(const std::string& path);
    146 
    147     ///
    148     /// similar to commit_dates
    149     ///
    150     std::vector<std::string> authors(const std::string& path);
    151     std::vector<size_t> revisions(const std::string& path);
     145    //std::vector<std::string> commit_dates(const std::string& path);
    152146
    153147    ///
  • trunk/lib/SVNlog.cc

    r233 r234  
    2525#include "SVN.h"
    2626
     27#include <cassert>
    2728#include <string>
    2829#include <vector>
     
    3637    SVN* svn = SVN::instance();
    3738    svn->client_log(path, &lb_);
     39    assert(date().size()==author().size());
     40    assert(date().size()==revision().size());
     41    assert(date().size()==message().size());
     42
    3843  }
    3944
  • trunk/lib/html_utility.cc

    r228 r234  
    2323
    2424#include "html_utility.h"
     25
     26#include "HtmlStream.h"
    2527#include "Stats.h"
     28#include "SVNlog.h"
    2629#include "utility.h"
    2730#include <config.h> // this header file is created by configure
    2831
     32#include <algorithm>
    2933#include <fstream>
    3034#include <iostream>
     
    4953  }
    5054
    51 
    5255 
    53   void html(std::istream& is, std::ostream& os, char delim)
    54   {
    55     char c;
    56     while (true){
    57       is.get(c);
    58       if (c==delim || !is.good()){
    59         return;
    60       }
    61       if (c=='"')
    62         os << '\"';
    63       else if (c=='\'')
    64         os << "\'";
    65       else if (c=='\n')
    66         os << "<br/>";
    67       else if (c=='<')
    68         os << "&lt;";
    69       else if (c=='>')
    70         os << "&gt;";
    71       else if (c=='&')
    72         os << "&amp;";
    73       else if (c=='\t')
    74         os << "&nbsp;&nbsp;";
    75       else if (c=='å')
    76         os << "&aring;";
    77       else if (c=='ä')
    78         os << "&auml;";
    79       else if (c=='ö')
    80         os << "&ouml;";
    81       else if (c=='Å')
    82         os << "&Aring;";
    83       else if (c=='Ä')
    84         os << "&Auml;";
    85       else if (c=='Ö')
    86         os << "&Ouml;";
    87       else if (c=='é')
    88         os << "&eacute;";
    89       else
    90         os << c;
    91     }
    92   }
    93  
    94 
    9556  void print_css(const std::string& str)
    9657  {
     
    261222
    262223
    263   void print_main_page(const std::string& dir,
    264                        const std::vector<std::string>& commit_dates,
     224  void print_main_page(const std::string& dir, const SVNlog& log,
    265225                       const Stats& stats)
    266226  {
    267227    std::string filename="index.html";
    268228    std::ofstream os(filename.c_str());
    269     print_header(os, dir, 0, "main", "index.html");
    270     time_t first = str2time(commit_dates[1]);
     229    print_header(os, dir, 0, "all", "main", "index.html");
     230
     231    using namespace std;
     232    map<string, time_t> latest_commit_date;
     233    assert(log.author().size()==log.date().size());
     234    typedef vector<string>::const_iterator iter;
     235    iter d=log.date().begin();
     236    for (iter a=log.author().begin();
     237         a!=log.author().end(); ++a, ++d) {
     238      latest_commit_date[*a]=str2time(*d);
     239    }
     240    // erase invalid authors
     241    latest_commit_date.erase("");
     242    latest_commit_date.erase("no author");
     243
     244    // vector of authors & date sorted with respect to date
     245    typedef vector<pair<string, time_t> > vector;
     246    vector author_date;
     247    author_date.reserve(latest_commit_date.size());
     248    back_insert_iterator<vector> i(author_date);
     249    copy(latest_commit_date.begin(), latest_commit_date.end(), i);
     250    sort(author_date.begin(), author_date.end(),
     251         pair_value_compare<string,time_t>());
     252
     253    print_general_information(os, log, author_date.size());
     254    print_authors(os, author_date, log, stats);
     255    print_recent_logs(os, log);
     256    os << "<hr width=100% />";
     257    print_footer(os);
     258    os.close();
     259
     260  }
     261
     262  void print_general_information(std::ostream& os, const SVNlog& log,
     263                                 size_t nof_authors)
     264  {
     265    time_t first = str2time(log.date()[1]);
    271266    std::string first_date = asctime(gmtime(&first));
    272     time_t last = str2time(commit_dates.back());
     267    time_t last = str2time(log.date().back());
    273268    std::string last_date = asctime(gmtime(&last));
    274269   
     
    310305
    311306    now = time(NULL);
    312     os << "<div class=\"main\">\n"
     307    os << "<div class=\"main\">"
    313308       << "<table class=\"main\"><thead><tr><th colspan=\"2\">"
    314309       << "General Information"
    315        << "</th></tr><thead>\n"
     310       << "</th></tr></thead>\n"
    316311       << "<tr><td>First Revision:</td><td>"
    317312       << first_date << "</td></tr>\n"
     
    340335     
    341336    os << "</td></tr>\n"
    342        << "<tr><td>Number of Authors:</td><td>" << stats.authors().size()
     337       << "<tr><td>Number of Authors:</td><td>" << nof_authors
    343338       << "</td></tr>\n"
    344        << "<tr><td>Revisions:</td><td>" << commit_dates.size()-1
     339       << "<tr><td>Revisions:</td><td>" << log.revision().size()-1
    345340       << "</td></tr>\n"
    346341       << "</table></div>\n";
    347     os << "<hr width=100% />";
    348    
    349        
    350     print_footer(os);
    351     os.close();
    352342  }
    353343
     
    367357
    368358
    369   void print_header(std::ostream& os, const std::string& title, u_int level,
    370                     const std::string& item, const std::string& path)
     359  void print_header(std::ostream& os, std::string title, u_int level,
     360                    std::string user, std::string item, std::string path)
    371361  {
    372362    os << "<!DOCTYPE html\n"
     
    397387    else
    398388      os << "<li>";
    399     anchor(os, "all/total/"+path, "Total", level,
     389    anchor(os, user+"/total/"+path, "Total", level,
    400390           "View statistics of all lines");
    401391    os << "</li>";
     
    405395    else
    406396      os << "<li>";
    407     anchor(os, "all/code/"+path, "Code", level,
     397    anchor(os, user+"/code/"+path, "Code", level,
    408398           "View statistics of code lines");
    409399    os << "</li>";
     
    413403    else
    414404      os << "<li>";
    415     anchor(os, "all/comments/"+path, "Comment", level,
     405    anchor(os, user+"/comments/"+path, "Comment", level,
    416406           "View statistics of comment lines");
    417407    os << "</li>";
     
    422412    else
    423413      os << "<li>";
    424     anchor(os, "all/empty/"+path, "Empty", level,
     414    anchor(os, user+"/empty/"+path, "Empty", level,
    425415           "View statistics of empty lines");
    426416    os << "</li>"
     
    430420
    431421
     422  void print_authors(std::ostream& os,
     423                     const std::vector<std::pair<std::string,time_t> >& ad,
     424                     const SVNlog& log, const Stats& stats)
     425  {
     426    os << "<div class=\"main\">"
     427       << "<table class=\"main\"><thead><tr><th colspan=\"2\">"
     428       << "Authors"
     429       << "</th></tr></thead>\n";
     430
     431    os << "<tr><td>Author</td>"
     432       << "<td>Number of Lines</td>"
     433       << "<td>Code Lines</td>"
     434       << "<td>Comment Lines</td>"
     435       << "<td>Latest Commitment</td>"
     436       <<"</tr>";
     437
     438    using namespace std;
     439    for (vector<pair<string,time_t> >::const_reverse_iterator i=ad.rbegin();
     440         i!=ad.rend(); ++i) {
     441      os << "<tr><td>";
     442      anchor(os, string(i->first+"/total/index.html"),i->first);
     443      os << "</td><td>" << stats.lines(i->first) << " ("
     444         << 100*stats.lines(i->first)/stats.lines() << "%)</td>"
     445         << "<td>" << stats.code(i->first) << " ("
     446         << 100*stats.code(i->first)/stats.code() << "%)</td>"
     447         << "<td>" << stats.comments(i->first) << " ("
     448         << 100*stats.comments(i->first)/stats.comments() << "%)</td>"
     449         << "<td>" << asctime(gmtime(&i->second)) << "</td>"
     450         <<"</tr>";
     451    }
     452
     453    os << "</table></div>\n";
     454   
     455  }
     456
     457
     458  void print_recent_logs(std::ostream& os, const SVNlog& log)
     459  {
     460    os << "<div class=\"main\">\n"
     461       << "<table class=\"main\"><thead><tr><th colspan=\"2\">"
     462       << "Recent Log"
     463       << "</th></tr></thead>\n";
     464
     465    std::vector<std::string>::const_reverse_iterator a=log.author().rbegin();
     466    std::vector<std::string>::const_reverse_iterator d=log.date().rbegin();
     467    std::vector<std::string>::const_reverse_iterator m=log.message().rbegin();
     468    assert(log.author().size()==log.date().size());
     469    assert(log.author().size()==log.message().size());
     470    HtmlStream hs(os);
     471    for (size_t i=0; i<10 && a!=log.author().rend(); ++i) {
     472      os << "<tr><td>" << *a << "</td>";
     473      time_t date = str2time(*d);
     474      os << "<td>" << asctime(gmtime(&date)) << "</td>";
     475      os << "<td>";
     476      hs << *m;
     477      os << "</td></tr>";
     478      ++a;
     479      ++d;
     480      ++m;
     481    }
     482    os << "</table></div>\n";
     483  }
     484
    432485}} // end of namespace svndigest and namespace theplu
  • trunk/lib/html_utility.h

    r225 r234  
    2828#include <fstream>
    2929#include <iosfwd>
     30#include <set>
    3031#include <string>
    3132#include <vector>
     
    3536
    3637  class Stats;
     38  class SVNlog;
     39
    3740  ///
    3841  /// @brief send anchor to stream @a os
    3942  ///
    40   /// @param address to link to
     43  /// @param href address to link to
    4144  /// @param name text visible on page
    4245  /// @param level '../' is added @a level times before @a href
     
    4851
    4952  ///
    50   /// Function translating text to html format. Most character are
    51   /// just passing through (unary operation).
     53  /// \brief printing cascading style sheet to file name @a str.
    5254  ///
    53   void html(std::istream&, std::ostream&, char delim='\n');
     55  void print_css(const std::string& str);
     56
     57  void print_authors(std::ostream& os,
     58                     const std::vector<std::pair<std::string, time_t> >&,
     59                     const SVNlog&, const Stats& stats);
    5460
    5561  ///
    56   /// @printing cascading style sheet to file name @a str.
     62  /// called by print_main_page
    5763  ///
    58   void print_css(const std::string& str);
     64  void print_general_information(std::ostream&, const SVNlog&, size_t);
    5965
    6066  ///
    6167  /// @brief print main page
    6268  ///
    63   void print_main_page(const std::string&, const std::vector<std::string>&,
    64                        const Stats&);
     69  void print_main_page(const std::string&, const SVNlog&, const Stats&);
     70   
     71  void print_recent_logs(std::ostream&, const SVNlog&);
    6572   
    6673  ///
     
    7279  /// @brief print html header of page
    7380  ///
    74   void print_header(std::ostream&, const std::string& name, u_int level,
    75                     const std::string&, const std::string&);
     81  /// \param os stream to print to
     82  /// \param name
     83  /// \param level
     84  /// \param
     85  void print_header(std::ostream& os, std::string name, u_int level,
     86                    std::string user, std::string item, std::string path);
    7687
    7788
  • trunk/lib/utility.h

    r227 r234  
    66/*
    77  Copyright (C) 2005, 2006 Jari Häkkinen, Peter Johansson
     8  Copyright (C) 2007 Peter Johansson
    89
    910  This file is part of svndigest, http://lev.thep.lu.se/trac/svndigest
     
    128129
    129130  ///
     131  /// @brief Functor comparing pairs using second.
     132  ///
     133  /// STL provides operator< for the pair.first element, but none for
     134  /// pair.second. This template provides this and can be used as the
     135  /// comparison object in generic functions such as the STL sort.
     136  ///
     137  template <class T1,class T2>
     138  struct pair_value_compare
     139  {
     140    ///
     141    /// @return true if x.second<y.second or (x.second==y.second and
     142    /// x.first<y.first)
     143    ///
     144    inline bool operator()(const std::pair<T1,T2>& x,
     145                           const std::pair<T1,T2>& y) {
     146      return ((x.second<y.second) ||
     147              (!(y.second<x.second) && (x.first<y.first)));
     148    }
     149  };
     150
     151  ///
    130152  /// Calculating sum of two vectors.
    131153  ///
Note: See TracChangeset for help on using the changeset viewer.