Compare commits

..

4 Commits

Author SHA1 Message Date
Lukáš Mešťan
4f95691967 Merge pull request #55 from tomice/master
Fix bug related to author name in hourly stats
2019-01-06 17:30:54 +01:00
Tom Ice
36405591ec Fix bug related to author name in hourly stats
* Fixing a bug where, if you insert an author's name that has a space in the
  "Git commits by author per hour" option, it fails due to improper variable
  expansion. Note that the current implementation is a "greedy" one in that
  it will attempt to look for any instance of the user provided string in the
  author field
2019-01-01 14:37:11 -05:00
Lukáš Mešťan
4e3f4ba826 Merge pull request #54 from tomice/master
Fix divide by zero error and add utility checker
2018-12-27 14:21:44 +01:00
Tom Ice
83e96f8b80 Fix divide by zero error and add utility checker
* In some situations, the awk statements in the functions commitsByMonth,
  commitsByDay, and commitsByHour attempt to divide by zero and display
  an error to the user. To invoke this bug, checkout any of the previous
  commits and attempt to see commits by hour from some user who has never
  committed to this repository.

  This commit fixes this bug by making sure the awk statement only ever
  executes when the total commits is greater than zero.

* Added a utility checker to make sure that the user has all of the necessary
  tools in their path in order to run this script. If they do not exist, it
  exits and informs the user that this script cannot locate them in PATH.

* Adjusted shell logic to prevent double negatives from confusing developers
  as ! -z is technically read as something akin to "not has no value"

* Changed some statements to utilize safer and more predictable bash-isms

* Minor white space fixes and adjusted the README.md slightly
2018-12-21 14:50:13 -05:00
2 changed files with 68 additions and 49 deletions

View File

@@ -129,7 +129,7 @@ brew install git-quick-stats
## System requirements
* Unix like OS with a proper shell
* Tools we use: git ; awk ; sed ; tr ; echo ; grep ; cut ; sort ; head ; uniq ; column ; seq ; tput.
* Tools we use: awk ; cat ; column ; echo ; git ; grep ; head ; seq ; sort ; tput ; tr ; uniq ; wc
#### Dependences

View File

