Fixed some behavior that got broken with the implementation of gravatars.

Previously, gitinspector always tried to merge authors with the same name
(independently of the email). This behavior tends to (for the most part)
help in projects missing a .mailmap file. Often; authors commit under the
same name, but with different emails on different computers (if they for
example have a work email on their office desktop).

Whenever different e-mail addresses are used by an author; gitinspector
will use the last email it finds and will generate a gravatar from that
email address. This behavior was chosen because authors mostly do not tend
to create a gravatar image for their old email accounts (but often have
one in their newer ones).
This commit is contained in:
Adam Waldenberg 2013-07-22 05:51:56 +02:00
parent 35852f9859
commit 662cd3fa63
3 changed files with 36 additions and 36 deletions

View File

@ -93,7 +93,7 @@ class Blame:
if FileDiff.is_valid_extension(row) and not filtering.set_filtered(FileDiff.get_filename(row)): if FileDiff.is_valid_extension(row) and not filtering.set_filtered(FileDiff.get_filename(row)):
if not missing.add(row): if not missing.add(row):
blame_string = "git blame -e -w {0} ".format("-C -C -M" if hard else "") + \ blame_string = "git blame -w {0} ".format("-C -C -M" if hard else "") + \
interval.get_since() + interval.get_ref() + " -- \"" + row + "\"" interval.get_since() + interval.get_ref() + " -- \"" + row + "\""
thread = BlameThread(blame_string, FileDiff.get_extension(row), self.blames, row.strip()) thread = BlameThread(blame_string, FileDiff.get_extension(row), self.blames, row.strip())
thread.daemon = True thread.daemon = True
@ -173,12 +173,12 @@ class BlameOutput(Outputable):
for i, entry in enumerate(blames): for i, entry in enumerate(blames):
work_percentage = str("{0:.2f}".format(100.0 * entry[1].rows / total_blames)) work_percentage = str("{0:.2f}".format(100.0 * entry[1].rows / total_blames))
authorname = self.changes.get_authorname_from_email(entry[0]) author_email = self.changes.get_author_email(entry[0])
blame_xml += "<tr " + ("class=\"odd\">" if i % 2 == 1 else ">") blame_xml += "<tr " + ("class=\"odd\">" if i % 2 == 1 else ">")
if format.get_selected() == "html": if format.get_selected() == "html":
blame_xml += "<td><img src=\"{0}\"/>{1}</td>".format(gravatar.get_url(entry[0]), authorname) blame_xml += "<td><img src=\"{0}\"/>{1}</td>".format(gravatar.get_url(author_email), entry[0])
else: else:
blame_xml += "<td>" + authorname + "</td>" blame_xml += "<td>" + authorname + "</td>"
@ -186,7 +186,7 @@ class BlameOutput(Outputable):
blame_xml += "<td>" + "{0:.2f}".format(100.0 * entry[1].comments / entry[1].rows) + "</td>" blame_xml += "<td>" + "{0:.2f}".format(100.0 * entry[1].comments / entry[1].rows) + "</td>"
blame_xml += "<td style=\"display: none\">" + work_percentage + "</td>" blame_xml += "<td style=\"display: none\">" + work_percentage + "</td>"
blame_xml += "</tr>" blame_xml += "</tr>"
chart_data += "{{label: \"{0}\", data: {1}}}".format(authorname, work_percentage) chart_data += "{{label: \"{0}\", data: {1}}}".format(entry[0], work_percentage)
if blames[-1] != entry: if blames[-1] != entry:
chart_data += ", " chart_data += ", "
@ -221,9 +221,9 @@ class BlameOutput(Outputable):
print(textwrap.fill(_(BLAME_INFO_TEXT) + ":", width=terminal.get_size()[0]) + "\n") print(textwrap.fill(_(BLAME_INFO_TEXT) + ":", width=terminal.get_size()[0]) + "\n")
terminal.printb(_("Author").ljust(21) + _("Rows").rjust(10) + _("% in comments").rjust(20)) terminal.printb(_("Author").ljust(21) + _("Rows").rjust(10) + _("% in comments").rjust(20))
for i in sorted(__blame__.get_summed_blames().items()): for i in sorted(__blame__.get_summed_blames().items()):
authorname = self.changes.get_authorname_from_email(i[0]) print(i[0].ljust(20)[0:20], end=" ")
print(authorname.ljust(20)[0:20], end=" ")
print(str(i[1].rows).rjust(10), end=" ") print(str(i[1].rows).rjust(10), end=" ")
print("{0:.2f}".format(100.0 * i[1].comments / i[1].rows).rjust(19)) print("{0:.2f}".format(100.0 * i[1].comments / i[1].rows).rjust(19))
@ -234,9 +234,10 @@ class BlameOutput(Outputable):
blame_xml = "" blame_xml = ""
for i in sorted(__blame__.get_summed_blames().items()): for i in sorted(__blame__.get_summed_blames().items()):
authorname = self.changes.get_authorname_from_email(i[0]) author_email = self.changes.get_author_email(i[0])
name_xml = "\t\t\t\t<name>" + authorname + "</name>\n"
gravatar_xml = "\t\t\t\t<gravatar>" + gravatar.get_url(i[0]) + "</gravatar>\n" name_xml = "\t\t\t\t<name>" + i[0] + "</name>\n"
gravatar_xml = "\t\t\t\t<gravatar>" + gravatar.get_url(author_email) + "</gravatar>\n"
rows_xml = "\t\t\t\t<rows>" + str(i[1].rows) + "</rows>\n" rows_xml = "\t\t\t\t<rows>" + str(i[1].rows) + "</rows>\n"
percentage_in_comments_xml = ("\t\t\t\t<percentage-in-comments>" + "{0:.2f}".format(100.0 * i[1].comments / i[1].rows) + percentage_in_comments_xml = ("\t\t\t\t<percentage-in-comments>" + "{0:.2f}".format(100.0 * i[1].comments / i[1].rows) +
"</percentage-in-comments>\n") "</percentage-in-comments>\n")

