From 98615ccbfc1c001042eee7b0ef0838a29469a8ad Mon Sep 17 00:00:00 2001 From: Adam Waldenberg Date: Sat, 31 Oct 2015 05:10:00 +0100 Subject: [PATCH] Support for multiple repositories is near completion (See issue #24). Only the metrics module is lacking support. While the rest should work, please note that it is completely untested as of now and probably has some rough edges. --- gitinspector/blame.py | 20 ++++++++------- gitinspector/gitinspector.py | 14 +++++++---- gitinspector/output/blameoutput.py | 25 +++++++++---------- gitinspector/output/responsibilitiesoutput.py | 23 ++++++++--------- gitinspector/responsibilities.py | 4 +-- 5 files changed, 45 insertions(+), 41 deletions(-) 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: