Compare commits

..

6 Commits

Author SHA1 Message Date
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
Lukáš Mešťan
206ebd8a76 Merge pull request #53 from tomice/master
Improve color compatibility and other minor fixes
2018-12-21 19:35:55 +01:00
Tom Ice
2274ca1284 Improve color compatibility and other minor fixes
* Color was originally done with ANSI escape characters for defining
  different "expected" colors. However, this is not uniform across all
  terminals. To improve what the designers of this program expect
  colors to be, escape codes were replaced with tput equivalents.
  For more information, see the GNU manual here:

  https://www.gnu.org/software/termutils/manual/termutils-2.0/html_chapter/tput_1.html

* Limited scope of variables to their local scope instead of having them
  be global

* Renamed menu variables to aid in readability and adjusted formatting
  slightly to be more uniform

* Fixed a bug where option_picked was assigning an array to a string
  and relying on the default behavior of the shell to interpret it

* Added the -r option to "read" for safety, as read without -r will
  interpret backslashes before spaces/line feeds, which tends to
  be an unintended side effect

* Updated all backtick notation to the newer POSIX $(..) notation for
  aid in readability when paired next to single quotes and improved
  safety

* Updated the README.md to include missing utilities and fixed some
  minor formatting issues
2018-12-21 12:05:53 -05:00
Lukáš Mešťan
37f15f6381 Update index.html 2018-12-07 15:43:23 +01:00
Lukáš Mešťan
337ead38e3 Update index.html 2018-12-07 15:42:16 +01:00
3 changed files with 85 additions and 68 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.
* Tools we use: awk ; cat ; column ; echo ; git ; grep ; head ; seq ; sort ; tput ; tr ; uniq ; wc
#### Dependences
@@ -146,11 +146,11 @@ brew install git-quick-stats
Want to contribute? Great! First, read this page.
#### Code reviews
All submissions, including submissions by project members, require review.
All submissions, including submissions by project members, require review.</br>
We use Github pull requests for this purpose.
#### Some tips for good pull requests:
* Use our code
* Use our code </br>
When in doubt, try to stay true to the existing code of the project.
* Write a descriptive commit message. What problem are you solving and what
are the consequences? Where and what did you test? Some good tips:

View File

@@ -17,6 +17,7 @@
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
<script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
<![endif]-->
<meta http-equiv="refresh" content="0;url=https://lukasmestan.com/git-quick-stats/">
</head>
<body id="page-top">
<header>

View File

