Changeset 234
- Timestamp:
- Apr 9, 2007, 2:08:26 PM (16 years ago)
- Location:
- trunk
- Files:
-
- 4 added
- 17 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/bin/Parameter.cc
r229 r234 24 24 25 25 #include "Parameter.h" 26 27 #include "ColumnStream.h" 26 28 #include "utility.h" 27 29 #include <config.h> // this header file is created by configure … … 43 45 bool ok=false; 44 46 std::string myargv(argv[i]); 45 if (myargv=="- c" || myargv=="--config"){47 if (myargv=="--config-file"){ 46 48 if (++i<argc){ 47 49 config_file_= std::string(argv[i]); … … 136 138 137 139 if (config_file_.empty()) 138 runtime_error(string("svndigest: Parameter --config requires argument."));140 runtime_error(string("svndigest: Parameter --config-file requires argument.")); 139 141 140 142 } … … 157 159 { 158 160 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; 188 198 } 189 199 -
trunk/bin/svndigest.cc
r230 r234 32 32 #include "SVN.h" 33 33 #include "SVNinfo.h" 34 #include "SVNlog.h" 34 35 #include "utility.h" 35 36 … … 129 130 stats+=tree.parse(option->verbose()); 130 131 131 // Retrieve commit dates. 132 std::vector<std::string> commit_dates; 132 // Retrieve commit dates etc from SVNlog. 133 133 try { 134 134 if (option->verbose()) 135 135 std::cout << "Retrieving commit dates" << std::endl; 136 136 svn->setup_ra_session(repo); 137 commit_dates=svn->commit_dates(repo);138 137 } 139 138 catch (SVNException e) { … … 141 140 exit(-1); 142 141 } 143 // Is this line needed? 144 svn->setup_ra_session(repo); 145 std::vector<std::string> authors=svn->authors(repo); 142 SVNlog svnlog(repo); 146 143 147 144 // remove target if needed … … 155 152 std::cout << "Generating output" << std::endl; 156 153 if (!option->revisions()) 157 GnuplotFE::instance()->set_dates( commit_dates);154 GnuplotFE::instance()->set_dates(svnlog.date()); 158 155 chdir(option->targetdir().c_str()); 159 156 mkdir(tree.name()); … … 162 159 +tree.name()+"'"); 163 160 print_css("svndigest.css"); 164 print_main_page(tree.name(), commit_dates, stats);161 print_main_page(tree.name(), svnlog, stats); 165 162 mkdir("all"); 166 163 for (std::set<std::string>::const_iterator i = stats.authors().begin(); … … 180 177 std::cout << "Updating copyright statements" << std::endl; 181 178 std::map<std::string, std::string> alias(config->copyright_alias()); 182 tree.print_copyright( commit_dates, authors,alias);179 tree.print_copyright(alias); 183 180 } 184 181 catch (const std::runtime_error& x) { -
trunk/lib/Directory.cc
r230 r234 157 157 assert(os.good()); 158 158 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"); 160 160 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"); 162 163 path_anchor(os); 163 164 os << "<p align=center>\n<img src='" … … 177 178 os << "<tbody>"; 178 179 179 bool dark=false;180 std::string color("light"); 180 181 if (level_){ 181 182 os << "<tr class=\"light\">\n"; … … 183 184 anchor(os, "../index.html", "../"); 184 185 os << "</td>\n</tr>\n"; 185 dark=!dark;186 color = "dark"; 186 187 } 187 188 188 189 // print html links to daughter nodes 189 190 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"; 192 194 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"; 200 198 os << "<td>Total</td>\n"; 201 199 if (user=="all"){ … … 215 213 os << "</tr>\n"; 216 214 os << "</table>\n"; 215 print_author_summary(os); 217 216 os << "</p>\n"; 218 217 print_footer(os); 219 218 os.close(); 220 221 222 223 219 } 224 220 225 221 226 222 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 { 231 224 if (!ignore()){ 232 225 // print daughter nodes, i.e, this function is recursive 233 226 for (NodeConstIterator i = daughters_.begin(); i!=daughters_.end(); ++i) 234 (*i)->print_copyright( dates, authors,alias);227 (*i)->print_copyright(alias); 235 228 } 236 229 } -
trunk/lib/Directory.h
r230 r234 6 6 /* 7 7 Copyright (C) 2005, 2006 Jari Häkkinen, Peter Johansson 8 Copyright (C) 2007 Peter Johansson 8 9 9 10 This file is part of svndigest, http://lev.thep.lu.se/trac/svndigest … … 80 81 void print(const bool verbose=false) const; 81 82 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; 85 84 86 85 private: -
trunk/lib/File.cc
r232 r234 26 26 #include "html_utility.h" 27 27 #include "Stats.h" 28 #include "SVN .h"28 #include "SVNlog.h" 29 29 30 30 #include <cassert> … … 66 66 std::string html_name(outpath + ".html"); 67 67 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"); 69 69 path_anchor(os); 70 70 os << "<p align=center>\n<img src='" … … 72 72 << "' alt='[plot]' border=0>\n</p>"; 73 73 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); 118 75 os << "</p>\n"; 119 76 … … 154 111 155 112 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{ 161 114 if (ignore()) 162 115 return; 163 assert(dates.size()==authors.size());164 116 using namespace std; 165 SVN* svn=SVN::instance(); 166 vector<size_t> rev=svn->revisions(path());117 118 SVNlog log(path()); 167 119 168 120 typedef map<int, set<string> > Container; 169 121 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); 173 129 tm* timeinfo = gmtime(&sec); 174 130 175 131 // 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); 177 133 // if alias exist insert alias 178 if (name != alias.end() && name->first== authors[*i])134 if (name != alias.end() && name->first==*author) 179 135 copyright[timeinfo->tm_year].insert(name->second); 180 136 else { 181 137 // 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"; 184 140 // 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)); 186 142 } 187 143 } 188 144 145 189 146 // Code copied from Gnuplot -r70 190 147 char tmpname[]="/tmp/svndigestXXXXXX"; … … 197 154 // already open for writing. 198 155 std::ofstream tmp(tmpname); 199 200 201 202 156 203 157 ifstream is(path().c_str()); 158 assert(is.good()); 204 159 string line; 205 160 bool found_copyright = false; … … 223 178 // check whether copyright starts on this line 224 179 string::iterator i = search(line.begin(), line.end(), "Copyright (C)"); 225 226 if (i==line.end()) 180 if (i==line.end()) { 227 181 tmp << line << "\n"; 182 } 228 183 else { 229 184 prefix = line.substr(0, distance(line.begin(), i)); 230 185 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); 252 195 } 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; 253 205 } 254 206 } -
trunk/lib/File.h
r230 r234 71 71 void print_blame(std::ofstream&, const std::string line_type) const; 72 72 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; 76 74 77 75 private: -
trunk/lib/Makefile.am
r233 r234 26 26 noinst_LTLIBRARIES = libsvndigest.la 27 27 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 \ 28 noinst_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 \ 30 32 SVNinfo.h SVNlog.h SVNproperty.h utility.h 31 33 32 libsvndigest_la_SOURCES = Configuration.cc Directory.cc File.cc \ 33 Gnuplot.cc GnuplotFE.cc \ 34 libsvndigest_la_SOURCES = ColumnStream.cc Configuration.cc \ 35 Directory.cc File.cc \ 36 Gnuplot.cc GnuplotFE.cc HtmlStream.cc \ 34 37 html_utility.cc Node.cc Parser.cc rmdirhier.cc Stats.cc SVN.cc \ 35 38 SVNblame.cc SVNinfo.cc SVNlog.cc SVNproperty.cc utility.cc -
trunk/lib/Node.cc
r213 r234 3 3 /* 4 4 Copyright (C) 2005, 2006 Jari Häkkinen, Peter Johansson 5 Copyright (C) 2007 Peter Johansson 5 6 6 7 This file is part of svndigest, http://lev.thep.lu.se/trac/svndigest … … 96 97 else if (binary()) 97 98 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(); 98 102 else 99 103 anchor(os,href(), name()); … … 117 121 118 122 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 119 165 }} // end of namespace svndigest and namespace theplu -
trunk/lib/Node.h
r230 r234 142 142 virtual void print(const bool verbose=false) const=0; 143 143 144 void print_author_summary(std::ostream&) const; 145 144 146 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; 148 148 149 149 /** -
trunk/lib/Parser.cc
r222 r234 143 143 144 144 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 145 171 void Parser::text_mode(std::istream& is) 146 172 { -
trunk/lib/Parser.h
r218 r234 6 6 /* 7 7 Copyright (C) 2006 Jari Häkkinen, Peter Johansson 8 Copyright (C) 2007 Peter Johansson 8 9 9 10 This file is part of svndigest, http://lev.thep.lu.se/trac/svndigest … … 72 73 void line_com_mode(std::istream& is, const std::string& com_start); 73 74 75 void markup_mode(std::istream&); 76 74 77 void text_mode(std::istream&); 75 78 -
trunk/lib/SVN.cc
r233 r234 178 178 } 179 179 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 reserve200 // 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_receiver205 // calls, here we only want to push all commit dates into a206 // 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 exception215 cleanup(err, subpool, "commit_dates: svn_client_log3 failed");216 svn_pool_destroy(subpool);217 return lb.commit_dates;218 180 } 219 181 … … 255 217 256 218 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 reserve274 // 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_receiver279 // calls, here we only want to push all commit dates into a280 // 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 exception289 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 reserve312 // 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_receiver317 // calls, here we only want to push all commit dates into a318 // 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 exception327 cleanup(err, subpool, "commit_dates: svn_client_log3 failed");328 svn_pool_destroy(subpool);329 return lb.rev;330 }331 332 333 219 void SVN::cleanup(svn_error_t *err,apr_pool_t *pool, 334 220 const std::string& message) … … 366 252 lb->authors.push_back(""); 367 253 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("")); 368 258 return SVN_NO_ERROR; 369 259 } -
trunk/lib/SVN.h
r233 r234 143 143 /// API. 144 144 /// 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); 152 146 153 147 /// -
trunk/lib/SVNlog.cc
r233 r234 25 25 #include "SVN.h" 26 26 27 #include <cassert> 27 28 #include <string> 28 29 #include <vector> … … 36 37 SVN* svn = SVN::instance(); 37 38 svn->client_log(path, &lb_); 39 assert(date().size()==author().size()); 40 assert(date().size()==revision().size()); 41 assert(date().size()==message().size()); 42 38 43 } 39 44 -
trunk/lib/html_utility.cc
r228 r234 23 23 24 24 #include "html_utility.h" 25 26 #include "HtmlStream.h" 25 27 #include "Stats.h" 28 #include "SVNlog.h" 26 29 #include "utility.h" 27 30 #include <config.h> // this header file is created by configure 28 31 32 #include <algorithm> 29 33 #include <fstream> 30 34 #include <iostream> … … 49 53 } 50 54 51 52 55 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 << "<";69 else if (c=='>')70 os << ">";71 else if (c=='&')72 os << "&";73 else if (c=='\t')74 os << " ";75 else if (c=='å')76 os << "å";77 else if (c=='ä')78 os << "ä";79 else if (c=='ö')80 os << "ö";81 else if (c=='Å')82 os << "Å";83 else if (c=='Ä')84 os << "Ä";85 else if (c=='Ö')86 os << "Ö";87 else if (c=='é')88 os << "é";89 else90 os << c;91 }92 }93 94 95 56 void print_css(const std::string& str) 96 57 { … … 261 222 262 223 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, 265 225 const Stats& stats) 266 226 { 267 227 std::string filename="index.html"; 268 228 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]); 271 266 std::string first_date = asctime(gmtime(&first)); 272 time_t last = str2time( commit_dates.back());267 time_t last = str2time(log.date().back()); 273 268 std::string last_date = asctime(gmtime(&last)); 274 269 … … 310 305 311 306 now = time(NULL); 312 os << "<div class=\"main\"> \n"307 os << "<div class=\"main\">" 313 308 << "<table class=\"main\"><thead><tr><th colspan=\"2\">" 314 309 << "General Information" 315 << "</th></tr>< thead>\n"310 << "</th></tr></thead>\n" 316 311 << "<tr><td>First Revision:</td><td>" 317 312 << first_date << "</td></tr>\n" … … 340 335 341 336 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 343 338 << "</td></tr>\n" 344 << "<tr><td>Revisions:</td><td>" << commit_dates.size()-1339 << "<tr><td>Revisions:</td><td>" << log.revision().size()-1 345 340 << "</td></tr>\n" 346 341 << "</table></div>\n"; 347 os << "<hr width=100% />";348 349 350 print_footer(os);351 os.close();352 342 } 353 343 … … 367 357 368 358 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) 371 361 { 372 362 os << "<!DOCTYPE html\n" … … 397 387 else 398 388 os << "<li>"; 399 anchor(os, "all/total/"+path, "Total", level,389 anchor(os, user+"/total/"+path, "Total", level, 400 390 "View statistics of all lines"); 401 391 os << "</li>"; … … 405 395 else 406 396 os << "<li>"; 407 anchor(os, "all/code/"+path, "Code", level,397 anchor(os, user+"/code/"+path, "Code", level, 408 398 "View statistics of code lines"); 409 399 os << "</li>"; … … 413 403 else 414 404 os << "<li>"; 415 anchor(os, "all/comments/"+path, "Comment", level,405 anchor(os, user+"/comments/"+path, "Comment", level, 416 406 "View statistics of comment lines"); 417 407 os << "</li>"; … … 422 412 else 423 413 os << "<li>"; 424 anchor(os, "all/empty/"+path, "Empty", level,414 anchor(os, user+"/empty/"+path, "Empty", level, 425 415 "View statistics of empty lines"); 426 416 os << "</li>" … … 430 420 431 421 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 432 485 }} // end of namespace svndigest and namespace theplu -
trunk/lib/html_utility.h
r225 r234 28 28 #include <fstream> 29 29 #include <iosfwd> 30 #include <set> 30 31 #include <string> 31 32 #include <vector> … … 35 36 36 37 class Stats; 38 class SVNlog; 39 37 40 /// 38 41 /// @brief send anchor to stream @a os 39 42 /// 40 /// @param address to link to43 /// @param href address to link to 41 44 /// @param name text visible on page 42 45 /// @param level '../' is added @a level times before @a href … … 48 51 49 52 /// 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. 52 54 /// 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); 54 60 55 61 /// 56 /// @printing cascading style sheet to file name @a str.62 /// called by print_main_page 57 63 /// 58 void print_ css(const std::string& str);64 void print_general_information(std::ostream&, const SVNlog&, size_t); 59 65 60 66 /// 61 67 /// @brief print main page 62 68 /// 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&); 65 72 66 73 /// … … 72 79 /// @brief print html header of page 73 80 /// 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); 76 87 77 88 -
trunk/lib/utility.h
r227 r234 6 6 /* 7 7 Copyright (C) 2005, 2006 Jari Häkkinen, Peter Johansson 8 Copyright (C) 2007 Peter Johansson 8 9 9 10 This file is part of svndigest, http://lev.thep.lu.se/trac/svndigest … … 128 129 129 130 /// 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 /// 130 152 /// Calculating sum of two vectors. 131 153 ///
Note: See TracChangeset
for help on using the changeset viewer.