#!/bin/sh
############################################################ IDENT(1)
#
# $Title: Script to count perforce user commits by-year $
#
############################################################ GLOBALS
pgm="${0##*/}" # Program basename
#
# Global exit status
#
SUCCESS=0
FAILURE=1
#
# Command-line options
#
NOHEADER= # -H
ONELINE= # -1
PAST365= # -Y
REVERSE= # -r
VERBOSE= # -v
YEARS= # -y years
#
# Miscellaneous
#
NEWESTYEAR=
OLDESTYEAR=
USER_YEARS=
THIS_YEAR=$( date +%Y )
RANGE365=$( date +"@%m/%d/$(( $THIS_YEAR - 1 )),@now" )
############################################################ FUNCTIONS
usage()
{
local fmt="$1"
exec >&2
if [ "$fmt" ]; then
shift 1 # fmt
printf "$pgm: $fmt\n" "$@"
fi
local optfmt="\t%-9s %s\n"
printf "Usage: %s [OPTIONS] [user ...]\n" "$pgm"
printf "OPTIONS:\n"
printf "$optfmt" -1 "Output data as a single-line for each user/year."
printf "$optfmt" -H "Don't print a header when \`-Y' is given."
printf "$optfmt" -r "List years in reverse order (oldest first)."
printf "$optfmt" -v "Verbose. Show years where user made zero commits."
printf "$optfmt" "-y year" \
"Specify years to list stats for (default all years)."
printf "$optfmt" "" "This option can be specified multiple times."
printf "$optfmt" -Y "Report number of commits made in past 365 days."
printf "$optfmt" "" "Mutually exclusive to \`-y year'."
exit $FAILURE
}
get_user_years()
{
local user="$1" user_newest user_oldest date year
USER_YEARS=
NEWESTYEAR=
OLDESTYEAR=
# Base years off of actual user commit range
user_newest=$( p4 changes -u "$user" | awk 'NR==1' )
user_oldest=$( p4 changes -u "$user" | awk 'END{print}' )
if [ ! "$user_newest" ]; then
# No changes by user
if [ "$VERBOSE" ]; then
NEWESTYEAR=$THIS_YEAR
OLDESTYEAR=$THIS_YEAR
USER_YEARS=$THIS_YEAR
fi
elif [ "$user_newest" = "$user_oldest" ]; then
# User has made exactly one change
date="${user_newest#* on }"
NEWESTYEAR="${date%%/*}"
OLDESTYEAR=$NEWESTYEAR
USER_YEARS=$NEWESTYEAR
else
# User has made multiple changes
if [ "$VERBOSE" ]; then
date="${user_newest#* on }"
NEWESTYEAR="${date%%/*}"
date="${user_oldest#* on }"
OLDESTYEAR="${date%%/*}"
if [ "$REVERSE" ]; then
USER_YEARS=$( seq $OLDESTYEAR 1 $NEWESTYEAR )
else
USER_YEARS=$( seq $NEWESTYEAR -1 $OLDESTYEAR )
fi
else
if [ "$REVERSE" ]; then
USER_YEARS=$( p4 changes -u "$user" |
awk '$0=substr($4,1,4)' | sort -un )
OLDESTYEAR=$( echo $USER_YEARS | head -1 )
NEWESTYEAR=$( echo $USER_YEARS | tail -1 )
else
USER_YEARS=$( p4 changes -u "$user" |
awk '$0=substr($4,1,4)' | sort -unr )
NEWESTYEAR=$( echo $USER_YEARS | head -1 )
OLDESTYEAR=$( echo $USER_YEARS | tail -1 )
fi
fi
fi
if [ "$VERBOSE" ]; then
year=$NEWESTYEAR
while [ $year -lt $THIS_YEAR ]; do
year=$(( $year + 1 ))
if [ "$REVERSE" ]; then
USER_YEARS="$USER_YEARS $year"
else
USER_YEARS="$year $USER_YEARS"
fi
done
fi
[ "$USER_YEARS" ] # return status
}
type tac > /dev/null 2>&1 || tac(){ tail -r "$@"; }
############################################################ MAIN
#
# Command-line options
#
while getopts 1Hrvy:Y flag; do
case "$flag" in
1) ONELINE=1 ;;
H) NOHEADER=1 ;;
r) REVERSE=1 ;;
v) VERBOSE=1 ;;
y) [ "$PAST365" ] && usage "cannot specify both \`-y year' and \`-Y'"
[ "$OPTARG" = "${OPTARG%[!0-9]*}" -a ${#OPTARG} -eq 4 ] ||
usage "invalid \`-y' argument -- %s" "$OPTARG"
YEARS="$YEARS $OPTARG" ;;
Y) [ "$YEARS" ] && usage "cannot specify both \`-y year' and \`-Y'"
PAST365=1 ;;
*) usage
esac
done
shift $(( $OPTIND - 1 ))
#
# Validate command-line arguments
#
for user in "$@"; do
case "$user" in
"") usage "invalid (NULL) user argument" ;;
*[#@]*) usage "Revision chars (@, #) not allowed in '%s'." "$user" ;;
*[*]*) usage "Wildcard (*) not allowed in user '%s'." "$user" ;;
*[^\ !\"#$%\&\'\(\)+,./0-9:\;\<=\>?A-Z\[\\\]^_\`a-z{\|}~-]*)
usage "Non-printable characters not allowed in '%s'." "$pgm" ;;
esac
done
#
# Reverse `-y year' arguments if `-r' is given
#
[ "$REVERSE" -a "$YEARS" ] && YEARS=$( echo $YEARS | xargs -n1 | tac )
# NOTREACHED unless all users and all years are valid
#
# Report commits by-year for each user argument
#
[ "$PAST365" -a ! "$NOHEADER" ] &&
echo "+++ Per-user statistics for: p4 changes $RANGE365" >&2
[ $# -gt 0 ] || set -- $( p4 users | awk '$0=$1' | sort )
for user in "$@"; do
USER_YEARS="$YEARS"
[ "$PAST365" -o "$USER_YEARS" ] || get_user_years "$user" || continue
[ "$ONELINE" ] || print_header=1
for year in $USER_YEARS; do
# NOTREACHED if `-Y' given
ncommits=$( p4 changes -u "$user" @01/01/$year,@12/31/$year |
awk 'END{print NR}' )
[ $ncommits -gt 0 -o "$VERBOSE" ] || continue
if [ "$print_header" ]; then
print_header=
printf "+++ Commits by %s:\n" "$user"
fi
if [ "$ONELINE" ]; then
printf "%8u y%4u %s\n" $ncommits $year "$user"
else
printf "\t... in the year %u: %u\n" $year $ncommits
fi
done
if [ "$PAST365" ]; then
# NOTREACHED if `-y year' given
ncommits=$( p4 changes -u "$user" "$RANGE365" |
awk 'END{print NR}' )
[ $ncommits -gt 0 -o "$VERBOSE" ] &&
printf "%8u %s\n" $ncommits "$user"
fi
done
exit $SUCCESS
################################################################################
# END
################################################################################
#
# $Copyright: 2015 Devin Teske. All rights reserved. $
#
# $Header: //guest/freebsdfrau/p4t/libexec/year#2 $
#
################################################################################