add git utilities to display stats of a repo

This commit is contained in:
MorganGeek 2020-07-23 07:18:03 +02:00
parent 595443e89b
commit a9feda9383
4 changed files with 172 additions and 0 deletions

View File

@ -200,3 +200,4 @@ brew "git-delta"
brew "sn0int" brew "sn0int"
brew "prettier" brew "prettier"
brew "switchaudio-osx" brew "switchaudio-osx"
brew "git-extras"

166
dot_scripts/git-overview.py Executable file
View File

@ -0,0 +1,166 @@
#!/usr/bin/env python3
"""
Origin : https://github.com/qznc/dot/blob/master/bin/git-overview
Gather a general overview from a git repository.
It shall identify the major contributors within a project.
It shall identify interesting parts in the code.
"""
from subprocess import check_output
from datetime import datetime
from os.path import splitext
_CMD_AUTHOR_HISTORY = 'git log --date=iso --format="format:%an;%ad;%G?;%H"'
_CMD_FILELIST = "git ls-files"
_CMD_COMMIT_FILES_CHANGES = "git diff-tree --no-commit-id --name-only -r "
from collections import namedtuple
FileInfo = namedtuple("FileInfo", "path,authors,commits,firstc,lastc")
def read_log_data():
total_commits = 0
authors = dict()
files = dict()
raw = check_output(_CMD_AUTHOR_HISTORY, shell=True, universal_newlines=True)
for line in raw.split("\n"):
total_commits += 1
name, dt, signed, hash = line.split(";")
if not name in authors:
authors[name] = (datetime.now(), datetime(1900, 1, 1), 0)
first, last, count = authors[name]
when = datetime.strptime(dt[:-6], "%Y-%m-%d %H:%M:%S")
if when < first:
first = when
if when > last:
last = when
authors[name] = (first, last, count + 1)
craw = check_output(
_CMD_COMMIT_FILES_CHANGES + hash, shell=True, universal_newlines=True
)
for file in craw.split("\n"):
if file == "":
continue
if file in files:
fi = files[file]
else:
files[file] = fi = dict(
path=file,
authors=set(),
commits=0,
firstc=datetime.now(),
lastc=datetime(1900, 1, 1),
)
fi["authors"].add(name)
fi["commits"] += 1
if when < fi["firstc"]:
fi["firstc"] = when
if when > fi["lastc"]:
fi["lastc"] = when
return authors, files, total_commits
def readable_duration(dur):
"""Given a timedelta object, returns a human-readable string"""
if dur.days > 0:
if dur.days > 365 * 2:
return "%d years" % (dur.days / 365)
elif dur.days > 30 * 5:
return "%d months" % (dur.days / 30)
else:
return "%d days" % (dur.days)
else:
if dur.seconds > 60 * 60 * 2:
return "%d hours" % (dur.seconds / 60 / 60)
elif dur.seconds > 60 * 5:
return "%d minutes" % (dur.seconds / 60)
else:
return "%d seconds" % (dur.seconds)
def partition_by_extension(fileinfo):
pd = dict()
meta = dict()
total_filecount = 0
total_extfilecount = 0
for path, fi in fileinfo.items():
total_filecount += 1
root, ext = splitext(path)
if not ext:
continue
total_extfilecount += 1
if not ext in pd:
pd[ext] = dict()
meta[ext] = dict(filecount=0)
pd[ext][path] = fi
meta[ext]["filecount"] += 1
return pd, meta, total_filecount, total_extfilecount
def print_top_committers(authorinfo, total_commits):
authors = sorted(authorinfo.items(), key=lambda x: x[1][2], reverse=True)
total_authors = len(authors)
committed = 0
print("Top Committers (of %d authors):" % (total_authors))
for author, info in authors:
first, last, count = info
readable_last = last.strftime("%Y-%m-%d")
if count == 1:
print("%-20s 1 commit on %s" % (author, readable_last))
else:
duration = readable_duration(last - first)
print(
"%-20s %4d commits during %s until %s"
% (author, count, duration, readable_last)
)
committed += count
if committed > total_commits * 0.8:
break
print(
" together these authors have 80+%% of the commits (%d/%d)"
% (committed, total_commits)
)
def print_important_files(fileinfo):
files = list(fileinfo.values())
files.sort(key=lambda x: x["commits"])
print("Files with most commits:")
for x in files[-5:]:
readable_last = x["lastc"].strftime("%Y-%m-%d")
duration = readable_duration(x["lastc"] - x["firstc"])
print(
"%4d commits: %-20s during %s until %s"
% (x["commits"], x["path"], duration, readable_last)
)
print()
files.sort(key=lambda x: len(x["authors"]))
print("Files with most authors:")
for x in files[-5:]:
print("%2d authors: %-20s" % (len(x["authors"]), x["path"]))
def print_extension_info(fileinfo):
pfileinfo, extinfo, total_filecount, total_extfilecount = partition_by_extension(
fileinfo
)
pf = [(e, i) for e, i in pfileinfo.items()]
pf.sort(key=lambda x: extinfo[x[0]]["filecount"], reverse=True)
print("By file extension:")
fc = 0
for ext, info in pf:
c = extinfo[ext]["filecount"]
print("%5s: %d files" % (ext, extinfo[ext]["filecount"]))
fc += c
if fc > total_filecount * 0.8:
break
print(" together these make up 80+%% of the files (%d/%d)" % (fc, total_filecount))
authorinfo, fileinfo, total_commits = read_log_data()
print_top_committers(authorinfo, total_commits)
print()
print_important_files(fileinfo)
print()
print_extension_info(fileinfo)

