source: trunk/lib/Directory.cc @ 1238

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

remove print_copyright from Node interface since we use traverse to traverse node tree and only need to update copyright on File

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 7.6 KB
Line 
1// $Id: Directory.cc 1238 2010-10-23 22:05:25Z peter $
2
3/*
4  Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Jari Häkkinen, Peter Johansson
5
6  This file is part of svndigest, http://dev.thep.lu.se/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 3 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 svndigest. If not, see <http://www.gnu.org/licenses/>.
20*/
21
22#include "Directory.h"
23
24#include "Alias.h"
25#include "Configuration.h"
26#include "File.h"
27#include "html_utility.h"
28#include "Node.h"
29#include "NodeVisitor.h"
30#include "SVN.h"
31#include "SVNlog.h"
32#include "TinyStats.h"
33#include "utility.h"
34
35#include <algorithm>
36#include <cassert>
37#include <fstream>
38#include <functional>
39#include <iostream>
40#include <iterator>
41#include <list>
42#include <map>
43#include <sstream>
44
45#include <cerrno> // Needed to check error state below.
46#include <dirent.h>
47#include <sys/stat.h>
48
49namespace theplu{
50namespace svndigest{
51
52
53  Directory::Directory(const unsigned int level, const std::string& path, 
54                       const std::string& output)
55    : Node(level,path,output)
56  {
57    output_dir_=local_path();
58    if (!output_dir_.empty())
59      output_dir_+='/';
60
61    using namespace std;
62    DIR* directory=opendir(path.c_str());    // C API from dirent.h
63    if (!directory)
64      throw NodeException("ERROR: opendir() failed; " + path +
65                          " is not a directory");
66    list<string> entries;
67    struct dirent* entry;
68    errno=0;  // Global variable used by C to track errors, from errno.h
69    while ((entry=readdir(directory)))       // C API from dirent.h
70      entries.push_back(string(entry->d_name));
71    if (errno)
72      throw NodeException("ERROR: readdir() failed on " + path);
73    closedir(directory);
74
75    SVN* svn=SVN::instance();
76    for (list<string>::iterator i=entries.begin(); i!=entries.end(); ++i)
77      if ((*i)!=string(".") && (*i)!=string("..") && (*i)!=string(".svn")) {
78        string fullpath(path_+'/'+(*i));
79        switch (svn->version_controlled(fullpath)) {
80        case SVN::uptodate:
81          struct stat nodestat;                // C api from sys/stat.h
82          lstat(fullpath,&nodestat);   // C api from sys/stat.h
83          if (S_ISDIR(nodestat.st_mode))       // C api from sys/stat.h
84            daughters_.push_back(new Directory(level_+1,fullpath,local_path()));
85          else
86            daughters_.push_back(new File(level_,fullpath,local_path()));
87          break;
88        case SVN::unresolved:
89          throw NodeException(fullpath+" is not up to date");
90        case SVN::unversioned: ; // do nothing
91        }
92      }
93    std::sort(daughters_.begin(), daughters_.end(), NodePtrLess());
94  }
95
96
97  Directory::~Directory(void)
98  {
99    for (NodeIterator i=daughters_.begin(); i!=daughters_.end(); ++i)
100      delete *i;
101  }
102
103
104  void Directory::collect_stats(void)
105  {
106    stats_.reset();
107    for (NodeIterator i=daughters_.begin(); i!=daughters_.end(); ++i)
108      if (!(*i)->ignore()) {
109        stats_ += (*i)->stats();
110        (*i)->stats().reset();
111      }
112  }
113
114
115  bool Directory::dir(void) const
116  {
117    return true;
118  }
119
120
121  std::string Directory::href(void) const
122  { 
123    return name() + "/index.html";
124  }
125
126
127  svn_revnum_t Directory::last_changed_rev(void) const
128  {
129    svn_revnum_t res = svn_info().last_changed_rev();
130    for (NodeConstIterator i=daughters_.begin(); i!=daughters_.end(); ++i)
131      res = std::max(res, (*i)->last_changed_rev());
132    return res;
133  }
134
135
136  void Directory::log_core(SVNlog& log) const
137  {
138    for (NodeConstIterator i(daughters_.begin()); i != daughters_.end(); ++i)
139      log += (*i)->log();
140  }
141
142  std::string Directory::node_type(void) const
143  {
144    return std::string("directory");
145  }
146
147
148  std::string Directory::output_path(void) const
149  {
150    return output_dir()+"index.html";
151  }
152
153
154  void Directory::print_core(const bool verbose) const
155  {
156    //mkdir("blame_output/" + local_path());
157    // print daughter nodes
158    //for (NodeConstIterator i=daughters_.begin(); i!=daughters_.end(); ++i)
159    //  (*i)->print(verbose);
160  }
161
162
163  void Directory::print_core(const std::string& stats_type,
164                             const std::string& user, 
165                             const std::string& line_type,
166                             const SVNlog& log) const
167  {
168
169    const Stats& stats = stats_[stats_type];
170    std::string imagedir = stats_type+"/"+"images/"+line_type;
171    std::string outdir   = stats_type+"/"+user+"/" +line_type;
172    if (local_path()!="") {
173      imagedir += "/"+local_path();
174      outdir   += "/"+local_path();
175    }
176    mkdir_p(outdir);
177    if (user=="all")
178      mkdir_p(imagedir);
179    std::string html_name = outdir+"/index.html";
180    std::ofstream os(html_name.c_str());
181    assert(os.good());
182    if (local_path().empty())
183      print_header(os, name(), level_+3, user, line_type, "index.html", 
184                   stats_type);
185    else
186      print_header(os, name(), level_+3, user, line_type, 
187                   local_path()+"/index.html", stats_type);
188    path_anchor(os);
189
190    std::stringstream ss;
191    for (size_t i=0; i<level_; ++i)
192      ss << "../";
193    ss << "../../../";
194    if (user=="all")
195      ss << stats.plot(imagedir+"/index", line_type);
196    else
197      ss << imagedir << "/index";
198    os << "<p class=\"plot\">\n"; 
199    os << image(ss.str());
200    os << "</p>\n";
201
202    os << "<h3>File Summary";
203    if (user!="all")
204      os << " for " << user;
205    os << "</h3>";     
206    os << "<table class=\"listings\">\n";
207    os << "<thead>\n";
208    os << "<tr>\n";
209    os << "<th>Node</th>\n";
210    os << "<th>Lines</th>\n";
211    os << "<th>Code</th>\n";
212    os << "<th>Comments</th>\n";
213    os << "<th>Other</th>\n";
214    os << "<th>Revision</th>\n";
215    os << "<th>Author</th>\n";
216    os << "</tr>\n</thead>\n";
217    os << "<tbody>\n";
218
219    std::string color("light");
220    if (level_){
221      os << "<tr class=\"light\">\n";
222      os << "<td class=\"directory\" colspan=\"7\">";
223      os << anchor("../index.html", "../");
224      os << "</td>\n</tr>\n";
225      color = "dark";
226    }
227
228    // print html links to daughter nodes
229    for (NodeConstIterator d = daughters_.begin(); d!=daughters_.end(); ++d) {
230      (*d)->html_tablerow(os,stats_type, color, user);
231      if (color=="dark")
232        color = "light";
233      else
234        color = "dark";
235    }
236    os << "<tr class=\"" << color << "\">\n";
237    os << "<td>Total</td>\n";
238    if (user=="all"){
239      os << "<td>" << stats.lines() << "</td>\n";
240      os << "<td>" << stats.code() << "</td>\n";
241      os << "<td>" << stats.comments() << "</td>\n";
242      os << "<td>" << stats.empty() << "</td>\n";
243    }
244    else {
245      os << "<td>" << stats.lines(user); 
246      if (stats.lines(user)) 
247        os << " (" << percent(stats.lines(user),stats.lines()) << "%)"; 
248      os << "</td>\n";
249      os << "<td>" << stats.code(user); 
250      if (stats.code(user)) 
251        os << " (" << percent(stats.code(user),stats.code()) << "%)"; 
252      os << "</td>\n";
253      os << "<td>" << stats.comments(user); 
254      if (stats.comments(user)) 
255        os << " (" << percent(stats.comments(user),stats.comments()) << "%)"; 
256      os << "</td>\n";
257      os << "<td>" << stats.empty(user); 
258      if (stats.empty(user)) 
259        os << " (" << percent(stats.empty(user),stats.empty()) << "%)"; 
260      os << "</td>\n";
261    }
262    os << "<td>" << trac_revision(last_changed_rev()) << "</td>\n";
263    os << "<td>" << author() << "</td>\n";
264    os << "</tr>\n";
265    os << "</tbody>\n";
266    os << "</table>\n";
267    print_author_summary(os, stats, line_type, log);
268    os << "\n";
269    print_footer(os);
270    os.close(); 
271  }
272
273
274  void Directory::traverse(NodeVisitor& visitor)
275  {
276    visitor.enter(*this);
277    for (NodeIterator first=daughters_.begin(), end=daughters_.end();
278         first!=end; ++first)
279      (*first)->traverse(visitor);
280    visitor.leave(*this);
281  }
282
283
284}} // end of namespace svndigest and namespace theplu
Note: See TracBrowser for help on using the repository browser.