@@ -4,69 +4,79 @@ 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 show_menu() {
NORMAL=`echo "\033[m"`
MENU=`echo "\033[36m"`
NUMBER=`echo "\033[33m"`
FGRED=`echo "\033[41m"`
RED_TEXT=`echo "\033[31m"`
ENTER_LINE=`echo "\033[33m"`
function check_utils() {
local HELP_MSG="not found. Please make sure this is installed and in PATH."
echo -e ""
echo -e "${RED_TEXT} Generate: ${NORMAL}"
echo -e "${MENU} ${NUMBER} 1)${MENU} Contribution stats (by author) ${NORMAL}"
echo -e "${MENU} ${NUMBER} 2)${MENU} Git changelogs (last $_limit days)${NORMAL}"
echo -e "${MENU} ${NUMBER} 3)${MENU} Git changelogs by author ${NORMAL}"
echo -e "${MENU} ${NUMBER} 4)${MENU} My daily status ${NORMAL}"
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)
local RED_TEXT=$(tput setaf 1)
local YELLOW_TEXT=$(tput setaf 3)
echo -e "\n${RED_TEXT} Generate: ${NORMAL}"
echo -e "${CYAN_TEXT} ${YELLOW_TEXT} 1)${CYAN_TEXT} Contribution stats (by author) ${NORMAL}"
echo -e "${CYAN_TEXT} ${YELLOW_TEXT} 2)${CYAN_TEXT} Git changelogs (last $_limit days)${NORMAL}"
echo -e "${CYAN_TEXT} ${YELLOW_TEXT} 3)${CYAN_TEXT} Git changelogs by author ${NORMAL}"
echo -e "${CYAN_TEXT} ${YELLOW_TEXT} 4)${CYAN_TEXT} My daily status ${NORMAL}"
echo -e "${RED_TEXT} List: ${NORMAL}"
echo -e "${MENU} ${NUMBER} 5)${MENU} Branch tree view (last $_limit)${NORMAL}"
echo -e "${MENU} ${NUMBER} 6)${MENU} All branches (sorted by most recent commit) ${NORMAL}"
echo -e "${MENU} ${NUMBER} 7)${MENU} All contributors (sorted by name) ${NORMAL}"
echo -e "${MENU} ${NUMBER} 8)${MENU} Git commits per author ${NORMAL}"
echo -e "${MENU} ${NUMBER} 9)${MENU} Git commits per date ${NORMAL}"
echo -e "${MENU} ${NUMBER} 10)${MENU} Git commits per month ${NORMAL}"
echo -e "${MENU} ${NUMBER} 11)${MENU} Git commits per weekday ${NORMAL}"
echo -e "${MENU} ${NUMBER} 12)${MENU} Git commits per hour ${NORMAL}"
echo -e "${MENU} ${NUMBER} 13)${MENU} Git commits by author per hour ${NORMAL}"
echo -e "${CYAN_TEXT} ${YELLOW_TEXT} 5)${CYAN_TEXT} Branch tree view (last $_limit)${NORMAL}"
echo -e "${CYAN_TEXT} ${YELLOW_TEXT} 6)${CYAN_TEXT} All branches (sorted by most recent commit) ${NORMAL}"
echo -e "${CYAN_TEXT} ${YELLOW_TEXT} 7)${CYAN_TEXT} All contributors (sorted by name) ${NORMAL}"
echo -e "${CYAN_TEXT} ${YELLOW_TEXT} 8)${CYAN_TEXT} Git commits per author ${NORMAL}"
echo -e "${CYAN_TEXT} ${YELLOW_TEXT} 9)${CYAN_TEXT} Git commits per date ${NORMAL}"
echo -e "${CYAN_TEXT} ${YELLOW_TEXT} 10)${CYAN_TEXT} Git commits per month ${NORMAL}"
echo -e "${CYAN_TEXT} ${YELLOW_TEXT} 11)${CYAN_TEXT} Git commits per weekday ${NORMAL}"
echo -e "${CYAN_TEXT} ${YELLOW_TEXT} 12)${CYAN_TEXT} Git commits per hour ${NORMAL}"
echo -e "${CYAN_TEXT} ${YELLOW_TEXT} 13)${CYAN_TEXT} Git commits by author per hour ${NORMAL}"
echo -e "${RED_TEXT} Suggest: ${NORMAL}"
echo -e "${MENU} ${NUMBER} 14)${MENU} Code reviewers (based on git history) ${NORMAL}"
echo -e ""
echo -e "${ENTER_LINE}Please enter a menu option or ${RED_TEXT}press enter to exit. ${NORMAL}"
read opt
echo -e "${CYAN_TEXT} ${YELLOW_TEXT} 14)${CYAN_TEXT} Code reviewers (based on git history) ${NORMAL}"
echo -e "\n${YELLOW_TEXT}Please enter a menu option or ${RED_TEXT}press enter to exit. ${NORMAL}"
read -r opt
}
function option_picked() {
COLOR='\033[01;31m'
RESET='\033[00;00m'
MESSAGE=${@:-"${RESET}Error: No message passed"}
echo -e "${COLOR}${MESSAGE}${RESET}"
echo ""
local BOLD=$(tput bold)
local RED_TEXT=$(tput setaf 1)
local COLOR="${BOLD}${RED_TEXT}"
local RESET=$(tput sgr0)
local MESSAGE=${*:-"${RESET}Error: No message passed"}
echo -e "${COLOR}${MESSAGE}${RESET}\n"
}
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
@@ -154,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
}
@@ -183,26 +194,29 @@ 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:"
else
option_picked "Git commits by hour for author '$author':"
_author="--author=$author"
fi
echo -e "\thour\tsum"
for i in `seq -w 0 23`
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)"
@@ -213,11 +227,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
}
@@ -269,8 +285,9 @@ 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
@@ -287,6 +304,9 @@ function changelogs() {
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
@@ -347,11 +367,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