File size: 6,384 Bytes
90f0b29 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 |
#include <string>
#include <sstream>
#include <iostream>
#include <fstream>
#include <iomanip>
#include <map>
#include <list>
using namespace std;
// this function takes a line that may contain a name and/or email address,
// and returns just the name, while fixing the "bad cases".
std::string contributor_name(const std::string& line)
{
string result;
// let's first take care of the case of isolated email addresses, like
// "user@localhost.localdomain" entries
if(line.find("markb@localhost.localdomain") != string::npos)
{
return "Mark Borgerding";
}
if(line.find("kayhman@contact.intra.cea.fr") != string::npos)
{
return "Guillaume Saupin";
}
// from there on we assume that we have a entry of the form
// either:
// Bla bli Blurp
// or:
// Bla bli Blurp <bblurp@email.com>
size_t position_of_email_address = line.find_first_of('<');
if(position_of_email_address != string::npos)
{
// there is an e-mail address in <...>.
// Hauke once committed as "John Smith", fix that.
if(line.find("hauke.heibel") != string::npos)
result = "Hauke Heibel";
else
{
// just remove the e-mail address
result = line.substr(0, position_of_email_address);
}
}
else
{
// there is no e-mail address in <...>.
if(line.find("convert-repo") != string::npos)
result = "";
else
result = line;
}
// remove trailing spaces
size_t length = result.length();
while(length >= 1 && result[length-1] == ' ') result.erase(--length);
return result;
}
// parses hg churn output to generate a contributors map.
map<string,int> contributors_map_from_churn_output(const char *filename)
{
map<string,int> contributors_map;
string line;
ifstream churn_out;
churn_out.open(filename, ios::in);
while(!getline(churn_out,line).eof())
{
// remove the histograms "******" that hg churn may draw at the end of some lines
size_t first_star = line.find_first_of('*');
if(first_star != string::npos) line.erase(first_star);
// remove trailing spaces
size_t length = line.length();
while(length >= 1 && line[length-1] == ' ') line.erase(--length);
// now the last space indicates where the number starts
size_t last_space = line.find_last_of(' ');
// get the number (of changesets or of modified lines for each contributor)
int number;
istringstream(line.substr(last_space+1)) >> number;
// get the name of the contributor
line.erase(last_space);
string name = contributor_name(line);
map<string,int>::iterator it = contributors_map.find(name);
// if new contributor, insert
if(it == contributors_map.end())
contributors_map.insert(pair<string,int>(name, number));
// if duplicate, just add the number
else
it->second += number;
}
churn_out.close();
return contributors_map;
}
// find the last name, i.e. the last word.
// for "van den Schbling" types of last names, that's not a problem, that's actually what we want.
string lastname(const string& name)
{
size_t last_space = name.find_last_of(' ');
if(last_space >= name.length()-1) return name;
else return name.substr(last_space+1);
}
struct contributor
{
string name;
int changedlines;
int changesets;
string url;
string misc;
contributor() : changedlines(0), changesets(0) {}
bool operator < (const contributor& other)
{
return lastname(name).compare(lastname(other.name)) < 0;
}
};
void add_online_info_into_contributors_list(list<contributor>& contributors_list, const char *filename)
{
string line;
ifstream online_info;
online_info.open(filename, ios::in);
while(!getline(online_info,line).eof())
{
string hgname, realname, url, misc;
size_t last_bar = line.find_last_of('|');
if(last_bar == string::npos) continue;
if(last_bar < line.length())
misc = line.substr(last_bar+1);
line.erase(last_bar);
last_bar = line.find_last_of('|');
if(last_bar == string::npos) continue;
if(last_bar < line.length())
url = line.substr(last_bar+1);
line.erase(last_bar);
last_bar = line.find_last_of('|');
if(last_bar == string::npos) continue;
if(last_bar < line.length())
realname = line.substr(last_bar+1);
line.erase(last_bar);
hgname = line;
// remove the example line
if(hgname.find("MercurialName") != string::npos) continue;
list<contributor>::iterator it;
for(it=contributors_list.begin(); it != contributors_list.end() && it->name != hgname; ++it)
{}
if(it == contributors_list.end())
{
contributor c;
c.name = realname;
c.url = url;
c.misc = misc;
contributors_list.push_back(c);
}
else
{
it->name = realname;
it->url = url;
it->misc = misc;
}
}
}
int main()
{
// parse the hg churn output files
map<string,int> contributors_map_for_changedlines = contributors_map_from_churn_output("churn-changedlines.out");
//map<string,int> contributors_map_for_changesets = contributors_map_from_churn_output("churn-changesets.out");
// merge into the contributors list
list<contributor> contributors_list;
map<string,int>::iterator it;
for(it=contributors_map_for_changedlines.begin(); it != contributors_map_for_changedlines.end(); ++it)
{
contributor c;
c.name = it->first;
c.changedlines = it->second;
c.changesets = 0; //contributors_map_for_changesets.find(it->first)->second;
contributors_list.push_back(c);
}
add_online_info_into_contributors_list(contributors_list, "online-info.out");
contributors_list.sort();
cout << "{| cellpadding=\"5\"\n";
cout << "!\n";
cout << "! Lines changed\n";
cout << "!\n";
list<contributor>::iterator itc;
int i = 0;
for(itc=contributors_list.begin(); itc != contributors_list.end(); ++itc)
{
if(itc->name.length() == 0) continue;
if(i%2) cout << "|-\n";
else cout << "|- style=\"background:#FFFFD0\"\n";
if(itc->url.length())
cout << "| [" << itc->url << " " << itc->name << "]\n";
else
cout << "| " << itc->name << "\n";
if(itc->changedlines)
cout << "| " << itc->changedlines << "\n";
else
cout << "| (no information)\n";
cout << "| " << itc->misc << "\n";
i++;
}
cout << "|}" << endl;
}
|