View File

@ -85,6 +85,7 @@ class Commit:
return string.split("|").__len__() == 4 return string.split("|").__len__() == 4
class AuthorInfo: class AuthorInfo:
email = None
insertions = 0 insertions = 0
deletions = 0 deletions = 0
commits = 0 commits = 0
@ -141,29 +142,28 @@ 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.email), i) Changes.__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.email), i) Changes.__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_authorname_from_email(self, email): def get_author_email(self, name):
if not self.authors: if not self.authors:
get_authorinfo_list(self) self.get_authorinfo_list()
for author in self.authors: return self.authors.get(name).email
if author[1] == email:
return author[0]
return "Unknown"
__changes__ = None __changes__ = None
@ -205,7 +205,7 @@ 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(entry[1]), entry[0]) changes_xml += "<td><img src=\"{0}\"/>{1}</td>".format(gravatar.get_url(authorinfo.email), entry)
else: else:
changes_xml += "<td>" + entry[0] + "</td>" changes_xml += "<td>" + entry[0] + "</td>"
@ -214,7 +214,7 @@ class ChangesOutput(Outputable):
changes_xml += "<td>" + str(authorinfo.deletions) + "</td>" changes_xml += "<td>" + str(authorinfo.deletions) + "</td>"
changes_xml += "<td>" + "{0:.2f}".format(percentage) + "</td>" changes_xml += "<td>" + "{0:.2f}".format(percentage) + "</td>"
changes_xml += "</tr>" changes_xml += "</tr>"
chart_data += "{{label: \"{0}\", data: {1}}}".format(entry[0], "{0:.2f}".format(percentage)) chart_data += "{{label: \"{0}\", data: {1}}}".format(entry, "{0:.2f}".format(percentage))
if sorted(authorinfo_list)[-1] != entry: if sorted(authorinfo_list)[-1] != entry:
chart_data += ", " chart_data += ", "
@ -283,8 +283,8 @@ class ChangesOutput(Outputable):
for i in sorted(authorinfo_list): for i in sorted(authorinfo_list):
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[0] + "</name>\n" name_xml = "\t\t\t\t<name>" + i + "</name>\n"
gravatar_xml = "\t\t\t\t<gravatar>" + gravatar.get_url(i[1]) + "</gravatar>\n" gravatar_xml = "\t\t\t\t<gravatar>" + gravatar.get_url(authorinfo.email) + "</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

