mirror of
https://github.com/ejwa/gitinspector.git
synced 2025-01-03 11:22:15 +01:00
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:
parent
35852f9859
commit
662cd3fa63
3 changed files with 36 additions and 36 deletions
|
@ -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")
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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\"> </div>" + signs[0] * "<div class=\"insert\"> </div>")
|
signs_str = (signs[1] * "<div class=\"remove\"> </div>" + signs[0] * "<div class=\"insert\"> </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:
|
||||||
|
|
Loading…
Reference in a new issue