source: trunk/lib/CopyrightVisitor.cc @ 1321

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

updating includes

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 6.9 KB
Line 
1// $Id: CopyrightVisitor.cc 1321 2010-11-28 23:41:31Z peter $
2
3/*
4  Copyright (C) 2010 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 "CopyrightVisitor.h"
23
24#include "Configuration.h"
25#include "Directory.h"
26#include "File.h"
27#include "NodeVisitor.h"
28#include "utility.h"
29
30#include <fstream>
31
32namespace theplu {
33namespace svndigest {
34
35  CopyrightVisitor::CopyrightVisitor(std::map<std::string, Alias>& alias, 
36                                     bool verbose,
37                                     const std::map<int,svn_revnum_t>& year2rev,
38                                     bool ignore_cache)
39    : NodeVisitor(), alias_(alias), verbose_(verbose), year2rev_(year2rev),
40      ignore_cache_(ignore_cache)
41  {}
42
43
44  std::string
45  CopyrightVisitor::copyright_block(const std::map<int, std::set<Alias> >& year_authors,
46                                    const std::string& prefix) const
47  {
48    using namespace std;
49    stringstream ss;
50    for (map<int, set<Alias> >::const_iterator i(year_authors.begin());
51         i!=year_authors.end();) {
52      ss << prefix << Configuration::instance().copyright_string() << " "
53         << 1900+i->first;
54      map<int, set<Alias> >::const_iterator j = i;
55      assert(i!=year_authors.end());
56      while (++j!=year_authors.end() && 
57             i->second == j->second){
58        ss << ", " << 1900+(j->first);
59      }
60      // printing authors
61      std::vector<Alias> vec_alias;
62      back_insert_iterator<std::vector<Alias> > ii(vec_alias);
63      std::copy(i->second.begin(), i->second.end(), ii);
64      // sort with respect to id
65      std::sort(vec_alias.begin(), vec_alias.end(), IdCompare());
66      for (std::vector<Alias>::iterator a=vec_alias.begin();
67           a!=vec_alias.end(); ++a){
68        if (a!=vec_alias.begin())
69          ss << ",";
70        ss << " " << a->name();
71      }
72      ss << "\n";
73      i = j;
74    }
75    return ss.str();
76  }
77
78
79  void CopyrightVisitor::create_year2alias(std::map<int, std::set<Alias> >& m,
80                                           const File& file)
81  {
82    using namespace std;
83    const Stats& stats = file.stats()["add"];
84
85    // loop over all years
86    for (std::map<int, svn_revnum_t>::const_iterator rev_iter=year2rev_.begin();
87         rev_iter!=year2rev_.end(); ++rev_iter) {
88
89      svn_revnum_t last_rev_this_year = rev_iter->second;
90      svn_revnum_t last_rev_last_year = 0;
91      if (rev_iter != year2rev_.begin()) {
92        last_rev_last_year = (--rev_iter)->second;
93        ++rev_iter;
94      }
95      // do not go beyond BASE rev of file
96      last_rev_this_year = std::min(last_rev_this_year,file.last_changed_rev());
97      last_rev_last_year = std::min(last_rev_last_year,file.last_changed_rev());
98      // loop over authors
99      for (std::set<std::string>::const_iterator a_iter=stats.authors().begin();
100           a_iter!=stats.authors().end(); ++a_iter) {
101
102        // check if anything has been added since last year
103        if ( (stats(LineTypeParser::code, *a_iter, last_rev_this_year) >
104              stats(LineTypeParser::code, *a_iter, last_rev_last_year)) || 
105             (stats(LineTypeParser::comment, *a_iter, last_rev_this_year) >
106              stats(LineTypeParser::comment, *a_iter, last_rev_last_year)) ) {
107       
108       
109          // find username in map of aliases
110          std::map<string,Alias>::iterator name(alias_.lower_bound(*a_iter));
111         
112          // if alias exist insert alias
113          if (name != alias_.end() && name->first==*a_iter)
114            m[rev_iter->first].insert(name->second);
115          else {
116            // else insert user name
117            Alias a(*a_iter,alias_.size());
118            m[rev_iter->first].insert(a);
119            std::cerr << "svncopyright: warning: no copyright alias found for `" 
120                      << *a_iter << "'\n";
121            // insert alias to avoid multiple warnings.
122            alias_.insert(name, std::make_pair(*a_iter, a));
123          }
124        }
125      }
126    }
127  }
128
129
130  bool CopyrightVisitor::detect_copyright(const std::string& path,
131                                          std::string& block, 
132                                          size_t& start_at_line,
133                                          size_t& end_at_line, 
134                                          std::string& prefix) const
135  {
136    using namespace std;
137    LineTypeParser parser(path);
138    std::ifstream is(path.c_str());
139    std::string line;
140    while (std::getline(is, line)) 
141      parser.parse(line);
142    if (!parser.copyright_found())
143      return false;
144    block = parser.block();
145    start_at_line = parser.start_line();
146    end_at_line = parser.end_line();
147    prefix = parser.prefix();
148    return true;
149  }
150
151
152  bool CopyrightVisitor::enter(Directory& dir) 
153  {
154    if (dir.ignore() || dir.svncopyright_ignore())
155      return false;
156    return true;
157  }
158 
159
160  void CopyrightVisitor::leave(Directory& dir) 
161  {
162  }
163 
164
165  void CopyrightVisitor::update_copyright(const File& file)
166  {
167    std::string old_block;
168    size_t start_line=0;
169    size_t end_line=0;
170    std::string prefix;
171    if (!detect_copyright(file.path(),old_block, start_line, end_line, prefix)){
172      if (Configuration::instance().missing_copyright_warning())
173        std::cerr << "svncopyright: warning: no copyright statement found in `" 
174                  << file.path() << "'\n";
175      return;
176    }
177    std::map<int, std::set<Alias> > map;
178    create_year2alias(map, file);
179    std::string new_block = copyright_block(map, prefix);
180    if (old_block==new_block)
181      return;
182    if (verbose_)
183      std::cout << "Updating copyright in '" << file.path() << "'" << std::endl; 
184    update_copyright(file.path(), new_block, start_line, end_line);
185  }
186
187
188  void CopyrightVisitor::update_copyright(const std::string& path,
189                                          const std::string& new_block,
190                                          size_t start_at_line, 
191                                          size_t end_at_line) const
192  {
193    // embrace filename with brackets #filename#
194    std::string tmpname = concatenate_path(directory_name(path),
195                                           "#" + file_name(path) + "#");
196    std::ofstream tmp(tmpname.c_str());
197    assert(tmp);
198    using namespace std;
199    ifstream is(path.c_str());
200    assert(is.good());
201    string line;
202    // Copy lines before block
203    for (size_t i=1; i<start_at_line; ++i){
204      assert(is.good());
205      getline(is, line);
206      tmp << line << "\n";
207    }
208    // Printing copyright statement
209    tmp << new_block;
210    // Ignore old block lines
211    for (size_t i=start_at_line; i<end_at_line; ++i){
212      assert(is.good());
213      getline(is, line);
214    }
215    // Copy lines after block
216    while(is.good()) {
217      char ch=is.get();
218      if (is.good())
219        tmp.put(ch);
220    }
221
222    is.close();
223    tmp.close();
224   
225    // finally rename file
226    rename(tmpname, path);
227  }
228
229  void CopyrightVisitor::visit(File& file)
230  {
231    if (file.ignore() || file.svncopyright_ignore())
232      return;
233    file.parse(verbose_, ignore_cache_);
234    update_copyright(file);
235    file.stats().reset();
236  }
237
238}} // end of namespace svndigest and namespace theplu
Note: See TracBrowser for help on using the repository browser.