|
import tempfile |
|
import gradio as gr |
|
from git import Repo, Git |
|
import datetime |
|
import argparse |
|
from collections import Counter |
|
import os |
|
|
|
|
|
def greet(name): |
|
with tempfile.TemporaryDirectory() as d: |
|
Repo.clone_from(name, d) |
|
repo = Repo(d) |
|
for commit in repo.iter_commits(): |
|
print(commit) |
|
|
|
return check_repo(d, datetime.datetime(2022, 1, 1), 10) |
|
|
|
|
|
|
|
def check(): |
|
parser = argparse.ArgumentParser( |
|
prog = 'ProgramName', |
|
description = 'What the program does', |
|
epilog = 'Text at the bottom of help') |
|
parser.add_argument('repo', nargs='?', default=default_repo()) |
|
parser.add_argument('--since', |
|
type=lambda d: datetime.datetime.strptime(d, '%Y-%m-%d'), |
|
default=None, |
|
help='Set a start date') |
|
parser.add_argument('--filter', |
|
type=lambda d: d.split(","), |
|
default=None, |
|
help='Set a comma separated filter') |
|
parser.add_argument('--mincount', |
|
type=int, |
|
default=10, |
|
help='Set a comma separated filter') |
|
args = parser.parse_args() |
|
if "/" not in args.repo: |
|
args.repo = f"/home/nicolas/src/{args.repo}" |
|
with cd(args.repo): |
|
check_repo(args.repo, args.since, args.mincount) |
|
|
|
class cd: |
|
"""Context manager for changing the current working directory""" |
|
|
|
def __init__(self, newPath): |
|
self.newPath = os.path.expanduser(newPath) |
|
|
|
def __enter__(self): |
|
self.savedPath = os.getcwd() |
|
os.chdir(self.newPath) |
|
|
|
def __exit__(self, etype, value, traceback): |
|
os.chdir(self.savedPath) |
|
|
|
def default_repo(): |
|
return os.getcwd() |
|
|
|
|
|
|
|
def check_repo(repo_path, since, mincount, filter_=None): |
|
most_common = 10 |
|
bugwords = [("revert", 1), ("bug", 1), ("fix", 1)] |
|
|
|
repo = Repo(repo_path) |
|
c = Counter() |
|
git = Git() |
|
commits = [] |
|
for commit in repo.iter_commits(): |
|
if since and commit.committed_datetime < since.astimezone(): |
|
break |
|
commits.append(commit.hexsha[:8]) |
|
|
|
|
|
files = Counter() |
|
bugfiles = Counter() |
|
current_commit = 0 |
|
current_files = [] |
|
out = git.show('--stat', '--oneline', '--name-only', f"{commits[-1]}..") |
|
|
|
is_bug = 0 |
|
for i, line in enumerate(out.split("\n")): |
|
line = line.strip() |
|
if not line: |
|
continue |
|
if line.startswith(commits[current_commit]): |
|
|
|
commit, message = line.lower().split(" ", 1) |
|
found = False |
|
for (bugword, count) in bugwords: |
|
if bugword in message: |
|
is_bug = count |
|
found = True |
|
break |
|
if not found: |
|
is_bug = 0 |
|
current_commit += 1 |
|
else: |
|
found = True |
|
if filter_: |
|
found = False |
|
for filter_ in filter_: |
|
if filter_ in line: |
|
found = True |
|
break |
|
if not found: |
|
continue |
|
|
|
files[line] += 1 |
|
if is_bug: |
|
bugfiles[line] += is_bug |
|
|
|
string = "" |
|
|
|
string += "=====" + "\n" |
|
string += "Most commonly changed files" + "\n" |
|
string += + "\n" |
|
for (filename, count) in files.most_common(most_common): |
|
string += f"{filename}: {count}" + "\n" |
|
string += + "\n" |
|
string += + "\n" |
|
|
|
string += "=====" + "\n" |
|
string += "Most commonly bugged files" + "\n" |
|
for (filename, count) in bugfiles.most_common(most_common): |
|
string += f"{filename}: {count}" + "\n" |
|
|
|
string += + "\n" |
|
string += + "\n" |
|
string += "=====" + "\n" |
|
string += "Most commonly bugged files (adjusted)" + "\n" |
|
adjusted = {} |
|
for (filename, count) in bugfiles.items(): |
|
if count < mincount: |
|
continue |
|
percentage = count / files[filename] |
|
adjusted[filename] = (percentage, count) |
|
for (filename, (percentage, count)) in sorted(adjusted.items(), key=lambda x: x[1], reverse=True)[:most_common]: |
|
string += f"{filename}: {percentage} ({count})" + "\n" |
|
return string |
|
|
|
iface = gr.Interface(fn=greet, inputs="text", outputs="text") |
|
iface.launch() |
|
|