View File

@ -12,6 +12,10 @@ Darwin)
export PATH="$PATH:/usr/local/Cellar/python/3.7.3/Frameworks/Python.framework/Versions/3.7/bin/:/usr/local/Cellar/python/3.7.4/Frameworks/Python.framework/Versions/3.7/bin:/usr/local/Cellar/python/3.7.5/Frameworks/Python.framework/Versions/3.7/bin:/usr/local/opt/python/bin/" export PATH="$PATH:/usr/local/Cellar/python/3.7.3/Frameworks/Python.framework/Versions/3.7/bin/:/usr/local/Cellar/python/3.7.4/Frameworks/Python.framework/Versions/3.7/bin:/usr/local/Cellar/python/3.7.5/Frameworks/Python.framework/Versions/3.7/bin:/usr/local/opt/python/bin/"
;; ;;
esac esac
if ! test -f "/usr/bin/python2" || ! command -v python2 &>/dev/null; then
sudo ln -snf /usr/bin/python /usr/bin/python2
fi
echo "Upgrading pip" echo "Upgrading pip"
sudo pip install --upgrade pip sudo pip install --upgrade pip
echo "Pip installing stuff" echo "Pip installing stuff"

View File

@ -10,6 +10,7 @@ ln -snf "$HOME/Code/dotfiles/dot_gitconfig" "$HOME/.gitconfig"
ln -snf "$HOME/Code/dotfiles/dot_macos" "$HOME/.macos" ln -snf "$HOME/Code/dotfiles/dot_macos" "$HOME/.macos"
ln -snf "$HOME/Code/dotfiles/dot_scripts" "$HOME/.scripts" ln -snf "$HOME/Code/dotfiles/dot_scripts" "$HOME/.scripts"
ln -snf "$HOME/Code/dotfiles/dot_scripts/checkci.sh" /usr/local/bin/checkci ln -snf "$HOME/Code/dotfiles/dot_scripts/checkci.sh" /usr/local/bin/checkci
ln -snf "$HOME/Code/dotfiles/dot_scripts/git-overview.py" /usr/local/bin/git-overview # via https://github.com/qznc/dot/blob/master/bin/git-overview
ln -snf "$HOME/Code/dotfiles/dot_scripts/pre-commit-verify-committer.sh" /usr/local/bin/pre-commit-verify-committer ln -snf "$HOME/Code/dotfiles/dot_scripts/pre-commit-verify-committer.sh" /usr/local/bin/pre-commit-verify-committer
ln -snf "$HOME/Code/dotfiles/dot_vimrc" "$HOME/.vimrc" ln -snf "$HOME/Code/dotfiles/dot_vimrc" "$HOME/.vimrc"
# custom linters # custom linters