source: trunk/lib/Node.cc @ 497

Last change on this file since 497 was 497, checked in by Peter Johansson, 14 years ago

preparing for more statistics by adding StatsType layer in structure on top of previous structure, i.e., NewStructure? = StatsType/OldStructure?

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 8.1 KB
Line 
1// $Id: Node.cc 497 2007-10-14 04:58:06Z peter $
2
3/*
4  Copyright (C) 2005, 2006, 2007 Jari Häkkinen, Peter Johansson
5
6  This file is part of svndigest, http://trac.thep.lu.se/trac/svndigest
7
8  svndigest is free software; you can redistribute it and/or modify it
9  under the terms of the GNU General Public License as published by
10  the Free Software Foundation; either version 2 of the License, or
11  (at your option) any later version.
12
13  svndigest is distributed in the hope that it will be useful, but
14  WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  General Public License for more details.
17
18  You should have received a copy of the GNU General Public License
19  along with this program; if not, write to the Free Software
20  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
21  02111-1307, USA.
22*/
23
24#include "Node.h"
25
26#include "Date.h"
27#include "html_utility.h"
28#include "SVNlog.h"
29#include "SVNproperty.h"
30#include "utility.h"
31
32#include <cassert>
33#include <ctime>
34#include <fstream>
35#include <iostream>
36#include <sstream>
37
38#include <dirent.h>
39#include <sys/stat.h>
40
41namespace theplu{
42namespace svndigest{
43
44  std::string Node::project_=std::string();
45
46  Node::Node(const u_int level, const std::string& path, 
47             const std::string& local_path)
48    : level_(level), path_(path), stats_(path), log_(NULL), 
49      svninfo_(path)
50  { 
51    SVNproperty property(path);
52    binary_=property.binary();
53    svndigest_ignore_=property.svndigest_ignore();
54    if (Node::project_==std::string()) // no root directory in local path
55      Node::project_ = file_name(path);
56    else if (local_path.empty())
57      local_path_ = file_name(path);
58    else
59      local_path_ = local_path + "/" + file_name(path);
60
61    struct stat nodestat;                // C api from sys/stat.h
62    lstat(path.c_str(),&nodestat);   // C api from sys/stat.h
63    link_ = S_ISLNK(nodestat.st_mode);
64  }
65
66
67  Node::~Node(void)
68  {
69    if (log_)
70      delete log_;
71  }
72
73
74  std::string Node::author(void) const
75  { 
76    if (ignore())
77      return svninfo_.last_changed_author(); 
78    assert(log().author().size());
79    return log().author().back();
80  }
81
82
83  bool Node::dir(void) const
84  {
85    return false;
86  }
87
88
89  void Node::html_tablerow(std::ostream& os, 
90                           const std::string& css_class,
91                           const std::string& user) const
92  {
93    os << "<tr class=\"" << css_class << "\">\n"
94       << "<td class=\"" << node_type() << "\">";
95    if (svndigest_ignore())
96      os << name() << " (<i>svndigest:ignore</i>)";
97    else if (binary())
98      os << name() << " (<i>binary</i>)";
99    else if (link_)
100      os << name() << " (<i>link</i>)";
101    // there is no output for nodes when user has zero contribution
102    else if (user!="all" && !stats_.lines(user))
103      os << name();
104    else
105      os << anchor(href(), name()); 
106    os << "</td>\n"; 
107    if (user=="all") {
108      os << "<td>" << stats_.lines() << "</td>\n"
109         << "<td>" << stats_.code() << "</td>\n"
110         << "<td>" << stats_.comments() << "</td>\n"
111         << "<td>" << stats_.empty() << "</td>\n";
112    }
113    else {
114      os << "<td>" << stats_.lines(user); 
115      if (stats_.lines(user)) 
116        os << " (" << percent(stats_.lines(user),stats_.lines()) << "%)"; 
117      os << "</td>\n";
118      os << "<td>" << stats_.code(user); 
119      if (stats_.code(user)) 
120        os << " (" << percent(stats_.code(user),stats_.code()) << "%)"; 
121      os << "</td>\n";
122      os << "<td>" << stats_.comments(user); 
123      if (stats_.comments(user)) 
124        os << " (" << percent(stats_.comments(user),stats_.comments()) << "%)"; 
125      os << "</td>\n";
126      os << "<td>" << stats_.empty(user); 
127      if (stats_.empty(user)) 
128        os << " (" << percent(stats_.empty(user),stats_.empty()) << "%)"; 
129      os << "</td>\n";
130
131    }
132
133    os << "<td>" << trac_revision(last_changed_rev()) << "</td>\n"
134       << "<td>" << author() << "</td>\n"
135       << "</tr>\n";
136  }
137
138
139  svn_revnum_t Node::last_changed_rev(void) const
140  {
141    if (ignore())
142      return svninfo_.last_changed_rev();
143    assert(log().revision().size());
144    return log().revision().back();
145  }
146
147
148  const SVNlog& Node::log(void) const
149  {
150    if (!log_)
151      if (ignore())
152        log_ = new SVNlog;
153      else
154        log_ = new SVNlog(log_core());
155    return *log_;
156  }
157
158
159  std::string Node::name(void) const 
160  { 
161    std::string res = file_name(path_); 
162    return res;
163  }
164
165
166  std::string Node::output_dir(void) const
167  {
168    return output_dir_;
169  }
170
171
172  void Node::path_anchor(std::ostream& os) const
173  {
174    os << "<h2 class=\"path\">\n";
175    std::vector<std::string> words;
176    words.reserve(level_+1);
177    std::string word;
178    words.push_back(Node::project_);
179    std::stringstream ss(local_path());
180    while(getline(ss,word,'/'))
181      if (!word.empty()) // ignore double slash in path
182        words.push_back(word);
183    if (words.size()==1)
184      os << anchor("index.html", Node::project_,0, "View " + Node::project_);
185    else {
186      for (size_t i=0; i<words.size()-1; ++i){
187        os << anchor("index.html", words[i], level_-i, "View " + words[i]);
188        os << "<span class=\"sep\">/</span>";
189      }
190      os << anchor(href(), words.back(), level_+2-words.size(), 
191             "View " + words.back()); 
192    }
193    os << "\n</h2>\n";
194  }
195
196
197  void Node::print(const bool verbose) const
198  {
199    if (ignore())
200      return;
201    if (verbose)
202      std::cout << "Printing output for " << path_ << std::endl;
203    SVNlog log(path_);
204    print_core("classic", "all", "total", log);
205    print_core("classic", "all", "code", log);
206    print_core("classic", "all", "comments", log);
207    print_core("classic", "all", "empty", log);
208
209    for (std::set<std::string>::const_iterator i = stats_.authors().begin();
210         i!=stats_.authors().end(); ++i) {
211      print_core("classic", *i, "total", log);
212      print_core("classic", *i, "code", log);
213      print_core("classic", *i, "comments", log);
214      print_core("classic", *i, "empty", log);
215    }
216   
217    print_core(verbose);
218  }
219
220
221  void Node::print_author_summary(std::ostream& os, std::string line_type,
222                                  const SVNlog& log) const
223  { 
224    os << "<h3>Author Summary</h3>";
225    os << "<table class=\"listings\">\n";
226    os << "<thead>\n";
227    os << "<tr>\n";
228    os << "<th>Author</th>\n";
229    os << "<th>Lines</th>\n";
230    os << "<th>Code</th>\n";
231    os << "<th>Comments</th>\n";
232    os << "<th>Other</th>\n";
233    os << "<th>Revision</th>\n";
234    os << "<th>Date</th>\n";
235    os << "</tr>\n</thead>\n";
236    os << "<tbody>\n";
237
238    std::string color("light");
239    if (!dir()) {
240      os << "<tr class=\"" << color << "\">\n";
241      os << "<td class=\"directory\" colspan=\"7\">";
242      os << anchor("index.html", "../");
243      os << "</td>\n</tr>\n";
244    }
245
246    // print authors
247    const std::string timefmt("%e/%m/%y %H:%M:%S");
248    for (std::set<std::string>::const_iterator i=stats_.authors().begin();
249         i!=stats_.authors().end(); ++i){
250      if (color=="dark")
251        color="light";
252      else
253        color="dark";
254      os << "<tr class=\"" << color << "\"><td>"; 
255      os << anchor(*i+"/"+line_type+"/"+output_path()
256                   ,*i, level_+2, "View statistics for "+*i); 
257      os << "</td><td>" << stats_.lines(*i)
258         << "</td><td>" << stats_.code(*i)
259         << "</td><td>" << stats_.comments(*i)
260         << "</td><td>" << stats_.empty(*i);
261      if (log.exist(*i)) {
262        Commitment lc(log.latest_commit(*i));
263        os << "</td>" << "<td>" << trac_revision(lc.revision()) 
264           << "</td>" << "<td>" << Date(lc.date())(timefmt);
265      }
266      else {
267        os << "</td>" << "<td>N/A"
268           << "</td>" << "<td>N/A";
269      }
270      os << "</td></tr>\n";
271    }
272
273    os << "<tr class=\"" << color << "\">\n";
274    os << "<td>"; 
275    if (dir())
276      if (local_path().empty())
277        os << anchor("all/"+line_type+"/index.html"
278                     ,"Total", level_+2, "View statistics for all"); 
279      else
280        os << anchor("all/"+line_type+"/"+local_path()+"/index.html"
281                     ,"Total", level_+2, "View statistics for all"); 
282    else
283      os << anchor("all/"+line_type+"/"+local_path()+".html"
284                   ,"Total", level_+2, "View statistics for all"); 
285    os << "</td>\n";
286    os << "<td>" << stats_.lines() << "</td>\n";
287    os << "<td>" << stats_.code() << "</td>\n";
288    os << "<td>" << stats_.comments() << "</td>\n";
289    os << "<td>" << stats_.empty() << "</td>\n";
290    Commitment lc(log.latest_commit());
291    os << "<td>" << trac_revision(lc.revision()) << "</td>\n";
292    os << "<td>" << Date(lc.date())(timefmt)<< "</td>\n";
293    os << "</tr>\n";
294    os << "</tbody>\n";
295    os << "</table>\n";
296  }
297
298 
299  std::string Node::url(void) const
300  {
301    return svninfo_.url();
302  }
303
304}} // end of namespace svndigest and namespace theplu
Note: See TracBrowser for help on using the repository browser.