@@ -4,27 +4,40 @@ set -o nounset
set -o errexit
_since=${_GIT_SINCE:-}
if [ ! -z ${_since} ]
then _since="--since=$_since"
fi
[[ -n "${_since}" ]] && _since="--since=$_since"
_until=${_GIT_UNTIL:-}
if [ ! -z ${_until} ]
then _until="--until=$_until"
fi
[[ -n "${_until}" ]] && _until="--until=$_until"
_pathspec=${_GIT_PATHSPEC:-}
if [ ! -z "${_pathspec}" ]
then _pathspec="-- $_pathspec"
fi
[[ -n "${_pathspec}" ]] && _pathspec="-- $_pathspec"
_limit=${_GIT_LIMIT:-}
if [ ! -z ${_limit} ]
if [[ -n "${_limit}" ]];
then _limit=$_limit
else
_limit=10
fi
function check_utils() {
local HELP_MSG="not found. Please make sure this is installed and in PATH."
command -v awk >/dev/null 2>&1 || { echo >&2 "awk ${HELP_MSG}"; exit 1; }
command -v cat > /dev/null 2>&1 || { echo >&2 "cat ${HELP_MSG}"; exit 1; }
command -v column > /dev/null 2>&1 || { echo >&2 "column ${HELP_MSG}"; exit 1; }
command -v echo > /dev/null 2>&1 || { echo >&2 "echo ${HELP_MSG}"; exit 1; }
command -v git > /dev/null 2>&1 || { echo >&2 "git ${HELP_MSG}"; exit 1; }
command -v grep > /dev/null 2>&1 || { echo >&2 "grep ${HELP_MSG}"; exit 1; }
command -v head > /dev/null 2>&1 || { echo >&2 "head ${HELP_MSG}"; exit 1; }
command -v seq > /dev/null 2>&1 || { echo >&2 "seq ${HELP_MSG}"; exit 1; }
command -v sort > /dev/null 2>&1 || { echo >&2 "sort ${HELP_MSG}"; exit 1; }
command -v tput > /dev/null 2>&1 || { echo >&2 "tput ${HELP_MSG}"; exit 1; }
command -v tr > /dev/null 2>&1 || { echo >&2 "tr ${HELP_MSG}"; exit 1; }
command -v uniq > /dev/null 2>&1 || { echo >&2 "uniq ${HELP_MSG}"; exit 1; }
command -v wc > /dev/null 2>&1 || { echo >&2 "wc ${HELP_MSG}"; exit 1; }
}
function show_menu() {
local NORMAL=$(tput sgr0)
local CYAN_TEXT=$(tput setaf 6)
@@ -64,7 +77,6 @@ function option_picked() {
function detailedGitStats() {
option_picked "Contribution stats (by author):"
git log --use-mailmap --no-merges --numstat --pretty="format:commit %H%nAuthor: %aN <%aE>%nDate: %ad%n%n%w(0,4,4)%B%n" $_since $_until $_pathspec | LC_ALL=C awk '
function printStats(author) {
printf "\t%s:\n", author
@@ -152,12 +164,13 @@ function commitsByMonth() {
END{
for (month in count) {
s="|";
percent = ((count[month] / total) * 100) / 1.25;
for (i = 1; i <= percent; ++i) {
s=s"█"
if (total > 0) {
percent = ((count[month] / total) * 100) / 1.25;
for (i = 1; i <= percent; ++i) {
s=s"█"
}
printf( "\t%s\t%-0s\t%s\n", month, count[month], s );
}
printf( "\t%s\t%-0s\t%s\n", month, count[month], s );
}
}' | LC_TIME="en_EN.UTF-8" sort -M
}
@@ -181,29 +194,33 @@ function commitsByWeekday() {
for (day in count) {
s="|";
percent = ((count[day] / total) * 100) / 1.25;
for (i = 1; i <= percent; ++i) {
s=s"█"
if (total > 0) {
percent = ((count[day] / total) * 100) / 1.25;
for (i = 1; i <= percent; ++i) {
s=s"█"
}
printf( "\t%s\t%-0s\t%s\n", day, count[day], s );
}
printf( "\t%s\t%-0s\t%s\n", day, count[day], s );
}
}' | sort -k 2 -n -r
}
function commitsByHour() {
local author="${1:-}"
local _author=''
if [ -z "$author" ]; then
local _author=""
if [[ -z "${author}" ]]; then
option_picked "Git commits by hour:"
_author="--author=**"
else
option_picked "Git commits by hour for author '$author':"
_author="--author=$author"
option_picked "Git commits by hour for author '${author}':"
_author="--author=${author}"
fi
echo -e "\thour\tsum"
for i in $(seq -w 0 23)
do
echo -ne "\t$i\t"
echo "$(git shortlog -n --no-merges --format='%ad %s' $_author $_since $_until | grep ' '$i: | wc -l)"
git shortlog -n --no-merges --format='%ad %s' "${_author}" $_since $_until | grep ' '$i: | wc -l
done | awk '{
count[$1] = $2
total += $2
@@ -211,11 +228,13 @@ function commitsByHour() {
END{
for (hour in count) {
s="|";
percent = ((count[hour] / total) * 100) / 1.25;
for (i = 1; i <= percent; ++i) {
s=s"█"
if (total > 0) {
percent = ((count[hour] / total) * 100) / 1.25;
for (i = 1; i <= percent; ++i) {
s=s"█"
}
printf( "\t%s\t%-0s\t%s\n", hour, count[hour], s );
}
printf( "\t%s\t%-0s\t%s\n", hour, count[hour], s );
}
}' | sort
}
@@ -267,24 +286,28 @@ function branchesByDate() {
function changelogs() {
local author="${1:-}"
local _author
if [ -z "$author" ]; then
local _author=""
if [[ -z "${author}" ]]; then
option_picked "Git changelogs:"
_author="--author=**"
else
option_picked "Git changelogs for author '$author':"
_author="--author=$author"
option_picked "Git changelogs for author '${author}':"
_author="--author=${author}"
fi
NEXT=$(date +%F)
git log --use-mailmap --no-merges --format="%cd" --date=short "$_author" $_since $_until $_pathspec | sort -u -r | head -n $_limit | while read DATE ; do
git log --use-mailmap --no-merges --format="%cd" --date=short "${_author}" $_since $_until $_pathspec | sort -u -r | head -n $_limit | while read DATE ; do
echo
echo "[$DATE]"
GIT_PAGER=cat git log --use-mailmap --no-merges --format=" * %s (%aN)" "$_author" --since=$DATE --until=$NEXT
GIT_PAGER=cat git log --use-mailmap --no-merges --format=" * %s (%aN)" "${_author}" --since=$DATE --until=$NEXT
NEXT=$DATE
done
}
# Check to make sure all utilities required for this script are installed
check_utils
# Check if we are currently in a git repo.
git rev-parse --is-inside-work-tree > /dev/null
@@ -320,8 +343,8 @@ if [ $# -eq 1 ]
;;
"changelogsByAuthor")
author="${_GIT_AUTHOR:-}"
while [ -z "$author" ]; do read -p "Which author? " author; done
changelogs "$author"
while [ -z "${author}" ]; do read -p "Which author? " author; done
changelogs "${author}"
;;
"commitsByWeekday")
commitsByWeekday
@@ -331,8 +354,8 @@ if [ $# -eq 1 ]
;;
"commitsByAuthorByHour")
author="${_GIT_AUTHOR:-}"
while [ -z "$author" ]; do read -p "Which author? " author; done
commitsByHour "$author"
while [ -z "${author}" ]; do read -p "Which author? " author; done
commitsByHour "${author}"
;;
"commitsByMonth")
commitsByMonth
@@ -345,11 +368,7 @@ if [ $# -eq 1 ]
exit 0;
fi
if [ $# -gt 1 ]
then
echo "Usage: git quick-stats <optional-command-to-execute-directly>";
exit 1;
fi
[[ $# -gt 1 ]] && { echo "Usage: git quick-stats <optional-command-to-execute-directly>"; exit 1; }
clear
show_menu
@@ -371,8 +390,8 @@ while [ opt != '' ]
;;
3)
author=''
while [ -z "$author" ]; do read -p "Which author? " author; done
changelogs "$author"
while [ -z "${author}" ]; do read -p "Which author? " author; done
changelogs "${author}"
show_menu
;;
4)
@@ -413,8 +432,8 @@ while [ opt != '' ]
;;
13)
author=''
while [ -z "$author" ]; do read -p "Which author? " author; done
commitsByHour "$author"
while [ -z "${author}" ]; do read -p "Which author? " author; done
commitsByHour "${author}"
show_menu
;;
14)