Implemented filtering by commit message (Fixes #57).

When filtering, "git show" is called in order to pull the commit message
from the git log. While slow, it makes certain that the message itself is
pulled correctly, including any escape characters that might be present.
This commit is contained in:
Adam Waldenberg 2015-09-24 03:38:35 +02:00
parent f368c0019a
commit da1553b57e
4 changed files with 47 additions and 17 deletions

View file

@ -1,6 +1,6 @@
# coding: utf-8
#
# Copyright © 2012-2014 Ejwa Software. All rights reserved.
# Copyright © 2012-2015 Ejwa Software. All rights reserved.
#
# This file is part of gitinspector.
#
@ -82,10 +82,12 @@ class BlameThread(threading.Thread):
except KeyError:
return
__blame_lock__.acquire() # Global lock used to protect calls from here...
if not filtering.set_filtered(author, "author") and not filtering.set_filtered(self.blamechunk_email, "email") and not \
if not filtering.set_filtered(author, "author") and not \
filtering.set_filtered(self.blamechunk_email, "email") and not \
filtering.set_filtered(self.blamechunk_revision, "revision"):
__blame_lock__.acquire() # Global lock used to protect calls from here...
if self.blames.get((author, self.filename), None) == None:
self.blames[(author, self.filename)] = BlameEntry()
@ -96,7 +98,7 @@ class BlameThread(threading.Thread):
self.blames[(author, self.filename)].skew += ((self.changes.last_commit_date - self.blamechunk_time).days /
(7.0 if self.useweeks else AVG_DAYS_PER_MONTH))
__blame_lock__.release() # ...to here.
__blame_lock__.release() # ...to here.
def run(self):
git_blame_r = subprocess.Popen(self.blame_command, bufsize=1, stdout=subprocess.PIPE).stdout

View file

@ -134,6 +134,7 @@ class ChangesThread(threading.Thread):
commit = None
found_valid_extension = False
is_filtered = False
commits = []
__changes_lock__.acquire() # Global lock used to protect calls from here...
@ -153,11 +154,18 @@ class ChangesThread(threading.Thread):
commits.append(commit)
found_valid_extension = False
is_filtered = False
commit = Commit(j)
if FileDiff.is_filediff_line(j) and not filtering.set_filtered(FileDiff.get_filename(j)) and not \
filtering.set_filtered(commit.author, "author") and not filtering.set_filtered(commit.email, "email") and not \
filtering.set_filtered(commit.sha, "revision"):
if Commit.is_commit_line(j) and \
(filtering.set_filtered(commit.author, "author") or \
filtering.set_filtered(commit.email, "email") or \
filtering.set_filtered(commit.sha, "revision") or \
filtering.set_filtered(commit.sha, "message")):
is_filtered = True
if FileDiff.is_filediff_line(j) and not \
filtering.set_filtered(FileDiff.get_filename(j)) and not is_filtered:
extensions.add_located(FileDiff.get_extension(j))
if FileDiff.is_valid_extension(j):

View file

@ -22,10 +22,11 @@ from __future__ import unicode_literals
from localization import N_
from outputable import Outputable
import re
import subprocess
import terminal
import textwrap
__filters__ = {"file": [[], set()], "author": [[], set()], "email": [[], set()], "revision": [[], set()]}
__filters__ = {"file": [set(), set()], "author": [set(), set()], "email": [set(), set()], "revision": [set(), set()], "message" : [set(), None]}
class InvalidRegExpError(ValueError):
def __init__(self, msg):
@ -38,9 +39,9 @@ def get():
def __add_one__(string):
for i in __filters__:
if (i + ":").lower() == string[0:len(i) + 1].lower():
__filters__[i][0].append(string[len(i) + 1:])
__filters__[i][0].add(string[len(i) + 1:])
return
__filters__["file"][0].append(string)
__filters__["file"][0].add(string)
def add(string):
rules = string.split(",")
@ -49,7 +50,7 @@ def add(string):
def clear():
for i in __filters__:
__filters__[i][0] = []
__filters__[i][0] = set()
def get_filered(filter_type="file"):
return __filters__[filter_type][1]
@ -60,14 +61,32 @@ def has_filtered():
return True
return False
def __find_commit_message__(sha):
git_show_r = subprocess.Popen(filter(None, ["git", "show", "-s", "--pretty=%B", "-w", sha]), bufsize=1,
stdout=subprocess.PIPE).stdout
commit_message = git_show_r.read()
git_show_r.close()
commit_message = commit_message.strip().decode("unicode_escape", "ignore")
commit_message = commit_message.encode("latin-1", "replace")
return commit_message.decode("utf-8", "replace")
def set_filtered(string, filter_type="file"):
string = string.strip()
if len(string) > 0:
for i in __filters__[filter_type][0]:
search_for = string
if filter_type == "message":
search_for = __find_commit_message__(string)
try:
if re.search(i, string) != None:
__filters__[filter_type][1].add(string)
if re.search(i, search_for) != None:
if filter_type == "message":
__add_one__("revision:" + string)
else:
__filters__[filter_type][1].add(string)
return True
except:
raise InvalidRegExpError(_("invalid regular expression specified"))
@ -138,5 +157,5 @@ class Filtering(Outputable):
Filtering.__output_xml_section__(_(FILTERING_INFO_TEXT), __filters__["file"][1], "files")
Filtering.__output_xml_section__(_(FILTERING_AUTHOR_INFO_TEXT), __filters__["author"][1], "authors")
Filtering.__output_xml_section__(_(FILTERING_EMAIL_INFO_TEXT), __filters__["email"][1], "emails")
Filtering.__output_xml_section__(_(FILTERING_COMMIT_INFO_TEXT), __filters__["revision"][1].union(), "revisions")
Filtering.__output_xml_section__(_(FILTERING_COMMIT_INFO_TEXT), __filters__["revision"][1], "revision")
print("\t</filtering>")

View file

@ -1,6 +1,6 @@
# coding: utf-8
#
# Copyright © 2012-2014 Ejwa Software. All rights reserved.
# Copyright © 2012-2015 Ejwa Software. All rights reserved.
#
# This file is part of gitinspector.
#
@ -61,7 +61,8 @@ Boolean arguments can only be given to long options.
-w, --weeks[=BOOL] show all statistical information in weeks
instead of in months
-x, --exclude=PATTERN an exclusion pattern describing the file
paths, revisions, author names or author
paths, revisions, revisions with certain
commit messages, author names or author
emails that should be excluded from the
statistics; can be specified multiple times
-h, --help display this help and exit