source: trunk/lib/Node.cc @ 1256

Last change on this file since 1256 was 1256, checked in by Peter Johansson, 11 years ago

remove debug output, and let test check that there is messages sent to standard error.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 8.7 KB
Line 
1// $Id: Node.cc 1256 2010-11-01 04:33:42Z peter $
2
3/*
4  Copyright (C) 2005, 2006, 2007, 2008 Jari Häkkinen, Peter Johansson
5  Copyright (C) 2009 Peter Johansson
6
7  This file is part of svndigest, http://dev.thep.lu.se/svndigest
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 3 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 svndigest. If not, see <http://www.gnu.org/licenses/>.
21*/
22
23#include "Node.h"
24
25#include "Configuration.h"
26#include "Date.h"
27#include "HtmlStream.h"
28#include "html_utility.h"
29#include "LineTypeParser.h"
30#include "SVNlog.h"
31#include "SVNproperty.h"
32#include "utility.h"
33
34#include <algorithm>
35#include <cassert>
36#include <ctime>
37#include <fstream>
38#include <iostream>
39#include <sstream>
40
41#include <dirent.h>
42#include <sys/stat.h>
43
44namespace theplu{
45namespace svndigest{
46
47  std::string Node::project_=std::string();
48
49  Node::Node(const unsigned int level, const std::string& path, 
50             const std::string& local_path)
51    : level_(level), path_(path), stats_(path), log_(NULL), 
52      svninfo_(path)
53  { 
54    SVNproperty property(path);
55    binary_=property.binary();
56    svndigest_ignore_=property.svndigest_ignore();
57    svncopyright_ignore_=property.svncopyright_ignore();
58    if (Node::project_==std::string()) // no root directory in local path
59      Node::project_ = file_name(path);
60    else if (local_path.empty())
61      local_path_ = file_name(path);
62    else
63      local_path_ = local_path + "/" + file_name(path);
64
65    struct stat nodestat;                // C api from sys/stat.h
66    lstat(path,&nodestat);   // C api from sys/stat.h
67    link_ = S_ISLNK(nodestat.st_mode);
68  }
69
70
71  Node::~Node(void)
72  {
73    if (log_)
74      delete log_;
75  }
76
77
78  std::string Node::author(void) const
79  { 
80    if (ignore())
81      return svninfo_.last_changed_author(); 
82    assert(log().commits().size());
83    return log().latest_commit().author();
84  }
85
86
87  bool Node::dir(void) const
88  {
89    return false;
90  }
91
92
93  void Node::html_tablerow(std::ostream& os, 
94                           const std::string& stats_type,
95                           const std::string& css_class,
96                           const std::string& user) const
97  {
98    os << "<tr class=\"" << css_class << "\">\n"
99       << "<td class=\"" << node_type() << "\">";
100    if (svndigest_ignore())
101      os << name() << " (<i>svndigest:ignore</i>)";
102    else if (binary())
103      os << name() << " (<i>binary</i>)";
104    else if (link_)
105      os << name() << " (<i>link</i>)";
106    // there is no output for nodes when user has zero contribution
107    else if (user!="all" && !tiny_stats_(stats_type,user,LineTypeParser::total))
108      os << name();
109    else if (!Configuration::instance().output_file() && !this->dir())
110      os << name();
111    else
112      os << anchor(href(), name()); 
113    os << "</td>\n"; 
114
115    html_tabletd(os, stats_type, user, LineTypeParser::total);
116    html_tabletd(os, stats_type, user, LineTypeParser::code);
117    html_tabletd(os, stats_type, user, LineTypeParser::comment);
118    html_tabletd(os, stats_type, user, LineTypeParser::other);
119   
120    os << "<td>" << trac_revision(last_changed_rev()) << "</td>\n"
121       << "<td>" << author() << "</td>\n"
122       << "</tr>\n";
123  }
124
125
126  void Node::html_tabletd(std::ostream& os, const std::string& stats_type, 
127                          const std::string& user, 
128                          LineTypeParser::line_type lt) const
129  {
130    os << "<td>" << tiny_stats_(stats_type, user, lt); 
131    if (user!="all" && tiny_stats_(stats_type, user, lt)) 
132      os << " (" << percent(tiny_stats_(stats_type, user, lt), 
133                            tiny_stats_(stats_type, "all", lt)) << "%)"; 
134    os << "</td>\n";
135  }
136 
137
138  void Node::init_tiny_stats(void)
139  {
140    tiny_stats_.init(stats_);
141  }
142
143
144  const SVNlog& Node::log(void) const
145  {
146    if (!log_) {
147      if (ignore())
148        log_ = new SVNlog;
149      else {
150        log_ = new SVNlog(path());
151        log_core(*log_);
152      }
153    }
154    return *log_;
155  }
156
157
158  std::string Node::name(void) const 
159  { 
160    std::string res = file_name(path_); 
161    return res;
162  }
163
164
165  std::string Node::output_dir(void) const
166  {
167    return output_dir_;
168  }
169
170
171  void Node::path_anchor(std::ostream& os) const
172  {
173    os << "<h2 class=\"path\">\n";
174    std::vector<std::string> words;
175    words.reserve(level_+1);
176    std::string word;
177    words.push_back(Node::project_);
178    std::stringstream ss(local_path());
179    while(getline(ss,word,'/'))
180      if (!word.empty()) // ignore double slash in path
181        words.push_back(word);
182    if (words.size()==1)
183      os << anchor("index.html", Node::project_,0, "View " + Node::project_);
184    else {
185      for (size_t i=0; i<words.size()-1; ++i){
186        os << anchor("index.html", words[i], level_-i, "View " + words[i]);
187        os << "<span class=\"sep\">/</span>";
188      }
189      os << anchor(href(), words.back(), level_+2-words.size(), 
190             "View " + words.back()); 
191    }
192    os << "\n</h2>\n";
193  }
194
195
196  void Node::print(const bool verbose) const
197  {
198    if (ignore())
199      return;
200    if (!Configuration::instance().output_file() && !this->dir())
201      return;
202    if (verbose)
203      std::cout << "Printing output for '" << path_ << "'" << std::endl;
204    const SVNlog& log = this->log();
205    typedef std::map<std::string, Stats*>::const_iterator iter;
206
207    const iter end(stats_.stats().end());
208    for (iter i=stats_.stats().begin();i!=end; ++i){
209      print_core(i->first, "all", "total", log);
210      print_core(i->first, "all", "code", log);
211      print_core(i->first, "all", "comments", log);
212      print_core(i->first, "all", "empty", log);
213      for (std::set<std::string>::const_iterator j=i->second->authors().begin();
214         j!=i->second->authors().end(); ++j) {
215        print_core(i->first, *j, "total", log);
216        print_core(i->first, *j, "code", log);
217        print_core(i->first, *j, "comments", log);
218        print_core(i->first, *j, "empty", log);
219      }
220    }
221    print_core(verbose);
222  }
223
224
225  void Node::print_author_summary(std::ostream& os, 
226                                  const Stats& stats,
227                                  const std::string& line_type,
228                                  const SVNlog& log) const
229  { 
230    HtmlStream hs(os);
231    os << "<h3>Author Summary</h3>";
232    os << "<table class=\"listings\">\n";
233    os << "<thead>\n";
234    os << "<tr>\n";
235    os << "<th>Author</th>\n";
236    os << "<th>Lines</th>\n";
237    os << "<th>Code</th>\n";
238    os << "<th>Comments</th>\n";
239    os << "<th>Other</th>\n";
240    os << "<th>Revision</th>\n";
241    os << "<th>Date</th>\n";
242    os << "</tr>\n</thead>\n";
243    os << "<tbody>\n";
244
245    std::string color("light");
246    if (!dir()) {
247      os << "<tr class=\"" << color << "\">\n";
248      os << "<td class=\"directory\" colspan=\"7\">";
249      os << anchor("index.html", "../");
250      os << "</td>\n</tr>\n";
251    }
252
253    // print authors
254    const std::string timefmt("%Y-%m-%d  %H:%M");
255    for (std::set<std::string>::const_iterator i=stats.authors().begin();
256         i!=stats.authors().end(); ++i){
257      if (color=="dark")
258        color="light";
259      else
260        color="dark";
261      os << "<tr class=\"" << color << "\"><td>"; 
262      os << anchor(*i+"/"+line_type+"/"+output_path()
263                   ,*i, level_+2, "View statistics for "+*i); 
264      os << "</td><td>" << stats.lines(*i)
265         << "</td><td>" << stats.code(*i)
266         << "</td><td>" << stats.comments(*i)
267         << "</td><td>" << stats.empty(*i);
268      if (log.exist(*i)) {
269        const Commitment& lc(log.latest_commit(*i));
270        os << "</td>" << "<td>" << trac_revision(lc.revision()) 
271           << "</td>" << "<td>";
272        hs << Date(lc.date())(timefmt);
273      }
274      else {
275        os << "</td>" << "<td>N/A"
276           << "</td>" << "<td>N/A";
277      }
278      os << "</td></tr>\n";
279    }
280
281    os << "<tr class=\"" << color << "\">\n";
282    os << "<td>"; 
283    if (dir())
284      if (local_path().empty())
285        os << anchor("all/"+line_type+"/index.html"
286                     ,"Total", level_+2, "View statistics for all"); 
287      else
288        os << anchor("all/"+line_type+"/"+local_path()+"/index.html"
289                     ,"Total", level_+2, "View statistics for all"); 
290    else
291      os << anchor("all/"+line_type+"/"+local_path()+".html"
292                   ,"Total", level_+2, "View statistics for all"); 
293    os << "</td>\n";
294    os << "<td>" << stats.lines() << "</td>\n";
295    os << "<td>" << stats.code() << "</td>\n";
296    os << "<td>" << stats.comments() << "</td>\n";
297    os << "<td>" << stats.empty() << "</td>\n";
298    const Commitment& lc(log.latest_commit());
299    os << "<td>" << trac_revision(lc.revision()) << "</td>\n";
300    os << "<td>";
301    hs << Date(lc.date())(timefmt);
302    os << "</td>\n";
303    os << "</tr>\n";
304    os << "</tbody>\n";
305    os << "</table>\n";
306  }
307
308 
309  const StatsCollection& Node::stats(void) const
310  {
311    return stats_;
312  }
313
314
315  StatsCollection& Node::stats(void)
316  {
317    return stats_;
318  }
319
320
321  bool Node::svncopyright_ignore(void) const
322  {
323    return svncopyright_ignore_;
324  }
325
326
327  std::string Node::url(void) const
328  {
329    return svninfo_.url();
330  }
331
332}} // end of namespace svndigest and namespace theplu
Note: See TracBrowser for help on using the repository browser.