@ -39,9 +39,9 @@ class TimelineData:
if useweeks: if useweeks:
yearweek = datetime.date(int(i[0][0][0:4]), int(i[0][0][5:7]), int(i[0][0][8:10])).isocalendar() yearweek = datetime.date(int(i[0][0][0:4]), int(i[0][0][5:7]), int(i[0][0][8:10])).isocalendar()
key = ((i[0][1], i[0][2]), str(yearweek[0]) + "W" + "{0:02d}".format(yearweek[1])) key = (i[0][1], str(yearweek[0]) + "W" + "{0:02d}".format(yearweek[1]))
else: else:
key = ((i[0][1], i[0][2]), i[0][0][0:7]) key = (i[0][1], i[0][0][0:7])
if self.entries.get(key, None) == None: if self.entries.get(key, None) == None:
self.entries[key] = i[1] self.entries[key] = i[1]
@ -54,7 +54,7 @@ class TimelineData:
total_deletions = 0 total_deletions = 0
for author in self.get_authors(): for author in self.get_authors():
entry = self.entries.get((author, period), None) entry = self.entries.get((author[0], period), None)
if entry != None: if entry != None:
total_insertions += entry.insertions total_insertions += entry.insertions
total_deletions += entry.deletions total_deletions += entry.deletions
@ -69,7 +69,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] for i in self.entries])) return sorted(set([(i[0][0], i[1].email) 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)
@ -118,13 +118,13 @@ def __output_row__text__(timeline_data, periods, names):
print(terminal.__normal__) print(terminal.__normal__)
for name in names: for name in names:
if timeline_data.is_author_in_periods(periods, name): if timeline_data.is_author_in_periods(periods, name[0]):
print(name[0].ljust(20)[0:20], end=" ") print(name[0].ljust(20)[0:20], end=" ")
for period in periods: for period in periods:
multiplier = timeline_data.get_multiplier(period, 9) multiplier = timeline_data.get_multiplier(period, 9)
signs = timeline_data.get_author_signs_in_period(name, period, multiplier) signs = timeline_data.get_author_signs_in_period(name[0], period, multiplier)
signs_str = (signs[1] * "-" + signs[0] * "+") signs_str = (signs[1] * "-" + signs[0] * "+")
print (("." if timeline_data.is_author_in_period(period, name) and print (("." if timeline_data.is_author_in_period(period, name[0]) and
len(signs_str) == 0 else signs_str).rjust(10), end=" ") len(signs_str) == 0 else signs_str).rjust(10), end=" ")
print("") print("")
@ -146,9 +146,8 @@ def __output_row__html__(timeline_data, periods, names):
i = 0 i = 0
for name in names: for name in names:
if timeline_data.is_author_in_periods(periods, name): if timeline_data.is_author_in_periods(periods, name[0]):
timeline_xml += "<tr" + (" class=\"odd\">" if i % 2 == 1 else ">") timeline_xml += "<tr" + (" class=\"odd\">" if i % 2 == 1 else ">")
#timeline_xml += "<td>" + name[0] + "</td>"
if format.get_selected() == "html": if format.get_selected() == "html":
timeline_xml += "<td><img src=\"{0}\"/>{1}</td>".format(gravatar.get_url(name[1]), name[0]) timeline_xml += "<td><img src=\"{0}\"/>{1}</td>".format(gravatar.get_url(name[1]), name[0])
@ -156,11 +155,11 @@ def __output_row__html__(timeline_data, periods, names):
timeline_xml += "<td>" + name[0] + "</td>" timeline_xml += "<td>" + name[0] + "</td>"
for period in periods: for period in periods:
multiplier = timeline_data.get_multiplier(period, 14) multiplier = timeline_data.get_multiplier(period, 18)
signs = timeline_data.get_author_signs_in_period(name, period, multiplier) signs = timeline_data.get_author_signs_in_period(name[0], period, multiplier)
signs_str = (signs[1] * "<div class=\"remove\">&nbsp;</div>" + signs[0] * "<div class=\"insert\">&nbsp;</div>") signs_str = (signs[1] * "<div class=\"remove\">&nbsp;</div>" + signs[0] * "<div class=\"insert\">&nbsp;</div>")
timeline_xml += "<td>" + ("." if timeline_data.is_author_in_period(period, name) and len(signs_str) == 0 else signs_str) timeline_xml += "<td>" + ("." if timeline_data.is_author_in_period(period, name[0]) and len(signs_str) == 0 else signs_str)
timeline_xml += "</td>" timeline_xml += "</td>"
timeline_xml += "</tr>" timeline_xml += "</tr>"
i = i + 1 i = i + 1
@ -225,9 +224,9 @@ class Timeline(Outputable):
authors_xml = "\t\t\t\t<authors>\n" authors_xml = "\t\t\t\t<authors>\n"
for name in names: for name in names:
if timeline_data.is_author_in_period(period, name): if timeline_data.is_author_in_period(period, name[0]):
multiplier = timeline_data.get_multiplier(period, 24) multiplier = timeline_data.get_multiplier(period, 24)
signs = timeline_data.get_author_signs_in_period(name, period, multiplier) signs = timeline_data.get_author_signs_in_period(name[0], period, multiplier)
signs_str = (signs[1] * "-" + signs[0] * "+") signs_str = (signs[1] * "-" + signs[0] * "+")
if len(signs_str) == 0: if len(signs_str) == 0: