ivi-resource-manager: fix out-of-bounds access in screen.c
[profile/ivi/murphy.git] / build-aux / prepare-release.sh
1 #!/bin/bash
2
3 # This needs a bit more work, mostly on the "discplined engineering" front.
4 # IOW, instead of this UPSTREAM_BASE hack it would be better to have 3
5 # branches:
6 #   1) pristine upstream: for tracking upstream progress/retrogression
7 #   2) patched upstream: pristine upstream with our patches applied
8 #   3) working local: patches upstream + a set of scripts (like this) to
9 #      do everyday stuff like making new releases, exporting stuff to
10 #      OBS, etc...
11
12 # show help on usage and exit
13 usage() {
14     echo ""
15     echo "usage: $0 [options]"
16     echo "The possible options are"
17     echo "  -n <name>             name of the package"
18     echo "  -v <version>          version to give to this release"
19     echo "  --release <gitrev>    git branch, tag or SHA1 to release"
20     echo "  --baseline <base>     use <base> as baseline for release"
21     echo "  --obs                 prepare for OBS release"
22     echo "  --gerrit-review       prepare for gerrit review"
23     echo "  --gerrit-release      prepare for gerrit release"
24     echo ""
25     echo "<name> is the name of the package. <version> is the version you want"
26     echo "to give to this release in RPM. <gitrev> is the actual git version"
27     echo "(typically tag, branch, or SHA1) you want to release. If <base> is"
28     echo "specified the release will contain a set of patches on top of this"
29     echo "baseline. Otherwise no patches will be generated. If --obs is given"
30     echo "the relase will be generated in a format (spec, tarball + patches)"
31     echo "suitable for importing to OBS. If --gerrit-review or --gerrit-release"
32     echo "is used, the release will be generated as a branch suitable to be"
33     echo "pushed to gerrit for review or review-bypassing release."
34     echo ""
35     echo "Examples:"
36     echo "Prepare a branch of 'HEAD' for gerrit review as 0.0.9:"
37     echo "    $0 --release HEAD -v 0.0.9 --gerrit-review"
38     echo ""
39     echo "Prepare a branch of 'tizen' for gerrit release as 0.10.1:"
40     echo "    $0 --release tizen -v 0.10.1 --gerrit-release"
41     echo ""
42     echo "Prepare directory obs-0.5.0 from 'foobar' suitable for exporting"
43     echo "to OBS as version 0.5.0:"
44     echo "    $0 --release foobar -v 0.5.0 --baseline foo"
45     echo ""
46     echo "<name> defaults to $(basename $(pwd))"
47     echo "<release> defaults to HEAD"
48     echo "<version> defaults to $(default_version)"
49     echo ""
50     exit 0
51 }
52
53 # emit an error message to stderr
54 error() {
55     echo "error: $*" 1>&2
56 }
57
58 # emit an info message to stdout
59 info() {
60     echo "$*"
61 }
62
63 # emit a warning message to stderr
64 warning() {
65     echo "warning: $*" 1>&2
66 }
67
68 # indent piped output
69 indent() {
70     local _prefix="${1:-    }"
71
72     sed "s/^/$_prefix/g"
73 }
74
75 # record an undo action
76 record_undo() {
77     if [ -n "$UNDO" ]; then
78         UNDO="$*;$UNDO"
79     else
80         UNDO="$*"
81     fi
82 }
83
84 # execute recorded undo actions
85 execute_undo() {
86     if [ -n "$UNDO" ]; then
87         echo "Executing recorded undo actions."
88         eval $UNDO
89     fi
90
91     echo "Exiting due to errors."
92     exit 1
93 }
94
95 # enable automatic undo
96 enable_auto_undo() {
97     trap undo_execute ERR
98     set -e
99     set -o pipefail
100 }
101
102 # generate default version number
103 default_version() {
104     echo "$(date +'%Y%m%d')"
105 }
106
107 # generate a tarball for a given package and version from git to a directory
108 generate_tarball() {
109     local _pkg="$1" _pkgversion="$2" _gitversion="$3" _dir="$4"
110     local _tarball="$_dir/$_pkg-$_pkgversion.tar"
111
112     info "* Generating tarball $_tarball.gz..."
113     git archive --format=tar --prefix=$_pkg-$_pkgversion/ \
114         $_gitversion > $_tarball && \
115     gzip $_tarball
116 }
117
118 # generate patches to a directory against a baseline, print list of patches
119 generate_patches() {
120     local _baseline="$1" _head="$2" _dir="$3" _patchret="$4" _patchlist
121
122     info "* Generating patches from $_baseline till $_head..." 1>&2
123     pushd $_dir >& /dev/null && \
124         _patchlist="`git format-patch -n $_baseline..$_head`" && \
125     popd >& /dev/null
126
127     if [ -n "$_patchret" ]; then
128         eval "$_patchret=\"$_patchlist\""
129     else
130         echo "$_patchlist"
131     fi
132 }
133
134 # generate a spec file from a spec template filling in version and patches
135 generate_specfile() {
136     local _specin="$1" _specout="$2" _version="$3" _patchlist
137
138     shift 3
139     _patchlist="$*"
140
141     info "* Generating spec file $_specout (from $_specin)..."
142
143     cat $_specin | sed "s/@VERSION@/$_version/g" > $_specout.tmp && \
144     cat $_specout.tmp | while read -r line; do
145         case $line in
146         @DECLARE_PATCHES@)
147             i=0
148             for patch in $_patchlist; do
149                 echo "Patch$i: $patch"
150                 let i=$i+1
151             done
152             ;;
153         @APPLY_PATCHES@)
154             i=0
155             for patch in $_patchlist; do
156                 echo "%patch$i -p1"
157                 let i=$i+1
158             done
159             ;;
160         *)
161             echo "$line"
162             ;;
163         esac
164     done > $_specout && \
165     rm -f $_specout.tmp
166 }
167
168 # generate a changelog for the release (with no real changelog content)
169 generate_changelog() {
170     local _chlog="$1" _version="$2" _gitver="$3" _author="$4"
171     local _sha _last
172
173     info "* Generating changelog $_chlog for version $_version ($_gitver)..." |
174         indent " GENLOG: "
175
176     _last="`git tag -l | grep accepted/$TARGET/ | tail -1`"
177     _sha="`git rev-parse $_gitver`"
178
179     rm -f $_chlog && touch $_chlog
180
181     echo "* $(date '+%a %b %d %H:%M:%S %Z %Y') $_author - $_version" > $_chlog
182     echo "- release: released $_version (git: $_sha)." >> $_chlog
183
184     if [ -n "$_last" ]; then
185         echo "" >> $_chlog
186         git cat-file -p $_last:$_chlog >> $_chlog
187     fi
188
189     vi $_chlog
190 }
191
192 # generate linker scripts
193 generate_linker_scripts() {
194     info "* Generating linker scripts..."
195     ./bootstrap && ./configure && make generate-linker-scripts
196 }
197
198 # generate a release branch
199 generate_branch() {
200     local _br="$1" _rel="$2" _current
201
202     info "* Creating release branch $_br from $_rel..."
203
204     _current="`git_current_branch`"
205
206     git branch $_br $_rel
207     record_undo "git branch -D $_br"
208
209     git checkout $_br
210     record_undo "git checkout $_current"
211 }
212
213 # add files/directories to the repository
214 git_add() {
215     local _msg="$1"
216     shift
217
218     git add $*
219     git commit -n -m "$_msg" $*
220 }
221
222 # add an annotated git tag
223 git_tag() {
224     local _tag="$1" _msg="$2"
225
226     info "* Tagging for release..."
227
228     git tag -a -m "$_msg" $_tag
229     record_undo "git branch -D $_tag"
230 }
231
232 # run package-specific GBS quirks
233 package_gbs_quirks() {
234     local _ld_scripts
235     local _pkg_quirks
236
237     _pkg_quirks="${0%/prepare-release.sh}/gbs-quirks"
238     if [ -f $_pkg_quirks ]; then
239         info "* Running package-specific GBS quirks ($_pkg_quirks)..."
240         source $_pkg_quirks
241     else
242         info "* No package-specific GBS quirks found ($_pkg_quirks)..."
243     fi
244 }
245
246 # parse the command line for configuration
247 parse_configuration() {
248     while [ -n "${1#-}" ]; do
249         case $1 in
250             --name|-n)
251                 if [ -z "$PKG" ]; then
252                     shift
253                     PKG="$1"
254                 else
255                     error "Multiple package names ($PKG, $1) specified."
256                     usage
257                 fi
258                 ;;
259             --version|-v)
260                 if [ -z "$VERSION" ]; then
261                     shift
262                     VERSION="$1"
263                 else
264                     error "Multiple versions ($VERSION, $1) specified."
265                     usage
266                 fi
267                 ;;
268              --release|-R|--head|-H)
269                 if [ -z "$RELEASE" ]; then
270                     shift
271                     RELEASE="$1"
272                 else
273                     error "Multiple git versions ($RELEASE, $1) specified."
274                     usage
275                 fi
276                 ;;
277              --base|--baseline|-B)
278                 if [ -z "$BASELINE" ]; then
279                     shift
280                     BASELINE="$1"
281                 else
282                     error "Multiple git baselines ($BASELINE, $1) specified."
283                     usage
284                 fi
285                 ;;
286              --obs|-O)
287                 OBS="yes"
288                 ;;
289              --gbs*)
290                 if [ -z "$GBS" ]; then
291                     TYPE="${1#--gbs-}"
292                     GBS="yes"
293                 else
294                     error "Multiple --gbs options specified."
295                     usage
296                 fi
297                 ;;
298              --gerrit*|-G)
299                 if [ -z "$GBS" ]; then
300                     TYPE="${1#--gerrit-}"
301                     GBS="yes"
302                 else
303                     error "Multiple --gerrit options specified."
304                     usage
305                 fi
306                 ;;
307              --target|-T)
308                 if [ -z "$TARGET" ]; then
309                     shift
310                     TARGET="$1"
311                 else
312                     error "Multiple targets ($TARGET, $1) specified."
313                     usage
314                 fi
315                 ;;
316              --author|-A)
317                 if [ -z "$AUTHOR" ]; then
318                     shift
319                     AUTHOR="$1"
320                 else
321                     error "Multiple authors ($AUTHOR, $1) specified."
322                     usage
323                 fi
324                 ;;
325              --help|-h)
326                 usage 0
327                 ;;
328              --debug|-d)
329                 set -x
330                 DEBUG=$((${DEBUG:-0} + 1))
331                 ;;
332              *)
333                 error "Unknown option or unexpected argument '$1'."
334                 usage
335                 ;;
336         esac
337         shift
338     done
339 }
340
341 # determine current git branch
342 git_current_branch() {
343     local _br
344
345     _br="`git branch -l | grep '^[^ ]' | cut -d ' ' -f 2`"
346
347     echo "$_br"
348 }
349
350 # prepare for gbs
351 gbs_prepare() {
352     local _dir _specin _specout _chlog _patches
353     local _stamp _branch _tag _remote
354
355     _dir=packaging
356     _specin=packaging.in/$PKG.spec.in
357     _specout=$_dir/$PKG.spec
358     _chlog=$_dir/$PKG.changes
359     _stamp=$(date -u +%Y%m%d.%H%M%S)
360     _branch=release/$TARGET/$_stamp
361     _tag=submit/$TARGET/$_stamp
362
363     case $TYPE in
364         release)  _remote=refs/heads/$TARGET;;
365         review|*) _remote=refs/for/$TARGET;;
366     esac
367
368     mkdir -p $_dir
369     record_undo "rm -fr $TOPDIR/$_dir"
370
371     if [ -z "$BASELINE" ]; then
372         _base=$RELEASE
373         _patches=""
374     else
375         _base=$BASELINE
376         generate_patches $_base $RELEASE $_dir _patches
377         echo "$_patches" | tr -s '\t' ' ' | tr ' ' '\n' | indent "PATCHES: "
378     fi
379
380     generate_specfile $_specin $_specout $VERSION $_patches | indent "GENSPEC: "
381
382     generate_branch $_branch $_base | indent " BRANCH: "
383
384     package_gbs_quirks 2>&1 | indent "QUIRKS: "
385
386     generate_changelog $_chlog $VERSION $RELEASE "$AUTHOR"
387
388     git_add "packaging: added packaging." $_dir | indent " GITADD: "
389
390     git_tag $_tag "Tagged $_stamp ($VERSION) for release to $TARGET." | \
391         indent "GITTAG: "
392
393     info ""
394     info "Branch $_branch prepared for release. Please check if"
395     info "everything looks okay. If it does, you can proceed with the"
396     info "release by executing the following commands:"
397     info ""
398     info "    git push <remote-repo> $_branch:$_remote"
399     info "    git push <remote-repo> $_tag"
400     info ""
401 }
402
403 # export to OBS
404 obs_export() {
405     local _patches _dir _specin _specout
406
407     _dir=obs-$VERSION
408     _specin=packaging.in/$PKG.spec.in
409     _specout=$_dir/$PKG.spec
410
411     mkdir -p $_dir
412     rm -f $_dir/*.spec $_dir/*.tar.gz $_dir/*.patches
413
414     if [ -n "$BASELINE" ]; then
415         _base=$BASELINE
416         _patches="`generate_patches $_base $RELEASE $_dir`"
417     else
418         _base=$RELEASE
419         _patches=""
420     fi
421
422     generate_specfile $_specin $_specout $VERSION $_patches
423     generate_tarball $PKG $VERSION $_base $_dir
424 }
425
426
427 #########################
428 # main script
429
430 if [ ! -d .git ]; then
431     error "Please always run ${0##*/} from the top directory."
432     exit 1
433 else
434     TOPDIR=$(basename $(pwd))
435 fi
436
437 parse_configuration $*
438
439 [ -z "$PKG" ]     && PKG=$(basename `pwd`)
440 [ -z "$RELEASE" ] && RELEASE=HEAD
441 [ -z "$VERSION" ] && VERSION=$(default_version)
442 [ -z "$TARGET" ]  && TARGET="tizen"
443 [ -z "$AUTHOR" ]  && AUTHOR="`git config user.name` <`git config \
444                                   user.email`>"
445
446
447 kind=0
448 [ -n "$OBS" ] && kind=$(($kind + 1))
449 [ -n "$GBS" ] && kind=$(($kind + 1))
450
451 if [ "$kind" -gt 1 ]; then
452     error "Multiple release types specified (--obs, --gbs)."
453     exit 1
454 else
455     if [ "$kind" = "0" ]; then
456         GBS=2.0alpha
457     fi
458 fi
459
460 echo "Release configuration for package $PKG:"
461 echo "    releasing:  $RELEASE"
462 echo "    as version: $VERSION"
463 echo "      baseline: ${BASELINE:--}"
464
465 # enable recording and excuting undo actions
466 enable_auto_undo
467
468 if [ -n "$OBS" ]; then
469     obs_export
470 else
471     gbs_prepare
472 fi