Changed the way e-mail addresses are collected when analyzing the git log.

Previously, an email for a specific author was collected whenever some
insertions/deletions were detected in an active or valid extension. This
was introduced with the addition of gravatars.

This had the side-effect that if #author1 committed some rows to a file
with an inactive or non-valid extension and #author2 later moved some of
those rows into an active or valid extension, those rows could still
belong to #author1. Consequently, when associating the author name with
an email in the blame phase, there would not be any stored email for
#author1 and no email would be associated with that author or those blamed
lines.

Emails are now (instead) always stored and associated with an author
regardless of the work or files analyzed.
This commit is contained in:
Adam Waldenberg 2013-07-25 23:36:50 +02:00
parent 353f8daee1
commit 67418fa25d
2 changed files with 25 additions and 18 deletions

View file

@ -80,6 +80,13 @@ class Commit:
def get_filediffs(self): def get_filediffs(self):
return self.filediffs return self.filediffs
@staticmethod
def get_author_and_email(string):
commit_line = string.split("|")
if commit_line.__len__() == 4:
return (commit_line[2].strip(), commit_line[3].strip())
@staticmethod @staticmethod
def is_commit_line(string): def is_commit_line(string):
return string.split("|").__len__() == 4 return string.split("|").__len__() == 4
@ -93,6 +100,7 @@ class AuthorInfo:
class Changes: class Changes:
authors = {} authors = {}
authors_dateinfo = {} authors_dateinfo = {}
authors_email = {}
def __init__(self, hard): def __init__(self, hard):
self.commits = [] self.commits = []
@ -109,6 +117,10 @@ class Changes:
j = j.encode("latin-1", "replace") j = j.encode("latin-1", "replace")
j = j.decode("utf-8", "replace") j = j.decode("utf-8", "replace")
if Commit.is_commit_line(j):
(author, email) = Commit.get_author_and_email(j)
self.authors_email[author] = email
if Commit.is_commit_line(j) or i is lines[-1]: if Commit.is_commit_line(j) or i is lines[-1]:
if found_valid_extension: if found_valid_extension:
self.commits.append(commit) self.commits.append(commit)
@ -130,8 +142,7 @@ class Changes:
def get_commits(self): def get_commits(self):
return self.commits return self.commits
@staticmethod def __modify_authorinfo__(self, authors, key, commit):
def __modify_authorinfo__(authors, key, commit):
if authors.get(key, None) == None: if authors.get(key, None) == None:
authors[key] = AuthorInfo() authors[key] = AuthorInfo()
@ -142,28 +153,22 @@ class Changes:
authors[key].insertions += j.insertions authors[key].insertions += j.insertions
authors[key].deletions += j.deletions authors[key].deletions += j.deletions
authors[key].email = commit.email
def get_authorinfo_list(self): def get_authorinfo_list(self):
if not self.authors: if not self.authors:
for i in self.commits: for i in self.commits:
Changes.__modify_authorinfo__(self.authors, i.author, i) self.__modify_authorinfo__(self.authors, i.author, i)
return self.authors return self.authors
def get_authordateinfo_list(self): def get_authordateinfo_list(self):
if not self.authors_dateinfo: if not self.authors_dateinfo:
for i in self.commits: for i in self.commits:
Changes.__modify_authorinfo__(self.authors_dateinfo, (i.date, i.author), i) self.__modify_authorinfo__(self.authors_dateinfo, (i.date, i.author), i)
self.authors_dateinfo[(i.date, i.author)].email = self.get_authorinfo_list()[i.author].email
return self.authors_dateinfo return self.authors_dateinfo
def get_author_email(self, name): def get_author_email(self, name):
if not self.authors: return self.authors_email[name]
self.get_authorinfo_list()
return self.authors.get(name).email
__changes__ = None __changes__ = None
@ -179,11 +184,11 @@ NO_COMMITED_FILES_TEXT = N_("No commited files with the specified extensions wer
class ChangesOutput(Outputable): class ChangesOutput(Outputable):
def __init__(self, hard): def __init__(self, hard):
self.hard = hard self.changes = get(hard)
Outputable.__init__(self) Outputable.__init__(self)
def output_html(self): def output_html(self):
authorinfo_list = get(self.hard).get_authorinfo_list() authorinfo_list = self.changes.get_authorinfo_list()
total_changes = 0.0 total_changes = 0.0
changes_xml = "<div><div class=\"box\">" changes_xml = "<div><div class=\"box\">"
chart_data = "" chart_data = ""
@ -205,7 +210,8 @@ class ChangesOutput(Outputable):
changes_xml += "<tr " + ("class=\"odd\">" if i % 2 == 1 else ">") changes_xml += "<tr " + ("class=\"odd\">" if i % 2 == 1 else ">")
if format.get_selected() == "html": if format.get_selected() == "html":
changes_xml += "<td><img src=\"{0}\"/>{1}</td>".format(gravatar.get_url(authorinfo.email), entry) changes_xml += "<td><img src=\"{0}\"/>{1}</td>".format(
gravatar.get_url(self.changes.get_author_email(entry)), entry)
else: else:
changes_xml += "<td>" + entry + "</td>" changes_xml += "<td>" + entry + "</td>"
@ -244,7 +250,7 @@ class ChangesOutput(Outputable):
print(changes_xml) print(changes_xml)
def output_text(self): def output_text(self):
authorinfo_list = get(self.hard).get_authorinfo_list() authorinfo_list = self.changes.get_authorinfo_list()
total_changes = 0.0 total_changes = 0.0
for i in authorinfo_list: for i in authorinfo_list:
@ -269,7 +275,7 @@ class ChangesOutput(Outputable):
print(_(NO_COMMITED_FILES_TEXT) + ".") print(_(NO_COMMITED_FILES_TEXT) + ".")
def output_xml(self): def output_xml(self):
authorinfo_list = get(self.hard).get_authorinfo_list() authorinfo_list = self.changes.get_authorinfo_list()
total_changes = 0.0 total_changes = 0.0
for i in authorinfo_list: for i in authorinfo_list:
@ -284,7 +290,7 @@ class ChangesOutput(Outputable):
authorinfo = authorinfo_list.get(i) authorinfo = authorinfo_list.get(i)
percentage = 0 if total_changes == 0 else (authorinfo.insertions + authorinfo.deletions) / total_changes * 100 percentage = 0 if total_changes == 0 else (authorinfo.insertions + authorinfo.deletions) / total_changes * 100
name_xml = "\t\t\t\t<name>" + i + "</name>\n" name_xml = "\t\t\t\t<name>" + i + "</name>\n"
gravatar_xml = "\t\t\t\t<gravatar>" + gravatar.get_url(authorinfo.email) + "</gravatar>\n" gravatar_xml = "\t\t\t\t<gravatar>" + gravatar.get_url(self.changes.get_author_email(i)) + "</gravatar>\n"
commits_xml = "\t\t\t\t<commits>" + str(authorinfo.commits) + "</commits>\n" commits_xml = "\t\t\t\t<commits>" + str(authorinfo.commits) + "</commits>\n"
insertions_xml = "\t\t\t\t<insertions>" + str(authorinfo.insertions) + "</insertions>\n" insertions_xml = "\t\t\t\t<insertions>" + str(authorinfo.insertions) + "</insertions>\n"
deletions_xml = "\t\t\t\t<deletions>" + str(authorinfo.deletions) + "</deletions>\n" deletions_xml = "\t\t\t\t<deletions>" + str(authorinfo.deletions) + "</deletions>\n"

View file

@ -30,6 +30,7 @@ import textwrap
class TimelineData: class TimelineData:
def __init__(self, changes, useweeks): def __init__(self, changes, useweeks):
authordateinfo_list = sorted(changes.get_authordateinfo_list().items()) authordateinfo_list = sorted(changes.get_authordateinfo_list().items())
self.changes = changes
self.entries = {} self.entries = {}
self.total_changes_by_period = {} self.total_changes_by_period = {}
self.useweeks = useweeks self.useweeks = useweeks
@ -69,7 +70,7 @@ class TimelineData:
return self.total_changes_by_period[period] return self.total_changes_by_period[period]
def get_authors(self): def get_authors(self):
return sorted(set([(i[0][0], i[1].email) for i in self.entries.items()])) return sorted(set([(i[0][0], self.changes.get_author_email(i[0][0])) for i in self.entries.items()]))
def get_author_signs_in_period(self, author, period, multiplier): def get_author_signs_in_period(self, author, period, multiplier):
authorinfo = self.entries.get((author, period), None) authorinfo = self.entries.get((author, period), None)