2 # Copyright © 2013,2014 Géraud Meyer <graud@gmx.com>
4 # This program is free software; you can redistribute it and/or modify it under
5 # the terms of the GNU General Public License version 2 as published by the
6 # Free Software Foundation.
8 # This program is distributed in the hope that it will be useful, but WITHOUT
9 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
10 # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
13 # You should have received a copy of the GNU General Public License along with
14 # this program. If not, see <http://www.gnu.org/licenses/>.
16 PROGRAM_NAME
="gitchangelog.sh"
21 gitchangelog.sh - portable script generating a GNU-like changelog from a Git log
23 gitchangelog.sh [<options>] [--] [ {-|<outfile>} [<git_log_args>] ]
24 gitchangelog.sh [<options>] [--] {-|<outfile>} -
27 Prepend changelog entries by tag names in brackets.
28 --tag-pattern <sed_BRE>
29 Tags to consider for marking entries. The pattern should not match
30 across spaces; the default is "[^ ]\{1,\}".
32 Prepend changelog entries by merge marks.
34 Only keep the title of a commit. This implies --title-star, that can
35 be disabled by a supplemental --git-body.
37 Prepend the title by a star as is done with the other paragraphs.
39 Do not reformat the commit message, only reindent it.
41 Do not separate the title from the rest by a blank line.
50 Each commit message is made into a changelog entry. Each paragraph of a
51 Git commit message body is made into a star item of the changelog. The
52 message title is kept on a separate line. Text lines are never broken nor
55 By default git is run to get the log
, with the required options. If a dash
56 is given
in place of additional
<git_log_args
>, then the log is
read from
57 the standard input
; in that
case pass the option
--date=short and possibly
58 also
--decorate to git to get the appropriate log format.
60 The
script is portable to POSIX sh and to other
less comformant shells such
63 The
sed code is portable to POSIX
sed but requires only Simple Regular
64 Expressions
(SRE
) instead of Basic Regular Expressions
(BRE
) which makes it
65 prone to work under Solaris and old BSDs. git-log is required
if the log
66 is not
read from stdin.
68 The
exit status of
sed is returned
if it fails
; otherwise the one of the
69 command generating the git log
(git or
cat) is returned.
71 $ .
/gitchangelog.sh
--title-star --no-blankline GNUChangeLog
72 $ .
/gitchangelog.sh
--tags --tag-pattern 'release\/[^ ]*' -- - --date-order |
73 sed 's/^\[release/^L\[release/' > ChangeLog
74 $ git log
--date=short
--decorate --first-parent |
75 .
/gitchangelog.sh
--merge ChangeLog
-
77 gitchangelog.sh was written by G.raud Meyer.
84 GITBODY
= NO_GITBODY
=yes
97 shift; TAG_PATTERN
=${1-} ;;
101 TITLE
=yes NO_TITLE
= TITLESTAR
=yes ;;
105 GITBODY
=yes NO_GITBODY
= ;;
109 echo "$PROGRAM_NAME version $PROGRAM_VERSION"
114 help_message
; exit ;;
116 echo "$0: unknown option $1" >&2
126 [ -n "$TAGS" ] ||
[ -n "$MERGE" ] && ANNOTATE
=yes
127 # git repository check
128 test x
"${2-}" != x
"-" &&
129 if test -d .git || git rev-parse
--git-dir >/dev
/null
132 echo >&2 "$0: ERROR not in a git repository"
138 test x
"${1-}" != x
"-" &&
146 # Some shells, like the family of pdksh, behave differently regarding
147 # the backslash in variable substitutions inside a here document.
150 # pdksh and posh do not keep a newline preceded by a backslash inside a
151 # single quoted string inside two levels of command substitution (when the
152 # second level is double quoted).
153 exec 4>&1 # to pass stdout to the following process substitution
154 eval "$( exec 3>&1 1>&4 4>&- # eval will set $gitrc and $rc
155 if test x"${1-}" = x"-"
156 then cat; echo >&3 gitrc=$?
157 else git log --date=short ${ANNOTATE:+--decorate} ${1+"$@"}; echo >&3 gitrc=$?
160 LC_ALL=C sed -e "$(# Transform the GNU sed program into a more portable one
161 LC_ALL=C sed -e 's
/\\s
/[ \\t
]/g
167 # Put the tags in the hold space
170 s
/^commit
[a-zA-Z0-9
]\
+//; s
/^ \
+(\
(.
*\
))\$
/, \
1/
172 # conditionnal branch to reset
173 ${TAGS:+t a;} s
/.
*//; t e
174 # extract the desired tags
176 s
/\
(.
*\
)\n tag
: \
($TAG_PATTERN\
)\$
/[\
2]@n\
1/; t a
177 s
/\
(.
*\
)\n [^
]*\$
/\
1/; t a
178 s
/\
(.
*\
)\n [a-zA-Z
]\
+: *[^
]*\$
/\
1/; t a
181 # Add the merge marker to the hold space
182 /^Merge
: / { ${MERGE:+x; s/\$/${B}M$b /; x;} d
; }
184 # Process author, date, tag
185 ${ANNOTATE:+x; s/${s}s*\$/@n/; x; b s;} x
; s
/.
*/@n
/; x
${ANNOTATE:+; :s}
186 N
; G
; s
/^Author
:\s
*\
(.
*\
) \s
*\
(<[^
<>]*>\
)\s
*\nDate
:\s
*\
(.
*\
)\n\
(.
*\n\
)\$
/\
4\
3 \
1 \
2@n
/
189 n
; N
; s
/^.
*\n /\t${TITLESTAR:+${NO_GITBODY:+* }}/
190 t t
; :t
; n
; s
/^ \
(.\
+\
)\$
/\t${TITLESTAR:+${NO_GITBODY:+ }}\
1/; t t
191 # If non empty body, print an extra line
192 ${NO_TITLE:+${NO_GITBODY:+${BLANKLINE:+/^\$/ !$B s/^ /${s}t/p; s/^${s}t/ /; $b}}}
195 # First line of the paragraph
196 :b
; /^ \$
/ { N
; s
/^
\n//; s
/^ \
(.\
)/${GITBODY:+${s}t@n}\t${NO_GITBODY:+* }\1/; b b; }
197 # Rest of the paragraph
198 s
/^
/\t${NO_GITBODY:+ }/
199 # Reset the hold space for the next entry
209 echo >&2 "$0: ERROR git or cat failed with #$gitrc"
211 { echo >&2 "$0: ERROR sed failed with #$rc"; exit $rc; }