|
|
@@ -411,6 +411,8 @@ class GitDataCollector(DataCollector):
|
|
411
|
411
|
# N files changed, N insertions (+), N deletions(-)
|
|
412
|
412
|
# <stamp> <author>
|
|
413
|
413
|
self.changes_by_date = {} # stamp -> { files, ins, del }
|
|
|
414
|
+ # computation of lines of code by date is better done
|
|
|
415
|
+ # on a linear history.
|
|
414
|
416
|
extra = ''
|
|
415
|
417
|
if conf['linear_linestats']:
|
|
416
|
418
|
extra = '--first-parent -m'
|
|
|
@@ -429,10 +431,6 @@ class GitDataCollector(DataCollector):
|
|
429
|
431
|
try:
|
|
430
|
432
|
(stamp, author) = (int(line[:pos]), line[pos+1:])
|
|
431
|
433
|
self.changes_by_date[stamp] = { 'files': files, 'ins': inserted, 'del': deleted, 'lines': total_lines }
|
|
432
|
|
- if author not in self.authors:
|
|
433
|
|
- self.authors[author] = { 'lines_added' : 0, 'lines_removed' : 0 }
|
|
434
|
|
- self.authors[author]['lines_added'] = self.authors[author].get('lines_added', 0) + inserted
|
|
435
|
|
- self.authors[author]['lines_removed'] = self.authors[author].get('lines_removed', 0) + deleted
|
|
436
|
434
|
files, inserted, deleted = 0, 0, 0
|
|
437
|
435
|
except ValueError:
|
|
438
|
436
|
print 'Warning: unexpected line "%s"' % line
|
|
|
@@ -451,6 +449,41 @@ class GitDataCollector(DataCollector):
|
|
451
|
449
|
(files, inserted, deleted) = (0, 0, 0)
|
|
452
|
450
|
#self.changes_by_date[stamp] = { 'files': files, 'ins': inserted, 'del': deleted }
|
|
453
|
451
|
self.total_lines = total_lines
|
|
|
452
|
+
|
|
|
453
|
+ # Per-author statistics
|
|
|
454
|
+ # Similar to the above, but never use --first-parent
|
|
|
455
|
+ # (we need to walk through every commits to know who
|
|
|
456
|
+ # commited what, not just through mainline)
|
|
|
457
|
+ lines = getpipeoutput(['git log --shortstat --pretty=format:"%%at %%aN" %s' % (getcommitrange('HEAD'))]).split('\n')
|
|
|
458
|
+ lines.reverse()
|
|
|
459
|
+ files = 0; inserted = 0; deleted = 0;
|
|
|
460
|
+ author = None
|
|
|
461
|
+ for line in lines:
|
|
|
462
|
+ if len(line) == 0:
|
|
|
463
|
+ continue
|
|
|
464
|
+
|
|
|
465
|
+ # <stamp> <author>
|
|
|
466
|
+ if line.find('files changed,') == -1:
|
|
|
467
|
+ pos = line.find(' ')
|
|
|
468
|
+ if pos != -1:
|
|
|
469
|
+ try:
|
|
|
470
|
+ (stamp, author) = (int(line[:pos]), line[pos+1:])
|
|
|
471
|
+ if author not in self.authors:
|
|
|
472
|
+ self.authors[author] = { 'lines_added' : 0, 'lines_removed' : 0 }
|
|
|
473
|
+ self.authors[author]['lines_added'] = self.authors[author].get('lines_added', 0) + inserted
|
|
|
474
|
+ self.authors[author]['lines_removed'] = self.authors[author].get('lines_removed', 0) + deleted
|
|
|
475
|
+ files, inserted, deleted = 0, 0, 0
|
|
|
476
|
+ except ValueError:
|
|
|
477
|
+ print 'Warning: unexpected line "%s"' % line
|
|
|
478
|
+ else:
|
|
|
479
|
+ print 'Warning: unexpected line "%s"' % line
|
|
|
480
|
+ else:
|
|
|
481
|
+ numbers = re.findall('\d+', line)
|
|
|
482
|
+ if len(numbers) == 3:
|
|
|
483
|
+ (files, inserted, deleted) = map(lambda el : int(el), numbers)
|
|
|
484
|
+ else:
|
|
|
485
|
+ print 'Warning: failed to handle line "%s"' % line
|
|
|
486
|
+ (files, inserted, deleted) = (0, 0, 0)
|
|
454
|
487
|
|
|
455
|
488
|
def refine(self):
|
|
456
|
489
|
# authors
|