source: trunk/lib/Directory.cc @ 235

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

added Date class
changed date format on first page
fixed plotting only once (fixes #113)
changed interface to anchor class
more anchors to users
removed anchor to '../' in author summary in dirs
anchors are filtered through HtmlStream?
log messages are truncated and newlines are replaced with spaces

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