|
|
@@ -451,6 +451,9 @@ class GitDataCollector(DataCollector):
|
|
451
|
451
|
self.total_lines = total_lines
|
|
452
|
452
|
|
|
453
|
453
|
# Per-author statistics
|
|
|
454
|
+ self.changes_by_date_by_author = {} # stamp -> author -> lines_added
|
|
|
455
|
+ # defined for stamp, author only if
|
|
|
456
|
+ # author commited at this timestamp.
|
|
454
|
457
|
# Similar to the above, but never use --first-parent
|
|
455
|
458
|
# (we need to walk through every commits to know who
|
|
456
|
459
|
# commited what, not just through mainline)
|
|
|
@@ -472,6 +475,9 @@ class GitDataCollector(DataCollector):
|
|
472
|
475
|
self.authors[author] = { 'lines_added' : 0, 'lines_removed' : 0 }
|
|
473
|
476
|
self.authors[author]['lines_added'] = self.authors[author].get('lines_added', 0) + inserted
|
|
474
|
477
|
self.authors[author]['lines_removed'] = self.authors[author].get('lines_removed', 0) + deleted
|
|
|
478
|
+ if stamp not in self.changes_by_date_by_author:
|
|
|
479
|
+ self.changes_by_date_by_author[stamp] = {}
|
|
|
480
|
+ self.changes_by_date_by_author[stamp][author] = self.authors[author]['lines_added']
|
|
475
|
481
|
files, inserted, deleted = 0, 0, 0
|
|
476
|
482
|
except ValueError:
|
|
477
|
483
|
print 'Warning: unexpected line "%s"' % line
|
|
|
@@ -842,6 +848,34 @@ class HTMLReportCreator(ReportCreator):
|
|
842
|
848
|
rest = allauthors[conf['max_authors']:]
|
|
843
|
849
|
f.write('<p class="moreauthors">These didn\'t make it to the top: %s</p>' % ', '.join(rest))
|
|
844
|
850
|
|
|
|
851
|
+ f.write(html_header(2, 'Cumulated Added Lines of Code per Author'))
|
|
|
852
|
+ f.write('<img src="lines_of_code_by_author.png" alt="Lines of code per Author" />')
|
|
|
853
|
+ if len(allauthors) > conf['max_authors']:
|
|
|
854
|
+ rest = allauthors[conf['max_authors']:]
|
|
|
855
|
+ f.write('<p class="moreauthors">These didn\'t make it to the graph: %s</p>' % ', '.join(rest))
|
|
|
856
|
+
|
|
|
857
|
+ fg = open(path + '/lines_of_code_by_author.dat', 'w')
|
|
|
858
|
+ lines_by_authors = {} # cumulated added lines by
|
|
|
859
|
+ # author. to save memory,
|
|
|
860
|
+ # changes_by_date_by_author[stamp][author] is defined
|
|
|
861
|
+ # only at points where author commits.
|
|
|
862
|
+ # lines_by_authors allows us to generate all the
|
|
|
863
|
+ # points in the .dat file.
|
|
|
864
|
+
|
|
|
865
|
+ # Don't rely on getAuthors to give the same order each
|
|
|
866
|
+ # time. Be robust and keep the list in a variable.
|
|
|
867
|
+ self.authors_to_plot = data.getAuthors(conf['max_authors'])
|
|
|
868
|
+ for author in self.authors_to_plot:
|
|
|
869
|
+ lines_by_authors[author] = 0
|
|
|
870
|
+ for stamp in sorted(data.changes_by_date_by_author.keys()):
|
|
|
871
|
+ fg.write('%d' % stamp)
|
|
|
872
|
+ for author in self.authors_to_plot:
|
|
|
873
|
+ if author in data.changes_by_date_by_author[stamp].keys():
|
|
|
874
|
+ lines_by_authors[author] = data.changes_by_date_by_author[stamp][author]
|
|
|
875
|
+ fg.write(' %d' % lines_by_authors[author])
|
|
|
876
|
+ fg.write('\n');
|
|
|
877
|
+ fg.close()
|
|
|
878
|
+
|
|
845
|
879
|
# Authors :: Author of Month
|
|
846
|
880
|
f.write(html_header(2, 'Author of Month'))
|
|
847
|
881
|
f.write('<table class="sortable" id="aom">')
|
|
|
@@ -1119,6 +1153,33 @@ plot 'lines_of_code.dat' using 1:2 w lines
|
|
1119
|
1153
|
""")
|
|
1120
|
1154
|
f.close()
|
|
1121
|
1155
|
|
|
|
1156
|
+ # Lines of Code Added per author
|
|
|
1157
|
+ f = open(path + '/lines_of_code_by_author.plot', 'w')
|
|
|
1158
|
+ f.write(GNUPLOT_COMMON)
|
|
|
1159
|
+ f.write(
|
|
|
1160
|
+"""
|
|
|
1161
|
+set terminal png transparent size 640,480
|
|
|
1162
|
+set output 'lines_of_code_by_author.png'
|
|
|
1163
|
+set key left top
|
|
|
1164
|
+set xdata time
|
|
|
1165
|
+set timefmt "%s"
|
|
|
1166
|
+set format x "%Y-%m-%d"
|
|
|
1167
|
+set grid y
|
|
|
1168
|
+set ylabel "Lines"
|
|
|
1169
|
+set xtics rotate
|
|
|
1170
|
+set bmargin 6
|
|
|
1171
|
+plot """
|
|
|
1172
|
+)
|
|
|
1173
|
+ i = 1
|
|
|
1174
|
+ plots = []
|
|
|
1175
|
+ for a in self.authors_to_plot:
|
|
|
1176
|
+ i = i + 1
|
|
|
1177
|
+ plots.append("""'lines_of_code_by_author.dat' using 1:%d title "%s" w lines""" % (i, a.replace("\"", "\\\"")))
|
|
|
1178
|
+ f.write(", ".join(plots))
|
|
|
1179
|
+ f.write('\n')
|
|
|
1180
|
+
|
|
|
1181
|
+ f.close()
|
|
|
1182
|
+
|
|
1122
|
1183
|
os.chdir(path)
|
|
1123
|
1184
|
files = glob.glob(path + '/*.plot')
|
|
1124
|
1185
|
for f in files:
|