source: trunk/lib/CopyrightVisitor.cc @ 1376

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

closes #385. implementing cache for svncopyright

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