160 lines
4.3 KiB
Bash
Executable File
160 lines
4.3 KiB
Bash
Executable File
#!/bin/bash
|
|
# vi:ts=4
|
|
#
|
|
# mkChangLog - produce a ChangeLog from git history on stdout
|
|
#
|
|
# SYNOPSIS
|
|
# mkChangeLog [OPTION]
|
|
#
|
|
# DESCRIPTION
|
|
# Extract commit comments and label each tag with a date
|
|
# from most recent to oldest.
|
|
# Default output is suitable for including in markdown files
|
|
#
|
|
# -c curRev - use CurRev as tag name if current rev (latest commit) has no tag
|
|
#
|
|
# -s stopRev - will stop the log with the specified tag
|
|
# changelog will not show commit messages earlier than the stopRev tag
|
|
# To indicate stopping at very first tag, use -
|
|
#
|
|
# -H heading - use heading instead of "CHANGELOG" for heading1 of log
|
|
#
|
|
# -h heading - use heading instead of "------------" for heading2 of log
|
|
#
|
|
# AUTHOR
|
|
# Bill Perry bperrybap@opensource.billsworld.billandterrie.com
|
|
# 2016-08-08
|
|
#
|
|
# NOTES:
|
|
# The reason for the curRev option is that when creating a changelog file that
|
|
# needs to be part of a tagged revision, there is a chicken & egg problem of
|
|
# how do you create the changelog for that revision and also set the tag for
|
|
# the revision that includes the updated changelog file?
|
|
# If you set the tag to get the changelog output to include the new tag, then
|
|
# when you commit the changelog file created from the log output, there is an
|
|
# additional commit that affects the log and the log file for the commit is
|
|
# *after* the tag instead of being at the tag.
|
|
# The answer to this dilema: "CHEAT" a bit.
|
|
# So the curRev option will fake the tagname on the most recent commits since
|
|
# the previous tag to be the name "curRev" even though the tag has not yet been
|
|
# set. There is still one limitation the commit log message for updating the
|
|
# changelog file will not be shown for the changes associated with the new tag.
|
|
# There is no way to work around this.
|
|
# However, the log message entry will show when the next tag is created, so it
|
|
# is only the most recent tag that will be missing the commit message for the
|
|
# changelog file update.
|
|
#
|
|
# This allows a process of:
|
|
#
|
|
# - generate the ChangeLog with curRev as tag about to be created
|
|
# - commit ChangeLog
|
|
# - tag with the tag used as curRev
|
|
#
|
|
# This will create a single commit as well as the desired tag pointing
|
|
# to the commit that contains the log for new tag.
|
|
#
|
|
#
|
|
|
|
pname=`basename $0`
|
|
|
|
HEADING1="CHANGELOG"
|
|
HEADING2="----------------------"
|
|
|
|
function USAGE {
|
|
printf "usage:\n"
|
|
printf "$pname [option]\n"
|
|
printf "\t-c curRev\n\t\tuse CurRev as tagname if current rev has no tag\n"
|
|
printf "\t-s stopRev\n\t\tno log output prior to stopRev tag\n"
|
|
printf "\t-H heading\n\t\tuse heading instead of \"$HEADING1\" for heading1 of log\n"
|
|
printf "\t-h heading\n\t\tuse heading instead of \"$HEADING2\" for heading2 of log\n"
|
|
}
|
|
|
|
# check for arguments
|
|
while getopts ":s:c:H:h:" opt; do
|
|
case $opt in
|
|
c)
|
|
curRev=$OPTARG
|
|
;;
|
|
s)
|
|
stopRev=$OPTARG
|
|
;;
|
|
H)
|
|
HEADING1=$OPTARG
|
|
;;
|
|
h)
|
|
HEADING2=$OPTARG
|
|
;;
|
|
\?)
|
|
echo "$pname: invalid option: -$OPTARG" >&2
|
|
USAGE
|
|
exit 1
|
|
;;
|
|
:)
|
|
echo "Option -$OPTARG requires an argument." >&2
|
|
USAGE
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
|
|
|
|
# if stopRev is "-" then use first tag in repo
|
|
if [ "$stopRev" = "-" ]
|
|
then
|
|
stopRev=$(git tag -l | head -1)
|
|
fi
|
|
|
|
#now generate the change log
|
|
|
|
# if headings are empty, don't output them
|
|
if [ "$HEADING1" != "" ]
|
|
then
|
|
echo "$HEADING1"
|
|
fi
|
|
if [ "$HEADING2" != "" ]
|
|
then
|
|
echo "$HEADING2"
|
|
fi
|
|
|
|
git for-each-ref --sort='*authordate' --format='%(tag)' refs/tags |tac |grep -v '^$' | while read TAG ; do
|
|
echo
|
|
if [ $NEXT ];then
|
|
rev=$NEXT
|
|
else
|
|
if [ "$curRev" != "" ]
|
|
then
|
|
rev=$curRev
|
|
else
|
|
rev=`git describe --dirty`
|
|
fi
|
|
fi
|
|
if [ "$rev" != "$TAG" ]
|
|
then
|
|
echo [$rev] - `git log -1 --format=%ad --date=short $NEXT`
|
|
if [ "$rev" = "$stopRev" ]
|
|
then
|
|
# note: the exit below exits the loop command not the script
|
|
# the exit value will be the status code of the loop
|
|
exit 9
|
|
fi
|
|
GIT_PAGER=cat git log --no-merges --format=" * %s" $TAG..$NEXT
|
|
fi
|
|
NEXT=$TAG
|
|
done
|
|
|
|
# if loop exited because it stopped early from a stopRev, status will be non zero
|
|
# so exit script
|
|
if [ $? -ne 0 ]
|
|
then
|
|
exit 0
|
|
fi
|
|
FIRST=$(git tag -l | head -1)
|
|
echo
|
|
echo [$FIRST] - `git log -1 --format=%ad --date=short $FIRST`
|
|
if [ "$FIRST" = "$stopRev" ]
|
|
then
|
|
exit 0
|
|
fi
|
|
# if this GIT_PAGER below is commented out then the logs for the first tag are not emitted
|
|
GIT_PAGER=cat git log --no-merges --format=" * %s" $FIRST
|