gitchangelog.sh: state inside comments that GNU sed is required
[cdimgtools:cdimgtools.git] / gitchangelog.sh
1 #!/bin/sh
2 # gitchangelog.sh - process a Git log to extract a GNU-like changelog
3 # Copyright © 2013 Géraud Meyer <graud@gmx.com>
4 #   This program is free software; you can redistribute it and/or modify
5 #   it under the terms of the GNU General Public License version 2 as
6 #   published by the Free Software Foundation.
7 #
8 #   This program is distributed in the hope that it will be useful, but
9 #   WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10 #   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
11 #   for more details.
12 #
13 #   You should have received a copy of the GNU General Public License along
14 #   with this program.  If not, see <http://www.gnu.org/licenses/>.
15
16 PROGRAM_NAME="gitchangelog.sh"
17 PROGRAM_VERSION="1.0"
18 # Requirements:
19 #   GNU sed is required.  To modify for BSD sed, you need:
20 #   - to replace command-separating semicolons by literal newlines,
21 #   - to replace C-escapes in substitution texts by literals (or backslash
22 #     followed by a literal in the case of \n),
23 #   - to replace, in RE patterns, C-escapes different from \n by literals and
24 #     the space class \s by an explicit bracket list.
25 #   - to replace, in RE patterns, \+ by \{1,\}
26 # Usage:
27 #   gitchangelog.sh [<options>] [--] [ {-|<outfile>} [ {-|<git_log_args>} ] ]
28
29 # parameters
30 GITBODY= NO_GITBODY=yes
31 BLANKLINE=yes
32 TAGS=
33 TAG_PATTERN='[^\n]\+'
34 MERGE=
35 TITLE= NO_TITLE=yes
36 while [ $# -gt 0 ]
37 do
38         case $1 in
39         --tags)
40                 TAGS=yes ;;
41         --tag-pattern)
42                 shift; TAG_PATTERN=${1-} ;;
43         --merge)
44                 MERGE=yes ;;
45         --title-only)
46                 TITLE=yes NO_TITLE= ;;
47         --git-body)
48                 GITBODY=yes NO_GITBODY= ;;
49         --no-blankline)
50                 BLANKLINE= ;;
51         --version)
52                 echo "$PROGRAM_NAME version $PROGRAM_VERSION"
53                 exit ;;
54         --?*)
55                 echo "$0: unknown option $1" >&2
56                 exit 255 ;;
57         --)
58                 shift; break ;;
59         *)
60                 break ;;
61         esac
62         shift
63 done
64 # git repository check
65 test x"${2-}" != x"-" &&
66 test ! -d .git && ! git rev-parse --git-dir >/dev/null &&
67 {
68         echo "$0: error not in a git repository" >&2
69         exit 255
70 }
71 # output file
72 test $# -gt 0 &&
73 {
74         test x"${1-}" != x"-" &&
75         exec >"$1"
76         shift
77 }
78
79 # input source
80 if test x"${1-}" = x"-"
81 then cat
82 else git log --date=short ${TAGS:+--decorate} ${1+"$@"}
83 fi |
84 # processing
85 LC_ALL=C sed \
86   -e '# Put the tags in the hold space
87       /^commit / {
88         s/^commit [a-zA-Z0-9]\+//
89         s/^ \+(\(.*\))$/, \1/; s/, /\n/g
90         # conditionnal branch to reset
91         s/^/\n/; t a
92         :a; s/\n$//; t e
93             s/\(.*\)\ntag: \('"$TAG_PATTERN"'\)$/[\2]\n\1/; t a
94             s/\(.*\)\n.*$/\1/; t a
95         :e; s/\n/ /g; h; d
96       }' \
97   -e '# Add the merge marker to the hold space
98       /^Merge: / { '${MERGE:+'x; s/$/{M} /; x;'}' d; }' \
99   -e '/^Author:/ {
100         # Process author, date, tag
101        '${TAGS:+'x; /^$/! { s/\s*$//; s/$/\n/; }; x; b s;'}' x; s/.*//; x '${TAGS:+'; :s'}'
102         N; G; s/^Author:\s*\([^\n]*\) \s*\(<[^ \n]*>\)\s*\nDate:\s*\([^\n]*\)\n\(.*\)/\4\3  \1  \2\n/
103         # Process title
104         n; N; s/[^\n]*\n    /\t'${TITLE:+${NO_GITBODY:+'* '}}'/
105         # If non empty body, print an extra line
106         n; '${NO_TITLE:+${NO_GITBODY:+${BLANKLINE:+'/^$/! { s/^    /\t/p; s/^\t/    /; }'}}}'
107       }' \
108   ${TITLE:+-e '/^    / d'} \
109   -e '# First line of the paragraph
110       :b; /^    $/ { N; s/^    \n//; s/^    \(.\)/'${GITBODY:+'\t\n'}'\t'${NO_GITBODY:+'* '}'\1/; b b; }' \
111   -e '# Rest of the paragraph
112       s/^    /\t'${NO_GITBODY:+'  '}'/' \
113   -e '# Reset the hold space for the next entry
114       /^$/ h'
115 rc=$?
116 # error check
117 test $rc -eq 0 ||
118 echo "$0: ERROR sed failed with #$rc" >&2
119 exit $rc