source: trunk/lib/Stats.cc

Last change on this file was 1552, checked in by Peter Johansson, 9 years ago

remove some dead (out commented) code

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 10.6 KB
Line 
1// $Id: Stats.cc 1552 2012-11-04 05:55:37Z peter $
2
3/*
4  Copyright (C) 2005 Peter Johansson
5  Copyright (C) 2006, 2007, 2008, 2009 Jari Häkkinen, Peter Johansson
6  Copyright (C) 2010, 2011, 2012 Peter Johansson
7
8  This file is part of svndigest, http://dev.thep.lu.se/svndigest
9
10  svndigest is free software; you can redistribute it and/or modify it
11  under the terms of the GNU General Public License as published by
12  the Free Software Foundation; either version 3 of the License, or
13  (at your option) any later version.
14
15  svndigest is distributed in the hope that it will be useful, but
16  WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18  General Public License for more details.
19
20  You should have received a copy of the GNU General Public License
21  along with svndigest. If not, see <http://www.gnu.org/licenses/>.
22*/
23
24#include "Stats.h"
25
26#include "Colors.h"
27#include "Configuration.h"
28#include "Functor.h"
29#include "SVNblame.h"
30#include "SVNinfo.h"
31#include "utility.h"
32
33#include <algorithm>
34#include <cassert>
35#include <cstdlib>
36#include <fstream>
37#include <iostream>
38#include <iterator>
39#include <map>
40#include <numeric>
41#include <string>
42#include <sstream>
43#include <unistd.h>
44#include <utility>
45#include <vector>
46
47namespace theplu{
48namespace svndigest{
49
50
51  Stats::Stats(const std::string& path)
52    : stats_(std::vector<Author2Vector>(LineTypeParser::total+1)),
53      ignore_rev_(0)
54  {
55    // Make sure latest revision is set properly
56    SVNinfo svn_info(path);
57    revision_=svn_info.rev();
58    last_changed_rev_=svn_info.last_changed_rev();
59    reset();
60    config_code_ = Configuration::instance().code(path);
61  }
62
63
64  Stats::~Stats(void)
65  {
66  }
67
68
69  void Stats::add(const std::vector<std::map<std::string, SparseVector> >& data)
70  {
71    // loop over line types
72    for (size_t lt = 0; lt<data.size(); ++lt) {
73      std::map<std::string, SparseVector>::const_iterator iter=data[lt].begin();
74      std::map<std::string, SparseVector>::const_iterator last=data[lt].end();
75      // loop over users
76      for ( ; iter!=last; ++iter) {
77        add_author(iter->first);
78        SumVector tmpvec;
79        accumulate(iter->second, tmpvec);
80        stats_[lt][iter->first] += tmpvec;
81      }
82    }
83  }
84
85
86  void Stats::add_author(std::string name)
87  {
88    authors_.insert(name);
89  }
90
91
92  void Stats::add_authors(std::set<std::string>::const_iterator first,
93                          std::set<std::string>::const_iterator last)
94  {
95    authors_.insert(first, last);
96  }
97
98
99  const std::set<std::string>& Stats::authors(void) const
100  {
101    return authors_;
102  }
103
104
105  void Stats::calc_all(void)
106  {
107    for (int lt=0; lt <= 4; ++lt) {
108      stats_[lt]["all"].clear();
109      for (std::map<std::string, SumVector>::iterator i = stats_[lt].begin();
110           i!=stats_[lt].end(); ++i) {
111        stats_[lt]["all"] += i->second;
112      }
113    }
114
115    comment_or_copy_stats()["all"] = comment_stats()["all"];
116    comment_or_copy_stats()["all"] += copyright_stats()["all"];
117
118    total_stats()["all"] = comment_or_copy_stats()["all"];
119    total_stats()["all"] += code_stats()["all"];
120    total_stats()["all"] += other_stats()["all"];
121  }
122
123
124  void Stats::calc_total(void)
125  {
126    for (std::set<std::string>::const_iterator iter(authors().begin());
127         iter!=authors().end(); ++iter) {
128      SumVector& total = total_stats()[*iter];
129      total = code_stats()[*iter];
130      total += comment_stats()[*iter];
131      total += other_stats()[*iter];
132      total += copyright_stats()[*iter];
133    }
134  }
135
136
137  void Stats::calc_comment_or_copy(void)
138  {
139    for (std::set<std::string>::const_iterator iter(authors().begin());
140         iter!=authors().end(); ++iter) {
141      const SumVector& comments = comment_stats()[*iter];
142      const SumVector& copy = copyright_stats()[*iter];
143
144      comment_or_copy_stats()[*iter] = comments;
145      comment_or_copy_stats()[*iter] += copy;
146    }
147
148  }
149
150
151  unsigned int Stats::code(const std::string& user) const
152  {
153    return get_back(code_stats(), user);
154  }
155
156
157  unsigned int Stats::comments(const std::string& user) const
158  {
159    return get_back(comment_or_copy_stats(), user);
160  }
161
162
163  std::string Stats::config_code(void) const
164  {
165    if (ignore_rev_==0)
166      return config_code_;
167    std::stringstream result(config_code_);
168    result << "ir" << ignore_rev_;
169    return result.str();
170  }
171
172
173  unsigned int Stats::empty(const std::string& user) const
174  {
175    return get_back(other_stats(), user);
176  }
177
178
179  unsigned int Stats::get_back(const Author2Vector& m, std::string user) const
180  {
181    A2VConstIter iter(m.find(std::string(user)));
182    if (iter==m.end() || iter->second.empty())
183      return 0;
184    assert(iter->second.size());
185    return iter->second.back();
186  }
187
188
189  const SumVector& Stats::get_vector(const Author2Vector& m,
190                                     const std::string& user) const
191  {
192    A2VConstIter iter(m.find(std::string(user)));
193    if (iter==m.end())
194      throw std::runtime_error(user+std::string(" not found i Stats"));
195    return iter->second;
196  }
197
198
199  void Stats::ignore_rev(svn_revnum_t rev)
200  {
201    ignore_rev_ = rev;
202  }
203
204
205  const svn_revnum_t& Stats::ignore_rev(void) const
206  {
207    return ignore_rev_;
208  }
209
210
211  svn_revnum_t Stats::last_changed_rev(void) const
212  {
213    return last_changed_rev_;
214  }
215
216
217  unsigned int Stats::lines(const std::string& user) const
218  {
219    return get_back(total_stats(), user);
220  }
221
222
223  void Stats::load(std::istream& is, Author2Vector& m)
224  {
225    while (m.size() < authors().size()+1 && is.good()) {
226      std::string name;
227      std::getline(is, name);
228      SparseVector vec;
229      std::string line;
230      std::getline(is, line);
231      std::stringstream ss(line);
232      while (ss.good()) {
233        svn_revnum_t rev=0;
234        unsigned int count=0;
235        ss >> rev;
236        ss >> count;
237        assert(rev<=revision_);
238        if (!count)
239          break;
240        vec.set(rev, count);
241      }
242      SumVector& sumvec = m[name];
243      accumulate(vec, sumvec);
244    }
245  }
246
247
248  svn_revnum_t Stats::load_cache(std::istream& is, bool& latest_ver)
249  {
250    std::string str;
251    getline(is, str);
252    if (str == "CACHE FILE VERSION 8") {
253      latest_ver = true;
254      return load_cache8(is);
255    }
256    latest_ver = false;
257    if (str == "CACHE FILE VERSION 7")
258      return load_cache7(is);
259
260    if (str == "CACHE FILE VERSION 6")
261      std::cout << "cache file is obsolete; "
262                << "retrieving statistics from repository.\n";
263    return 0;
264  }
265
266
267  svn_revnum_t Stats::load_cache8(std::istream& is)
268  {
269    std::string line;
270    getline(is, line);
271    if (line!=config_code()) {
272      std::cout << "cache file is for different configuration.\n"
273                << "config code: '" << config_code() << "'\n"
274                << "config code in cache file: '" << line << "'\n"
275                << "retrieving statistics from repository.\n";
276      return 0;
277    }
278    return load_cache7(is);
279  }
280
281
282  svn_revnum_t Stats::load_cache7(std::istream& is)
283  {
284    svn_revnum_t rev;
285    is >> rev;
286    reset();
287    size_t a_size=0;
288    is >> a_size;
289    std::string str;
290    while (authors().size()<a_size && is.good()){
291      getline(is, str);
292      if (str.size())
293        add_author(str);
294    }
295    getline(is, str);
296    if (str!=cache_check_str()) {
297      return 0;
298    }
299    for (size_t i=0; i<stats_.size(); ++i){
300      load(is, stats_[i]);
301      getline(is, str);
302      if (str!=cache_check_str()) {
303        return 0;
304      }
305    }
306    return rev;
307  }
308
309
310  void Stats::map_add(A2VConstIter first1, A2VConstIter last1,
311                      Author2Vector& map)
312  {
313    A2VIter first2(map.begin());
314    Author2Vector::key_compare compare;
315    while ( first1 != last1) {
316      // key of first1 less than key of first2
317      if (first2==map.end() || compare(first1->first,first2->first)) {
318        first2 = map.insert(first2, *first1);
319        ++first1;
320      }
321      // key of first2 less than key of first1
322      else if ( compare(first2->first, first1->first)) {
323        ++first2;
324      }
325      // keys are equivalent
326      else {
327        first2->second += first1->second;
328        ++first1;
329        ++first2;
330      }
331    }
332  }
333
334
335  unsigned int Stats::max_element(const SumVector& vec) const
336  {
337    return std::max_element(vec.begin(), vec.end(),
338       pair_value_compare<const svn_revnum_t, unsigned int>())->second;
339  }
340
341
342  void Stats::parse(const std::string& path, svn_revnum_t rev)
343  {
344    do_parse(path, rev);
345    calc_comment_or_copy();
346    calc_total();
347    calc_all();
348
349    assert(total_stats().size());
350    assert(code_stats().size());
351    assert(comment_or_copy_stats().size());
352    assert(other_stats().size());
353  }
354
355
356  void Stats::print(std::ostream& os) const
357  {
358    // indicate that cache file is version 8 here , but keep remaning
359    // 'CACHE FILE VERSION' as 'VERSION 7' to allow load_cache7() to
360    // be used from load_cache8().
361    os << "CACHE FILE VERSION 8\n";
362    os << config_code() << "\n";
363    os << last_changed_rev() << " ";
364    os << authors().size() << "\n";
365
366    std::copy(authors().begin(), authors().end(),
367              std::ostream_iterator<std::string>(os, "\n"));
368    os << cache_check_str() << "\n";
369    for (size_t i=0; i<stats_.size(); ++i){
370      print(os, stats_[i]);
371      os << cache_check_str() << "\n";
372    }
373  }
374
375
376  void Stats::print(std::ostream& os, const Author2Vector& m) const
377  {
378    for (A2VConstIter i(m.begin()); i!=m.end(); ++i){
379      os << i->first << "\n";
380      const SumVector& vec = i->second;
381      if (vec.size()) {
382        SumVector::const_iterator v = vec.begin();
383        if (v->second)
384          os << v->first << " " << v->second << " ";
385        ++v;
386        SumVector::const_iterator prev = vec.begin();
387        while (v != vec.end()) {
388          assert(vec[v->first - 1] == prev->second);
389          // FIXME: this if should not be needed if SumVector was
390          // truly sparse and collapsed when possible.
391          if (v->second != prev->second)
392            os << v->first << " " << v->second - prev->second << " ";
393          ++v;
394          ++prev;
395        }
396      }
397      os << "\n";
398    }
399  }
400
401  void Stats::reset(void)
402  {
403    for (size_t i=0; i<stats_.size(); ++i){
404      stats_[i].clear();
405      stats_[i]["all"].resize(revision()+1);
406    }
407    authors_.clear();
408  }
409
410
411  void Stats::resize(svn_revnum_t rev)
412  {
413    // set size on vectors
414    for (size_t i=0; i<stats_.size(); ++i) {
415      for (A2VIter iter=stats_[i].begin(); iter!=stats_[i].end(); ++iter) {
416        iter->second.resize(rev);
417      }
418    }
419  }
420
421
422  svn_revnum_t Stats::revision(void) const
423  {
424    return revision_;
425  }
426
427
428  Stats& Stats::operator+=(const Stats& rhs)
429  {
430    revision_ = std::max(revision_, rhs.revision_);
431    last_changed_rev_ = std::max(last_changed_rev_, rhs.last_changed_rev_);
432    add_authors(rhs.authors().begin(), rhs.authors().end());
433    assert(stats_.size()==rhs.stats_.size());
434    for (size_t i=0; i<stats_.size(); ++i)
435      map_add(rhs.stats_[i].begin(), rhs.stats_[i].end(), stats_[i]);
436
437    return *this;
438  }
439
440
441  size_t Stats::operator()(int linetype, std::string author,
442                           svn_revnum_t rev) const
443  {
444    assert(linetype<=LineTypeParser::total);
445    assert(static_cast<size_t>(linetype) < stats_.size());
446    assert(rev>=0);
447    A2VConstIter i = stats_[linetype].find(author);
448    if (i==stats_[linetype].end()){
449      std::stringstream msg;
450      msg << __FILE__ << ": author: " << author << " does not exist";
451      throw std::runtime_error(msg.str());
452    }
453    assert(rev <= revision());
454    //    assert(rev < static_cast<svn_revnum_t>(i->second.size()));
455    return i->second[rev];
456  }
457
458}} // end of namespace svndigest and namespace theplu
Note: See TracBrowser for help on using the repository browser.