String helper for printing indented text
[platform/upstream/libzypp.git] / mkChangelog
1 #! /bin/bash
2
3 function Recho() { echo -e "\e[0;31m""$@""\e[0m"; }
4 function Gecho() { echo -e "\e[0;32m""$@""\e[0m"; }
5 function Becho() { echo -e "\e[0;34m""$@""\e[0m"; }
6
7 function errexit() {
8   exec >&2
9   Recho "Error: $@"
10   exit 1
11 }
12
13 function usage() {
14   exec >&2
15   cat <<EOF
16   Usage:
17         $(basename $0) [OPTIONS]
18
19   Options:
20         -h,-?,--help    This page.
21         -n              Dryrun.
22
23 Prepare a new changes file entry preloaded with all commits since the last
24 changes tag and load it into \$EDITOR (vi). If the version file was changed,
25 optionally submitt and tag the new changes. Otherwise simply leave the changes
26 in place.
27
28 Don't forgett to push created tags as well: git push --tags
29
30 EOF
31   exit 1
32 }
33
34 DRYRUN=0
35
36 case "$1" in
37   -[n]*)
38     DRYRUN=1
39     ;;
40   -[hH?]*)
41     usage
42     ;;
43   --help)
44     usage
45     ;;
46 esac
47
48
49 export LC_ALL=""
50 export LANG="en"
51 EDITOR=${EDITOR:-vi}
52
53 EMAIL="$(git config --get user.email)"
54
55 CHANGESFILE=$(ls package/*.changes)
56 test -f "$CHANGESFILE" || errexit "No changes file '$CHANGESFILE'"
57
58 VERSIONFILE="VERSION.cmake"
59 test -f "$VERSIONFILE" || errexit "No version file '$VERSIONFILE'"
60
61 function getversion() {
62   cat "$VERSIONFILE" \
63   | awk '
64   function getnum() {
65     gsub("^[^\"]*\"","")
66     gsub("\".*$","")
67   }
68   /^ *SET *\( *LIBZYPP_MAJOR *"[0-9]+" *\)/       {getnum();major=$0}
69   /^ *SET *\( *LIBZYPP_MINOR *"[0-9]+" *\)/       {getnum();minor=$0}
70   /^ *SET *\( *LIBZYPP_PATCH *"[0-9]+" *\)/       {getnum();patch=$0}
71   /^ *SET *\( *LIBZYPP_COMPATMINOR *"[0-9]+" *\)/ {getnum();compatminor=$0}
72   /^# LAST RELEASED:/ {
73       gsub("^.*RELEASED: *","");
74       gsub(" +$","");
75       lastcompat=$0
76       gsub(".*\\(","",lastcompat)
77       gsub("\\).*","",lastcompat)
78       gsub(" +\\(.*","");
79       lastrelease=$0
80   }
81   END {
82     thisrelease = major"."minor"."patch" ("compatminor")"
83     printf "LAST_RELEASE='%s'\n", lastrelease
84     printf "LAST_COMPAT='%s'\n", lastcompat
85     printf "THIS_RELEASE='%s'\n", major"."minor"."patch
86     printf "THIS_COMPAT='%s'\n", compatminor
87     printf "THIS_MINOR='%s'\n", minor
88     printf "THIS_PATCH='%s'\n", patch
89   }
90   '
91 }
92
93 function setversion() {
94   local KEY="$1"
95   local VAL="$2"
96   sed -i "s/^ *SET *( *${KEY} .*/SET(${KEY} \"${VAL}\")/" "$VERSIONFILE"
97 }
98
99 function sameVersion() {
100   test "$LAST_RELEASE" == "$THIS_RELEASE" -a "$LAST_COMPAT" == "$THIS_COMPAT"
101 }
102
103 function getchanges() {
104   git log --no-merges --pretty=format:'- %s' "$LAST_RELEASE"..HEAD | grep -v 'po.tar.bz2'
105 }
106
107 function newchangesentry() {
108   echo "-------------------------------------------------------------------"
109   echo "$(date) - $EMAIL"
110   echo ""
111   echo "$(getchanges)"
112   sameVersion || {
113     echo "- version $THIS_RELEASE ($THIS_COMPAT)"
114   }
115   echo ""
116 }
117
118 function is_fast_forward() {
119   git fetch
120   test "$(git rev-list HEAD..origin/$(git name-rev --name-only HEAD) --count)" == "0"
121 }
122
123 is_fast_forward || {
124   Recho "!!!"
125   Recho "!!! Branch is not fast-forward. Pull changes first."
126   Recho "!!!"
127   exit 7
128 }
129
130 git status --porcelain | grep '^[^ ?]' | grep -v "$VERSIONFILE\|$CHANGESFILE" && {
131   Becho "!!! Files other than version and changes are added to the index."
132   Becho "!!! Doing dryrun..."
133   DRYRUN=1
134 }
135
136 # A tag for $LAST_RELEASE must exist!
137 eval $(getversion)
138 git rev-parse -q --verify "$LAST_RELEASE" >/dev/null || {
139   Recho "!!!"
140   Recho "!!! There is no LAST_RELEASE tag '$LAST_RELEASE'. Check manually. "
141   Recho "!!! (git tag -m 'tagging $LAST_RELEASE' '$LAST_RELEASE' ?commit?)"
142   Recho "!!!"
143   exit 8
144 }
145
146 if [ "$DRYRUN" == "1" ]; then
147   newchangesentry
148   sameVersion && {
149     Becho "!!! Version is unchanged at $LAST_RELEASE ($LAST_COMPAT)."
150   }
151   exit 0
152 fi
153
154 # check version file
155 #
156 while true; do
157   # $LAST_RELEASE
158   # $LAST_COMPAT
159   # $THIS_RELEASE
160   # $THIS_COMPAT
161   sameVersion && {
162     newchangesentry
163     Becho "!!! Version is unchanged at $LAST_RELEASE ($LAST_COMPAT)."
164     read -n 1 -p "$(Gecho "(a)bort, (c)ontinue, (P) patch, (M) minor, (I) incompat minor, (e)dit version [e]: ")" RES
165     echo
166     case "${RES:-e}" in
167       [eE]*)
168         $EDITOR $VERSIONFILE
169         eval $(getversion)
170         continue
171         ;;
172       [cC])
173         Becho "!!! Leave $VERSIONFILE untouched"
174         break
175         ;;
176       [P])
177         setversion LIBZYPP_PATCH $(($THIS_PATCH + 1))
178         eval $(getversion)
179         continue
180         ;;
181       [M])
182         setversion LIBZYPP_MINOR $(($THIS_MINOR + 1))
183         setversion LIBZYPP_PATCH 0
184         eval $(getversion)
185         continue
186         ;;
187       [I])
188         setversion LIBZYPP_COMPATMINOR $(($THIS_MINOR + 1))
189         setversion LIBZYPP_MINOR $(($THIS_MINOR + 1))
190         setversion LIBZYPP_PATCH 0
191         eval $(getversion)
192         continue
193         ;;
194       *)
195         errexit "aborted"
196         ;;
197     esac
198   }
199   break
200 done
201
202 # prepare changes file
203 #
204 TMPFILE=$(mktemp)
205 trap " [ -f \"$TMPFILE\" ] && /bin/rm -f -- \"$TMPFILE\" " 0 1 2 3 13 15
206 { newchangesentry; cat $CHANGESFILE; } >$TMPFILE
207
208 RES=e
209 while [ "$RES" == "e" ]; do
210   $EDITOR $TMPFILE
211   echo
212   awk '{print}/^----------/{n=n+1; if ( n == 2 ) exit 0; }' $TMPFILE
213   read -n 1 -p "$(Gecho "(a)bort, (c)ontinue, (s)ubmitt, (e)dit [e]: ")" RES
214   echo
215   case "${RES:-e}" in
216     [eE]*)
217       RES=e
218       ;;
219     [cCsS])
220       Becho "!!! Store new $CHANGESFILE"
221       mv $TMPFILE $CHANGESFILE
222       chmod 644 $CHANGESFILE
223
224       test "$RES" == "s" && {
225         if [ "$LAST_RELEASE" == "$THIS_RELEASE" ]; then
226           git add "$CHANGESFILE" && git commit -m "changes"
227         else
228           Becho "!!! Remember new version $THIS_RELEASE in $VERSIONFILE"
229           sed -i "s/^# LAST RELEASED:.*$/# LAST RELEASED: $THIS_RELEASE ($THIS_COMPAT)/" $VERSIONFILE
230           if git add "$CHANGESFILE" "$VERSIONFILE" \
231                 && git commit -m "changes $THIS_RELEASE ($THIS_COMPAT)" \
232                   && git tag -m "tagging $THIS_RELEASE" "$THIS_RELEASE" HEAD; then
233             Becho "!!!"
234             Becho "!!! Do not forget to push the commit and the tag: $(Gecho git push --tags origin HEAD)"
235             Becho "!!!"
236           else
237             Recho "!!!"
238             Recho "!!! Commit failed. Check manually. (git reset HEAD~)"
239             Recho "!!!"
240             exit 9
241           fi
242         fi
243       }
244       ;;
245     *)
246       Becho "!!! Leave $CHANGESFILE untouched"
247       ;;
248   esac
249 done