diff --git a/gitinspector/blame.py b/gitinspector/blame.py
index abeab1a..902bb03 100644
--- a/gitinspector/blame.py
+++ b/gitinspector/blame.py
@@ -148,6 +148,17 @@ class Blame(object):
for i in range(0, NUM_THREADS):
__thread_lock__.acquire()
+ # We also have to release them for future use.
+ for i in range(0, NUM_THREADS):
+ __thread_lock__.release()
+
+ def __add__(self, other):
+ if other == None:
+ return self
+
+ self.blames.update(other.blames)
+ return self
+
@staticmethod
def is_revision(string):
revision = re.search("([0-9a-f]{40})", string)
@@ -180,12 +191,3 @@ class Blame(object):
summed_blames[i[0][0]].comments += i[1].comments
return summed_blames
-
-__blame__ = None
-
-def get(hard, useweeks, changes):
- global __blame__
- if __blame__ == None:
- __blame__ = Blame(hard, useweeks, changes)
-
- return __blame__
diff --git a/gitinspector/gitinspector.py b/gitinspector/gitinspector.py
index e7ddf17..e9ad743 100644
--- a/gitinspector/gitinspector.py
+++ b/gitinspector/gitinspector.py
@@ -23,6 +23,7 @@ import atexit
import getopt
import os
import sys
+from .blame import Blame
from .changes import Changes
from .config import GitConfig
from . import (basedir, clone, extensions, filtering, format, help, interval,
@@ -58,13 +59,16 @@ class Runner(object):
terminal.skip_escapes(not sys.stdout.isatty())
terminal.set_stdout_encoding()
previous_directory = os.getcwd()
- changes = None
+ summed_blames = None
+ summed_changes = None
for repo in repos:
os.chdir(previous_directory)
os.chdir(repo)
absolute_path = basedir.get_basedir_git()
- changes = Changes(self.hard) + changes
+ changes = Changes(self.hard)
+ summed_blames = Blame(self.hard, self.useweeks, changes) + summed_blames
+ summed_changes = changes + summed_changes
if sys.stdout.isatty() and format.is_interactive_format():
terminal.clear_row()
@@ -75,16 +79,16 @@ class Runner(object):
outputable.output(ChangesOutput(changes))
if changes.get_commits():
- outputable.output(BlameOutput(changes, self.hard, self.useweeks))
+ outputable.output(BlameOutput(summed_changes, summed_blames))
if self.timeline:
- outputable.output(TimelineOutput(changes, self.useweeks))
+ outputable.output(TimelineOutput(summed_changes, self.useweeks))
if self.include_metrics:
outputable.output(MetricsOutput())
if self.responsibilities:
- outputable.output(ResponsibilitiesOutput(changes, self.hard, self.useweeks))
+ outputable.output(ResponsibilitiesOutput(summed_changes, summed_blames))
outputable.output(FilteringOutput())
diff --git a/gitinspector/output/blameoutput.py b/gitinspector/output/blameoutput.py
index 55b7edb..683f2ec 100644
--- a/gitinspector/output/blameoutput.py
+++ b/gitinspector/output/blameoutput.py
@@ -23,21 +23,20 @@ import json
import sys
import textwrap
from ..localization import N_
-from .. import blame, format, gravatar, terminal
+from .. import format, gravatar, terminal
+from ..blame import Blame
from .outputable import Outputable
BLAME_INFO_TEXT = N_("Below are the number of rows from each author that have survived and are still "
"intact in the current revision")
class BlameOutput(Outputable):
- def __init__(self, changes, hard, useweeks):
+ def __init__(self, changes, blame):
if format.is_interactive_format():
print("")
self.changes = changes
- self.hard = hard
- self.useweeks = useweeks
- blame.get(self.hard, self.useweeks, self.changes)
+ self.blame = blame
Outputable.__init__(self)
def output_html(self):
@@ -47,7 +46,7 @@ class BlameOutput(Outputable):
_("Author"), _("Rows"), _("Stability"), _("Age"), _("% in comments"))
blame_xml += "
"
chart_data = ""
- blames = sorted(blame.__blame__.get_summed_blames().items())
+ blames = sorted(self.blame.get_summed_blames().items())
total_blames = 0
for i in blames:
@@ -64,7 +63,7 @@ class BlameOutput(Outputable):
blame_xml += "" + entry[0] + " | "
blame_xml += "" + str(entry[1].rows) + " | "
- blame_xml += "" + ("{0:.1f}".format(blame.Blame.get_stability(entry[0], entry[1].rows, self.changes)) + " | ")
+ blame_xml += "" + ("{0:.1f}".format(Blame.get_stability(entry[0], entry[1].rows, self.changes)) + " | ")
blame_xml += "" + "{0:.1f}".format(float(entry[1].skew) / entry[1].rows) + " | "
blame_xml += "" + "{0:.2f}".format(100.0 * entry[1].comments / entry[1].rows) + " | "
blame_xml += "" + work_percentage + " | "
@@ -99,13 +98,13 @@ class BlameOutput(Outputable):
message_xml = "\t\t\t\"message\": \"" + _(BLAME_INFO_TEXT) + "\",\n"
blame_xml = ""
- for i in sorted(blame.__blame__.get_summed_blames().items()):
+ for i in sorted(self.blame.get_summed_blames().items()):
author_email = self.changes.get_latest_email_by_author(i[0])
name_xml = "\t\t\t\t\"name\": \"" + i[0] + "\",\n"
gravatar_xml = "\t\t\t\t\"gravatar\": \"" + gravatar.get_url(author_email) + "\",\n"
rows_xml = "\t\t\t\t\"rows\": " + str(i[1].rows) + ",\n"
- stability_xml = ("\t\t\t\t\"stability\": " + "{0:.1f}".format(blame.Blame.get_stability(i[0], i[1].rows,
+ stability_xml = ("\t\t\t\t\"stability\": " + "{0:.1f}".format(Blame.get_stability(i[0], i[1].rows,
self.changes)) + ",\n")
age_xml = ("\t\t\t\t\"age\": " + "{0:.1f}".format(float(i[1].skew) / i[1].rows) + ",\n")
percentage_in_comments_xml = ("\t\t\t\t\"percentage-in-comments\": " + "{0:.2f}".format(100.0 * i[1].comments / i[1].rows) +
@@ -125,10 +124,10 @@ class BlameOutput(Outputable):
terminal.printb(terminal.ljust(_("Author"), 21) + terminal.rjust(_("Rows"), 10) + terminal.rjust(_("Stability"), 15) +
terminal.rjust(_("Age"), 13) + terminal.rjust(_("% in comments"), 20))
- for i in sorted(blame.__blame__.get_summed_blames().items()):
+ for i in sorted(self.blame.get_summed_blames().items()):
print(terminal.ljust(i[0], 20)[0:20 - terminal.get_excess_column_count(i[0])], end=" ")
print(str(i[1].rows).rjust(10), end=" ")
- print("{0:.1f}".format(blame.Blame.get_stability(i[0], i[1].rows, self.changes)).rjust(14), end=" ")
+ print("{0:.1f}".format(Blame.get_stability(i[0], i[1].rows, self.changes)).rjust(14), end=" ")
print("{0:.1f}".format(float(i[1].skew) / i[1].rows).rjust(12), end=" ")
print("{0:.2f}".format(100.0 * i[1].comments / i[1].rows).rjust(19))
@@ -136,13 +135,13 @@ class BlameOutput(Outputable):
message_xml = "\t\t" + _(BLAME_INFO_TEXT) + "\n"
blame_xml = ""
- for i in sorted(blame.__blame__.get_summed_blames().items()):
+ for i in sorted(self.blame.get_summed_blames().items()):
author_email = self.changes.get_latest_email_by_author(i[0])
name_xml = "\t\t\t\t" + i[0] + "\n"
gravatar_xml = "\t\t\t\t" + gravatar.get_url(author_email) + "\n"
rows_xml = "\t\t\t\t" + str(i[1].rows) + "\n"
- stability_xml = ("\t\t\t\t" + "{0:.1f}".format(blame.Blame.get_stability(i[0], i[1].rows,
+ stability_xml = ("\t\t\t\t" + "{0:.1f}".format(Blame.get_stability(i[0], i[1].rows,
self.changes)) + "\n")
age_xml = ("\t\t\t\t" + "{0:.1f}".format(float(i[1].skew) / i[1].rows) + "\n")
percentage_in_comments_xml = ("\t\t\t\t" + "{0:.2f}".format(100.0 * i[1].comments / i[1].rows) +
diff --git a/gitinspector/output/responsibilitiesoutput.py b/gitinspector/output/responsibilitiesoutput.py
index ba5e74e..27c4d62 100644
--- a/gitinspector/output/responsibilitiesoutput.py
+++ b/gitinspector/output/responsibilitiesoutput.py
@@ -21,7 +21,7 @@ from __future__ import print_function
from __future__ import unicode_literals
import textwrap
from ..localization import N_
-from .. import blame, format, gravatar, terminal
+from .. import format, gravatar, terminal
from .. import responsibilities as resp
from .outputable import Outputable
@@ -31,18 +31,17 @@ RESPONSIBILITIES_INFO_TEXT = N_("The following responsibilities, by author, were
MOSTLY_RESPONSIBLE_FOR_TEXT = N_("is mostly responsible for")
class ResponsibilitiesOutput(Outputable):
- def __init__(self, changes, hard, useweeks):
+ def __init__(self, changes, blame):
self.changes = changes
- self.hard = hard
- self.useweeks = useweeks
+ self.blame = blame
Outputable.__init__(self)
def output_text(self):
print("\n" + textwrap.fill(_(RESPONSIBILITIES_INFO_TEXT) + ":", width=terminal.get_size()[0]))
- for i in sorted(set(i[0] for i in blame.get(self.hard, self.useweeks, self.changes).blames)):
+ for i in sorted(set(i[0] for i in self.blame.blames)):
responsibilities = sorted(((i[1], i[0]) for i in resp.Responsibilities.get(self.changes,
- self.hard, self.useweeks, i)), reverse=True)
+ self.blame, i)), reverse=True)
if responsibilities:
print("\n" + i, _(MOSTLY_RESPONSIBLE_FOR_TEXT) + ":")
@@ -60,9 +59,9 @@ class ResponsibilitiesOutput(Outputable):
resp_xml = ""
resp_xml += "
" + _(RESPONSIBILITIES_INFO_TEXT) + ".
"
- for i in sorted(set(i[0] for i in blame.get(self.hard, self.useweeks, self.changes).blames)):
+ for i in sorted(set(i[0] for i in self.blame.blames)):
responsibilities = sorted(((i[1], i[0]) for i in resp.Responsibilities.get(self.changes,
- self.hard, self.useweeks, i)), reverse=True)
+ self.blame, i)), reverse=True)
if responsibilities:
resp_xml += "
"
@@ -87,9 +86,9 @@ class ResponsibilitiesOutput(Outputable):
message_xml = "\t\t\t\"message\": \"" + _(RESPONSIBILITIES_INFO_TEXT) + "\",\n"
resp_xml = ""
- for i in sorted(set(i[0] for i in blame.get(self.hard, self.useweeks, self.changes).blames)):
+ for i in sorted(set(i[0] for i in self.blame.blames)):
responsibilities = sorted(((i[1], i[0]) for i in resp.Responsibilities.get(self.changes,
- self.hard, self.useweeks, i)), reverse=True)
+ self.blame, i)), reverse=True)
if responsibilities:
author_email = self.changes.get_latest_email_by_author(i)
@@ -118,9 +117,9 @@ class ResponsibilitiesOutput(Outputable):
message_xml = "\t\t" + _(RESPONSIBILITIES_INFO_TEXT) + "\n"
resp_xml = ""
- for i in sorted(set(i[0] for i in blame.get(self.hard, self.useweeks, self.changes).blames)):
+ for i in sorted(set(i[0] for i in self.blame.blames)):
responsibilities = sorted(((i[1], i[0]) for i in resp.Responsibilities.get(self.changes,
- self.hard, self.useweeks, i)), reverse=True)
+ self.blame, i)), reverse=True)
if responsibilities:
author_email = self.changes.get_latest_email_by_author(i)
diff --git a/gitinspector/responsibilities.py b/gitinspector/responsibilities.py
index 6a64150..5868dae 100644
--- a/gitinspector/responsibilities.py
+++ b/gitinspector/responsibilities.py
@@ -26,10 +26,10 @@ class ResponsibiltyEntry(object):
class Responsibilities(object):
@staticmethod
- def get(changes, hard, useweeks, author_name):
+ def get(changes, blame, author_name):
author_blames = {}
- for i in blame.get(hard, useweeks, changes).blames.items():
+ for i in blame.blames.items():
if author_name == i[0][0]:
total_rows = i[1].rows - i[1].comments
if total_rows > 0: