source: trunk/lib/Directory.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: 7.3 KB
Line 
1// $Id: Directory.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 "Directory.h"
25
26#include "Alias.h"
27#include "File.h"
28#include "html_utility.h"
29#include "Node.h"
30#include "SVN.h"
31#include "SVNlog.h"
32#include "utility.h"
33
34#include <algorithm>
35#include <cassert>
36#include <fstream>
37#include <functional>
38#include <iostream>
39#include <iterator>
40#include <list>
41#include <map>
42
43#include <cerrno> // Needed to check error state below.
44#include <dirent.h>
45#include <sys/stat.h>
46
47namespace theplu{
48namespace svndigest{
49
50
51  Directory::Directory(const u_int level, const std::string& path, 
52                       const std::string& output)
53    : Node(level,path,output)
54  {
55    output_dir_=local_path();
56    if (!output_dir_.empty())
57      output_dir_+='/';
58
59    using namespace std;
60    DIR* directory=opendir(path.c_str());    // C API from dirent.h
61    if (!directory)
62      throw NodeException("ERROR: opendir() failed; " + path +
63                          " is not a directory");
64    list<string> entries;
65    struct dirent* entry;
66    errno=0;  // Global variable used by C to track errors, from errno.h
67    while ((entry=readdir(directory)))       // C API from dirent.h
68      entries.push_back(string(entry->d_name));
69    if (errno)
70      throw NodeException("ERROR: readdir() failed on " + path);
71    closedir(directory);
72
73    SVN* svn=SVN::instance();
74    for (list<string>::iterator i=entries.begin(); i!=entries.end(); ++i)
75      if ((*i)!=string(".") && (*i)!=string("..") && (*i)!=string(".svn")) {
76        string fullpath(path_+'/'+(*i));
77        switch (svn->version_controlled(fullpath)) {
78        case SVN::uptodate:
79          struct stat nodestat;                // C api from sys/stat.h
80          lstat(fullpath.c_str(),&nodestat);   // C api from sys/stat.h
81          if (S_ISDIR(nodestat.st_mode))       // C api from sys/stat.h
82            daughters_.push_back(new Directory(level_+1,fullpath,local_path()));
83          else
84            daughters_.push_back(new File(level_,fullpath,local_path()));
85          break;
86        case SVN::unresolved:
87          throw NodeException(fullpath+" is not up to date");
88        case SVN::unversioned: ; // do nothing
89        }
90      }
91    daughters_.sort(NodePtrLess());
92  }
93
94
95  Directory::~Directory(void)
96  {
97    for (NodeIterator i=daughters_.begin(); i!=daughters_.end(); ++i)
98      delete *i;
99  }
100
101  bool Directory::dir(void) const
102  {
103    return true;
104  }
105
106  std::string Directory::href(void) const
107  { 
108    return name() + "/index.html";
109  }
110
111
112  SVNlog Directory::log_core(void) const
113  {
114    SVNlog log(path());
115    for (NodeConstIterator i(daughters_.begin()); i != daughters_.end(); ++i)
116      log += (*i)->log();
117    return log;
118  }
119
120  std::string Directory::node_type(void) const
121  {
122    return std::string("directory");
123  }
124
125
126  std::string Directory::output_path(void) const
127  {
128    return output_dir()+"index.html";
129  }
130
131  const ClassicStats& Directory::parse(const bool verbose)
132  {
133    stats_.reset();
134    // Directories themselved give no contribution to statistics.
135    for (NodeIterator i=daughters_.begin(); i!=daughters_.end(); ++i)
136      if (!(*i)->ignore())
137        stats_ += (*i)->parse(verbose);
138    return stats_;
139  }
140
141
142  void Directory::print_core(const bool verbose) const
143  {
144    // print daughter nodes, i.e., this function is recursive
145    for (NodeConstIterator i=daughters_.begin(); i!=daughters_.end(); ++i)
146      (*i)->print(verbose);
147  }
148
149
150  void Directory::print_core(const std::string& stats_type,
151                             const std::string& user, 
152                             const std::string& line_type,
153                             const SVNlog& log) const
154  {
155
156    std::string outdir = stats_type+"/"+user+"/"+line_type+"/"+local_path_;
157    if (local_path_=="")
158      outdir = stats_type+"/"+user+"/"+line_type;
159
160    mkdir(outdir);
161    std::string imagedir = stats_type+"/"+"images/"+line_type+"/"+local_path_;
162    if (user=="all")
163      mkdir(imagedir);
164    std::string html_name = outdir+"/index.html";
165    std::ofstream os(html_name.c_str());
166    assert(os.good());
167    if (local_path().empty())
168      print_header(os, name(), level_+3, user, line_type, "index.html");
169    else
170      print_header(os, name(), level_+3, user, line_type, 
171                   local_path()+"/index.html");
172    path_anchor(os);
173    os << "<p class=\"plot\">\n<img src='"; 
174    for (size_t i=0; i<level_; ++i)
175      os << "../";
176    os << "../../../";
177    if (user=="all")
178      os << stats_.plot(imagedir+"/index.png", line_type);
179    else
180      os << imagedir << "/index.png";
181    os << "' alt='[plot]' /></p>\n";
182    os << "<h3>File Summary";
183    if (user!="all")
184      os << " for " << user;
185    os << "</h3>";     
186    os << "<table class=\"listings\">\n";
187    os << "<thead>\n";
188    os << "<tr>\n";
189    os << "<th>Node</th>\n";
190    os << "<th>Lines</th>\n";
191    os << "<th>Code</th>\n";
192    os << "<th>Comments</th>\n";
193    os << "<th>Other</th>\n";
194    os << "<th>Revision</th>\n";
195    os << "<th>Author</th>\n";
196    os << "</tr>\n</thead>\n";
197    os << "<tbody>\n";
198
199    std::string color("light");
200    if (level_){
201      os << "<tr class=\"light\">\n";
202      os << "<td class=\"directory\" colspan=\"7\">";
203      os << anchor("../index.html", "../");
204      os << "</td>\n</tr>\n";
205      color = "dark";
206    }
207
208    // print html links to daughter nodes
209    for (NodeConstIterator d = daughters_.begin(); d!=daughters_.end(); ++d) {
210      (*d)->html_tablerow(os,color, user);
211      if (color=="dark")
212        color = "light";
213      else
214        color = "dark";
215    }
216    os << "<tr class=\"" << color << "\">\n";
217    os << "<td>Total</td>\n";
218    if (user=="all"){
219      os << "<td>" << stats_.lines() << "</td>\n";
220      os << "<td>" << stats_.code() << "</td>\n";
221      os << "<td>" << stats_.comments() << "</td>\n";
222      os << "<td>" << stats_.empty() << "</td>\n";
223    }
224    else {
225      os << "<td>" << stats_.lines(user); 
226      if (stats_.lines(user)) 
227        os << " (" << percent(stats_.lines(user),stats_.lines()) << "%)"; 
228      os << "</td>\n";
229      os << "<td>" << stats_.code(user); 
230      if (stats_.code(user)) 
231        os << " (" << percent(stats_.code(user),stats_.code()) << "%)"; 
232      os << "</td>\n";
233      os << "<td>" << stats_.comments(user); 
234      if (stats_.comments(user)) 
235        os << " (" << percent(stats_.comments(user),stats_.comments()) << "%)"; 
236      os << "</td>\n";
237      os << "<td>" << stats_.empty(user); 
238      if (stats_.empty(user)) 
239        os << " (" << percent(stats_.empty(user),stats_.empty()) << "%)"; 
240      os << "</td>\n";
241    }
242    os << "<td>" << trac_revision(stats_.last_changed_rev()) << "</td>\n";
243    os << "<td>" << author() << "</td>\n";
244    os << "</tr>\n";
245    os << "</tbody>\n";
246    os << "</table>\n";
247    print_author_summary(os, line_type, log);
248    os << "\n";
249    print_footer(os);
250    os.close(); 
251  }
252
253
254  void Directory::print_copyright(std::map<std::string, Alias>& alias, 
255                                  bool verbose) const {
256    if (!ignore()){
257      // print daughter nodes, i.e, this function is recursive
258      for (NodeConstIterator i = daughters_.begin(); i!=daughters_.end(); ++i)
259        (*i)->print_copyright(alias, verbose);
260    }
261  }
262
263}} // end of namespace svndigest and namespace theplu
Note: See TracBrowser for help on using the repository browser.