Now also outputs the percentage of comments by each author.

Currently supports comments for the extensions; java, c, cpp, h, hpp, py, glsl,
rb, js, sql and xml.
This commit is contained in:
Adam Waldenberg 2012-05-09 12:14:25 +02:00
parent cf261728be
commit c964bf14d3
2 changed files with 71 additions and 4 deletions

View File

@ -18,11 +18,16 @@
# along with gitinspector. If not, see <http://www.gnu.org/licenses/>. # along with gitinspector. If not, see <http://www.gnu.org/licenses/>.
from changes import FileDiff from changes import FileDiff
import comment
import missing import missing
import re import re
import sysrun import sysrun
import terminal import terminal
class BlameEntry:
rows = 0
comments = 0
class Blame: class Blame:
def __init__(self, repo, hard): def __init__(self, repo, hard):
self.blames = {} self.blames = {}
@ -33,15 +38,26 @@ class Blame:
if not missing.add(repo, i.strip()): if not missing.add(repo, i.strip()):
git_blame_r = sysrun.run(repo, "git blame -w {0} \"".format("-C -M" if hard else "") + git_blame_r = sysrun.run(repo, "git blame -w {0} \"".format("-C -M" if hard else "") +
i.strip() + "\"") i.strip() + "\"")
is_inside_comment = False
for j in git_blame_r.readlines(): for j in git_blame_r.readlines():
if Blame.is_blame_line(j): if Blame.is_blame_line(j):
author = Blame.get_author(j) author = Blame.get_author(j)
content = Blame.get_content(j)
if self.blames.get(author, None) == None: if self.blames.get(author, None) == None:
self.blames[author] = 0 self.blames[author] = BlameEntry()
self.blames[author] += 1 if comment.is_comment_begining(FileDiff.get_extension(i), content):
is_inside_comment = True
if comment.is_comment(FileDiff.get_extension(i), content) or is_inside_comment:
self.blames[author].comments += 1
if comment.is_comment_end(FileDiff.get_extension(i), content):
is_inside_comment = False
self.blames[author].rows += 1
@staticmethod @staticmethod
def is_blame_line(string): def is_blame_line(string):
@ -52,12 +68,18 @@ class Blame:
author = re.search(" \((.*?)\d\d\d\d-\d\d-\d\d", string) author = re.search(" \((.*?)\d\d\d\d-\d\d-\d\d", string)
return re.sub("[^\w ]", "", author.group(1)).strip() return re.sub("[^\w ]", "", author.group(1)).strip()
@staticmethod
def get_content(string):
content = re.search(" \d+\)(.*)", string)
return content.group(1).lstrip()
def output(repo, hard): def output(repo, hard):
blame = Blame(repo, hard) blame = Blame(repo, hard)
print "\nBelow is the number of rows from each author that have survived and" print "\nBelow is the number of rows from each author that have survived and"
print "are still intact in the current revision:\n" print "are still intact in the current revision:\n"
terminal.printb("Author".ljust(21) + " Rows") terminal.printb("Author".ljust(21) + "Rows".rjust(10) + "% in comments".rjust(16))
for i in sorted(blame.blames.items()): for i in sorted(blame.blames.items()):
print i[0].ljust(20)[0:20], print i[0].ljust(20)[0:20],
print str(i[1]).rjust(10) print str(i[1].rows).rjust(10),
print "{0:.2f}".format(100.0 * i[1].comments / i[1].rows).rjust(15)

45
comment.py Normal file
View File

@ -0,0 +1,45 @@
# coding: utf-8
#
# Copyright © 2012 Ejwa Software. All rights reserved.
#
# This file is part of gitinspector.
#
# gitinspector is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# gitinspector is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with gitinspector. If not, see <http://www.gnu.org/licenses/>.
__comment_begining__ = {"java": "/*", "c": "/*", "cpp": "/*", "h": "/*", "hpp": "/*", "py": "\"\"\"", "glsl": "/*",
"rb": "=begin", "js": "/*", "sql": "/*", "xml": "<!--"}
__comment_end__ = {"java": "*/", "c": "*/", "cpp": "*/", "h": "*/", "hpp": "*/", "py": "\"\"\"", "glsl": "*/",
"rb": "=end", "js": "*/", "sql": "*/", "xml": "-->"}
__comment__ = {"java": "//", "c": "//", "cpp": "//", "h": "//", "hpp": "//", "py": "#", "glsl": "//",
"rb": "#", "js": "//", "sql": "--"}
def is_comment_begining(extension, string):
if __comment_begining__.get(extension, None) != None:
return string.strip().startswith(__comment_begining__[extension])
else:
return False
def is_comment_end(extension, string):
if __comment_end__.get(extension, None) != None:
return string.strip().endswith(__comment_end__[extension])
else:
return False
def is_comment(extension, string):
if __comment__.get(extension, None) != None:
return string.strip().startswith(__comment__[extension])
else:
return False