lib/CopyrightVisitor.cc

Code
Comments
Other
Rev Date Author Line
1225 17 Oct 10 peter 1 // $Id$
1225 17 Oct 10 peter 2
1225 17 Oct 10 peter 3 /*
1635 30 Mar 23 peter 4   Copyright (C) 2010, 2011, 2012, 2023 Peter Johansson
1225 17 Oct 10 peter 5
1225 17 Oct 10 peter 6   This file is part of svndigest, http://dev.thep.lu.se/svndigest
1225 17 Oct 10 peter 7
1225 17 Oct 10 peter 8   svndigest is free software; you can redistribute it and/or modify it
1225 17 Oct 10 peter 9   under the terms of the GNU General Public License as published by
1225 17 Oct 10 peter 10   the Free Software Foundation; either version 3 of the License, or
1225 17 Oct 10 peter 11   (at your option) any later version.
1225 17 Oct 10 peter 12
1225 17 Oct 10 peter 13   svndigest is distributed in the hope that it will be useful, but
1225 17 Oct 10 peter 14   WITHOUT ANY WARRANTY; without even the implied warranty of
1225 17 Oct 10 peter 15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1225 17 Oct 10 peter 16   General Public License for more details.
1225 17 Oct 10 peter 17
1225 17 Oct 10 peter 18   You should have received a copy of the GNU General Public License
1225 17 Oct 10 peter 19   along with svndigest. If not, see <http://www.gnu.org/licenses/>.
1225 17 Oct 10 peter 20 */
1225 17 Oct 10 peter 21
1619 12 Mar 23 peter 22 #include <config.h>
1619 12 Mar 23 peter 23
1225 17 Oct 10 peter 24 #include "CopyrightVisitor.h"
1225 17 Oct 10 peter 25
1239 23 Oct 10 peter 26 #include "Configuration.h"
1358 31 May 11 peter 27 #include "CopyrightStats.h"
1225 17 Oct 10 peter 28 #include "Directory.h"
1225 17 Oct 10 peter 29 #include "File.h"
1225 17 Oct 10 peter 30 #include "NodeVisitor.h"
1321 28 Nov 10 peter 31 #include "utility.h"
1225 17 Oct 10 peter 32
1675 26 Aug 23 peter 33 #include <yat/utility/utility.h>
1675 26 Aug 23 peter 34
1437 20 Dec 11 peter 35 #include <cassert>
1321 28 Nov 10 peter 36 #include <fstream>
1321 28 Nov 10 peter 37
1225 17 Oct 10 peter 38 namespace theplu {
1225 17 Oct 10 peter 39 namespace svndigest {
1225 17 Oct 10 peter 40
1437 20 Dec 11 peter 41   CopyrightVisitor::CopyrightVisitor(std::map<std::string, Alias>& alias,
1225 17 Oct 10 peter 42                                      bool verbose,
1227 17 Oct 10 peter 43                                      const std::map<int,svn_revnum_t>& year2rev,
1227 17 Oct 10 peter 44                                      bool ignore_cache)
1227 17 Oct 10 peter 45     : NodeVisitor(), alias_(alias), verbose_(verbose), year2rev_(year2rev),
1227 17 Oct 10 peter 46       ignore_cache_(ignore_cache)
1225 17 Oct 10 peter 47   {}
1225 17 Oct 10 peter 48
1225 17 Oct 10 peter 49
1456 24 Dec 11 peter 50   void CopyrightVisitor::add(RevisionSet& a, const RevisionSet& b) const
1456 24 Dec 11 peter 51   {
1456 24 Dec 11 peter 52     for (RevisionSet::const_iterator i=b.begin(); i!=b.end(); ++i)
1456 24 Dec 11 peter 53       a.insert_merge(*i);
1456 24 Dec 11 peter 54   }
1456 24 Dec 11 peter 55
1456 24 Dec 11 peter 56
1437 20 Dec 11 peter 57   std::string
1239 23 Oct 10 peter 58   CopyrightVisitor::copyright_block(const std::map<int, std::set<Alias> >& year_authors,
1239 23 Oct 10 peter 59                                     const std::string& prefix) const
1239 23 Oct 10 peter 60   {
1239 23 Oct 10 peter 61     using namespace std;
1239 23 Oct 10 peter 62     stringstream ss;
1239 23 Oct 10 peter 63     for (map<int, set<Alias> >::const_iterator i(year_authors.begin());
1239 23 Oct 10 peter 64          i!=year_authors.end();) {
1239 23 Oct 10 peter 65       ss << prefix << Configuration::instance().copyright_string() << " "
1239 23 Oct 10 peter 66          << 1900+i->first;
1239 23 Oct 10 peter 67       map<int, set<Alias> >::const_iterator j = i;
1239 23 Oct 10 peter 68       assert(i!=year_authors.end());
1437 20 Dec 11 peter 69       while (++j!=year_authors.end() &&
1239 23 Oct 10 peter 70              i->second == j->second){
1239 23 Oct 10 peter 71         ss << ", " << 1900+(j->first);
1239 23 Oct 10 peter 72       }
1239 23 Oct 10 peter 73       // printing authors
1239 23 Oct 10 peter 74       std::vector<Alias> vec_alias;
1239 23 Oct 10 peter 75       back_insert_iterator<std::vector<Alias> > ii(vec_alias);
1239 23 Oct 10 peter 76       std::copy(i->second.begin(), i->second.end(), ii);
1239 23 Oct 10 peter 77       // sort with respect to id
1239 23 Oct 10 peter 78       std::sort(vec_alias.begin(), vec_alias.end(), IdCompare());
1239 23 Oct 10 peter 79       for (std::vector<Alias>::iterator a=vec_alias.begin();
1239 23 Oct 10 peter 80            a!=vec_alias.end(); ++a){
1239 23 Oct 10 peter 81         if (a!=vec_alias.begin())
1239 23 Oct 10 peter 82           ss << ",";
1239 23 Oct 10 peter 83         ss << " " << a->name();
1239 23 Oct 10 peter 84       }
1239 23 Oct 10 peter 85       ss << "\n";
1239 23 Oct 10 peter 86       i = j;
1239 23 Oct 10 peter 87     }
1239 23 Oct 10 peter 88     return ss.str();
1239 23 Oct 10 peter 89   }
1239 23 Oct 10 peter 90
1239 23 Oct 10 peter 91
1239 23 Oct 10 peter 92   bool CopyrightVisitor::detect_copyright(const std::string& path,
1437 20 Dec 11 peter 93                                           std::string& block,
1239 23 Oct 10 peter 94                                           size_t& start_at_line,
1437 20 Dec 11 peter 95                                           size_t& end_at_line,
1239 23 Oct 10 peter 96                                           std::string& prefix) const
1239 23 Oct 10 peter 97   {
1239 23 Oct 10 peter 98     using namespace std;
1239 23 Oct 10 peter 99     LineTypeParser parser(path);
1239 23 Oct 10 peter 100     std::ifstream is(path.c_str());
1239 23 Oct 10 peter 101     std::string line;
1437 20 Dec 11 peter 102     while (std::getline(is, line))
1239 23 Oct 10 peter 103       parser.parse(line);
1239 23 Oct 10 peter 104     if (!parser.copyright_found())
1239 23 Oct 10 peter 105       return false;
1239 23 Oct 10 peter 106     block = parser.block();
1239 23 Oct 10 peter 107     start_at_line = parser.start_line();
1239 23 Oct 10 peter 108     end_at_line = parser.end_line();
1239 23 Oct 10 peter 109     prefix = parser.prefix();
1239 23 Oct 10 peter 110     return true;
1239 23 Oct 10 peter 111   }
1239 23 Oct 10 peter 112
1239 23 Oct 10 peter 113
1437 20 Dec 11 peter 114   bool CopyrightVisitor::enter(Directory& dir)
1225 17 Oct 10 peter 115   {
1449 22 Dec 11 peter 116     if (dir.svncopyright_ignore())
1225 17 Oct 10 peter 117       return false;
1456 24 Dec 11 peter 118
1456 24 Dec 11 peter 119     RevisionSet ignore = dir.property().svncopyright_ignore_rev();
1456 24 Dec 11 peter 120
1675 26 Aug 23 peter 121     auto mother = path2ignore_.find(yat::utility::dirname(dir.path()));
1456 24 Dec 11 peter 122     if (mother!=path2ignore_.end())
1456 24 Dec 11 peter 123       add(ignore, mother->second);
1456 24 Dec 11 peter 124
1456 24 Dec 11 peter 125     if (!ignore.empty())
1456 24 Dec 11 peter 126       path2ignore_[dir.path()] = ignore;
1456 24 Dec 11 peter 127
1225 17 Oct 10 peter 128     return true;
1225 17 Oct 10 peter 129   }
1225 17 Oct 10 peter 130
1437 20 Dec 11 peter 131
1437 20 Dec 11 peter 132   void CopyrightVisitor::leave(Directory& dir)
1225 17 Oct 10 peter 133   {
1225 17 Oct 10 peter 134   }
1225 17 Oct 10 peter 135
1437 20 Dec 11 peter 136
1239 23 Oct 10 peter 137   void CopyrightVisitor::update_copyright(const File& file)
1239 23 Oct 10 peter 138   {
1239 23 Oct 10 peter 139     std::string old_block;
1239 23 Oct 10 peter 140     size_t start_line=0;
1239 23 Oct 10 peter 141     size_t end_line=0;
1239 23 Oct 10 peter 142     std::string prefix;
1239 23 Oct 10 peter 143     if (!detect_copyright(file.path(),old_block, start_line, end_line, prefix)){
1239 23 Oct 10 peter 144       if (Configuration::instance().missing_copyright_warning())
1459 09 Jan 12 peter 145         std::cerr << "svncopyright: warning: no copyright statement found in '"
1239 23 Oct 10 peter 146                   << file.path() << "'\n";
1239 23 Oct 10 peter 147       return;
1239 23 Oct 10 peter 148     }
1358 31 May 11 peter 149     if (verbose_)
1358 31 May 11 peter 150       std::cout << "Parsing '" << file.path() << "'\n";
1456 24 Dec 11 peter 151
1456 24 Dec 11 peter 152     RevisionSet ignore_revs = file.property().svncopyright_ignore_rev();
1456 24 Dec 11 peter 153
1675 26 Aug 23 peter 154     auto mother = path2ignore_.find(yat::utility::dirname(file.path()));
1456 24 Dec 11 peter 155     if (mother!=path2ignore_.end())
1456 24 Dec 11 peter 156       add(ignore_revs, mother->second);
1456 24 Dec 11 peter 157
1451 22 Dec 11 peter 158     CopyrightStats stats(file.path(), ignore_cache_, year2rev_, ignore_revs);
1457 24 Dec 11 peter 159     if (stats.map().empty())
1457 24 Dec 11 peter 160       return;
1376 14 Jun 11 peter 161     const std::map<int, std::set<std::string> >& year2users = stats.map();
1376 14 Jun 11 peter 162     assert(!year2users.empty());
1376 14 Jun 11 peter 163     std::map<int, std::set<Alias> > year2alias;
1376 14 Jun 11 peter 164     translate(year2users, year2alias);
1376 14 Jun 11 peter 165     std::string new_block = copyright_block(year2alias, prefix);
1239 23 Oct 10 peter 166     if (old_block==new_block)
1239 23 Oct 10 peter 167       return;
1239 23 Oct 10 peter 168     if (verbose_)
1437 20 Dec 11 peter 169       std::cout << "Updating copyright in '" << file.path() << "'" << std::endl;
1239 23 Oct 10 peter 170     update_copyright(file.path(), new_block, start_line, end_line);
1239 23 Oct 10 peter 171   }
1239 23 Oct 10 peter 172
1239 23 Oct 10 peter 173
1239 23 Oct 10 peter 174   void CopyrightVisitor::update_copyright(const std::string& path,
1239 23 Oct 10 peter 175                                           const std::string& new_block,
1437 20 Dec 11 peter 176                                           size_t start_at_line,
1239 23 Oct 10 peter 177                                           size_t end_at_line) const
1239 23 Oct 10 peter 178   {
1239 23 Oct 10 peter 179     // embrace filename with brackets #filename#
1675 26 Aug 23 peter 180     std::string tmpname =
1675 26 Aug 23 peter 181       concatenate_path(yat::utility::dirname(path),
1675 26 Aug 23 peter 182                        "#" + yat::utility::basename(path) + "#");
1239 23 Oct 10 peter 183     std::ofstream tmp(tmpname.c_str());
1239 23 Oct 10 peter 184     assert(tmp);
1239 23 Oct 10 peter 185     using namespace std;
1239 23 Oct 10 peter 186     ifstream is(path.c_str());
1239 23 Oct 10 peter 187     assert(is.good());
1239 23 Oct 10 peter 188     string line;
1239 23 Oct 10 peter 189     // Copy lines before block
1239 23 Oct 10 peter 190     for (size_t i=1; i<start_at_line; ++i){
1239 23 Oct 10 peter 191       assert(is.good());
1239 23 Oct 10 peter 192       getline(is, line);
1239 23 Oct 10 peter 193       tmp << line << "\n";
1239 23 Oct 10 peter 194     }
1239 23 Oct 10 peter 195     // Printing copyright statement
1239 23 Oct 10 peter 196     tmp << new_block;
1239 23 Oct 10 peter 197     // Ignore old block lines
1239 23 Oct 10 peter 198     for (size_t i=start_at_line; i<end_at_line; ++i){
1239 23 Oct 10 peter 199       assert(is.good());
1239 23 Oct 10 peter 200       getline(is, line);
1239 23 Oct 10 peter 201     }
1239 23 Oct 10 peter 202     // Copy lines after block
1239 23 Oct 10 peter 203     while(is.good()) {
1239 23 Oct 10 peter 204       char ch=is.get();
1239 23 Oct 10 peter 205       if (is.good())
1239 23 Oct 10 peter 206         tmp.put(ch);
1239 23 Oct 10 peter 207     }
1239 23 Oct 10 peter 208
1239 23 Oct 10 peter 209     is.close();
1239 23 Oct 10 peter 210     tmp.close();
1437 20 Dec 11 peter 211
1437 20 Dec 11 peter 212     // finally rename file
1392 12 Jul 11 peter 213     struct stat nodestat;
1392 12 Jul 11 peter 214     stat(path.c_str(), &nodestat);
1675 26 Aug 23 peter 215     yat::utility::rename(tmpname, path);
1675 26 Aug 23 peter 216     yat::utility::chmod(path, nodestat.st_mode);
1239 23 Oct 10 peter 217   }
1239 23 Oct 10 peter 218
1376 14 Jun 11 peter 219
1225 17 Oct 10 peter 220   void CopyrightVisitor::visit(File& file)
1225 17 Oct 10 peter 221   {
1449 22 Dec 11 peter 222     if (file.svncopyright_ignore())
1229 17 Oct 10 peter 223       return;
1239 23 Oct 10 peter 224     update_copyright(file);
1225 17 Oct 10 peter 225   }
1225 17 Oct 10 peter 226
1376 14 Jun 11 peter 227
1437 20 Dec 11 peter 228   void CopyrightVisitor::translate(const std::set<std::string>& users,
1376 14 Jun 11 peter 229                                    std::set<Alias>& aliases)
1376 14 Jun 11 peter 230   {
1437 20 Dec 11 peter 231     for (std::set<std::string>::const_iterator user=users.begin();
1376 14 Jun 11 peter 232          user!=users.end(); ++user) {
1376 14 Jun 11 peter 233       std::map<std::string, Alias>::const_iterator i = alias_.find(*user);
1376 14 Jun 11 peter 234       // if alias not found for author
1376 14 Jun 11 peter 235       if (i==alias_.end()) {
1459 09 Jan 12 peter 236         std::cerr << "svncopyright: warning: no copyright alias found for '"
1376 14 Jun 11 peter 237                   << *user << "'\n";
1376 14 Jun 11 peter 238         // insert alias to avoid multiple warnings.
1376 14 Jun 11 peter 239         Alias a(*user, alias_.size());
1376 14 Jun 11 peter 240         alias_[*user] = a;
1376 14 Jun 11 peter 241       }
1376 14 Jun 11 peter 242       else {
1376 14 Jun 11 peter 243         // FIXME: perhaps use hint
1376 14 Jun 11 peter 244         aliases.insert(i->second);
1376 14 Jun 11 peter 245       }
1376 14 Jun 11 peter 246     }
1376 14 Jun 11 peter 247   }
1376 14 Jun 11 peter 248
1376 14 Jun 11 peter 249
1437 20 Dec 11 peter 250   void
1437 20 Dec 11 peter 251   CopyrightVisitor::translate(const std::map<int, std::set<std::string> >& y2u,
1376 14 Jun 11 peter 252                               std::map<int, std::set<Alias> >& y2a)
1376 14 Jun 11 peter 253   {
1376 14 Jun 11 peter 254     using std::map;
1376 14 Jun 11 peter 255     using std::set;
1376 14 Jun 11 peter 256     using std::string;
1437 20 Dec 11 peter 257     for (map<int, set<string> >::const_iterator yu=y2u.begin();
1376 14 Jun 11 peter 258          yu!=y2u.end();++yu) {
1376 14 Jun 11 peter 259       set<Alias>& alias = y2a[yu->first];
1376 14 Jun 11 peter 260       translate(yu->second, alias);
1376 14 Jun 11 peter 261     }
1376 14 Jun 11 peter 262   }
1437 20 Dec 11 peter 263
1225 17 Oct 10 peter 264 }} // end of namespace svndigest and namespace theplu