1#!/bin/sh
2#
3# Before a release:
4# * Update configure.ac and possibly ChangeLog and
5#   src/sox.h (SOX_LIB_VERSION_CODE) to match release #. If this is a
6#   release candidate, add "rcN" to end of version in configure.ac.
7# * Update date strings and possibly copyright years in man pages.
8# * Tag files to release using following form: git tag sox-14.4.0rc1
9#
10# Automatable release steps.   Most are optional but default to enabled.
11#
12# 1. Verify master git repo matches local git repo.
13# 2. Build source packages.
14# 3. Build Windows packages.
15# 4. Generate announce email from NEWS file.
16# 5. Build HTML and PDF documentation and upload to web site.
17# 6. Create new release directory and upload packages to directory.
18#
19# After a release:
20# * Make sure local tags get pushed remotely: git push --tags
21# * Need to update sourceforge for recommended package to give to each
22#   OS.
23# * send announcement email using Mutt or similar (mutt -H sox-RELEASE.email).
24# * Update front page of web site to point to latest files and give
25#   latest news.
26# * Modify configure.ac, increment version # and put "git" at end of #.
27#
28
29usage()
30{
31    cat <<HELP
32Usage: `basename $0` [options] <tag_previous> <tag_current>
33
34<tag_previous> can be special value "initial" when ran for first
35time.
36
37Options:
38  --force       force overwritting an existing release
39  --help        this help message
40  --ignore-local-changes        don't abort on uncommitted local changes
41  --no-build	Skip building executable packages
42  --no-release	Skip releasing files.
43  --no-short-log Put NEWS content into email instead of autogenerate.
44  --remote      git remote where the change should be pushed (default "origin")
45  --user <name> username on $hostname
46HELP
47}
48
49build_files=yes
50update_web=yes
51release_files=yes
52ignore_changes=no
53short_log=yes
54user=$USER
55remote=origin
56module="sox"
57webpath="sourceforge.net/projects/sox/files"
58rcpath=""
59email_list="sox-users@lists.sourceforge.net,sox-devel@lists.sourceforge.net"
60hostname="shell.sourceforge.net"
61release_path="/home/frs/project/sox"
62release_force="no"
63web_path="/home/project-web/sox/htdocs"
64
65
66while [ $# != 0 ]; do
67    case "$1" in
68    --force)
69        release_force="yes"
70        shift
71        ;;
72    --help)
73        usage
74        exit 0
75        ;;
76    --ignore-local-changes)
77        ignore_changes=yes
78        shift
79        ;;
80    --no-build)
81	build_files=no
82	shift
83	;;
84    --no-release)
85	release_files=no
86	shift
87	;;
88    --no-short-log)
89	short_log=no
90	shift
91	;;
92    --remote)
93        shift
94        remote=$1
95        shift
96        ;;
97    --user)
98	shift
99	user=$1
100	shift
101	;;
102    --*)
103        echo "error: unknown option"
104        usage
105        exit 1
106        ;;
107    *)
108        tag_previous="$1"
109        tag_current="$2"
110        shift 2
111        if [ $# != 0 ]; then
112            echo "error: unknown parameter"
113            usage
114            exit 1
115        fi
116        ;;
117    esac
118done
119
120# configure must have been ran to get release #.
121[ ! -x configure ] && autoreconf -i
122[ ! -f Makefile ] && ./configure
123
124# Check if the object has been pushed. Do do so
125# 1. Check if the current branch has the object. If not, abort.
126# 2. Check if the object is on $remote/branchname. If not, abort.
127local_sha=`git rev-list -1 $tag_current`
128current_branch=`git branch | grep "\*" | sed -e "s/\* //"`
129set +e
130git rev-list $current_branch | grep $local_sha > /dev/null
131if [ $? -eq 1 ]; then
132    echo "Cannot find tag '$tag_current' on current branch. Aborting."
133    echo "Switch to the correct branch and re-run the script."
134    exit 1
135fi
136
137revs=`git rev-list $remote/$current_branch..$current_branch | wc -l`
138if [ $revs -ne 0 ]; then
139    git rev-list $remote/$current_branch..$current_branch | grep $local_sha > /dev/null
140
141    if [ $? -ne 1 ]; then
142        echo "$remote/$current_branch doesn't have object $local_sha"
143        echo "for tag '$tag_current'. Did you push branch first? Aborting."
144        exit 1
145    fi
146fi
147set -e
148
149module="${tag_current%-*}"
150if [ "x$module" = "x$tag_current" ]; then
151    # release-number-only tag.
152    pwd=`pwd`
153    module=`basename $pwd`
154    release_num="$tag_current"
155else
156    # module-and-release-number style tag
157    release_num="${tag_current##*-}"
158fi
159
160detected_module=`grep 'PACKAGE = ' Makefile | sed 's|PACKAGE = ||'`
161if [ -f $detected_module-$release_num.tar.bz2 ]; then
162    module=$detected_module
163fi
164
165osx_zip="$module-${release_num}-macosx.zip"
166win_zip="$module-${release_num}-win32.zip"
167win_exe="$module-${release_num}-win32.exe"
168src_gz="$module-${release_num}.tar.gz"
169src_bz2="$module-${release_num}.tar.bz2"
170release_list="$src_gz $src_bz2 $win_exe $win_zip $osx_zip"
171
172email_file="${module}-${release_num}.email"
173
174build()
175{
176    echo "Creating source packages..."
177    ! make -s distcheck && echo "distcheck failed" && exit 1
178    ! make -s dist-bzip2 && echo "dist-bzip2 failed" && exit 1
179
180    if [ $update_web = "yes" ]; then
181	echo "Creating HTML documentation for web site..."
182	! make -s html && echo "html failed" && exit 1
183
184	echo "Creating PDF documentation for web site..."
185	! make -s pdf && echo "pdf failed" && exit 1
186    fi
187
188    echo "Creating Windows packages..."
189    make -s distclean
190    rm -f $win_zip
191    rm -f $win_exe
192    ./mingwbuild
193}
194
195MD5SUM=`which md5sum || which gmd5sum`
196SHA1SUM=`which sha1sum || which gsha1sum`
197
198create_email()
199{
200    cat<<EMAIL_HEADER
201Subject: [ANNOUNCE] SoX ${release_num} Released
202To: ${email_list}
203
204The developers of SoX are happy to announce the release of SoX ${release_num}.
205Thanks to all who contributed to this release.
206
207EMAIL_HEADER
208
209    if [ $short_log = "yes" ]; then
210	case "$tag_previous" in
211	    initial)
212		range="$tag_current"
213		;;
214	    *)
215		range="$tag_previous".."$tag_current"
216		;;
217	esac
218	echo "git tag: $tag_current"
219	echo
220	git log --no-merges "$range" | git shortlog
221    else
222	cat NEWS
223    fi
224
225    cat<<EMAIL_FOOTER
226
227http://$webpath/${rcpath}${module}/$release_num/$osx_zip/download
228
229MD5:  `$MD5SUM $osx_zip`
230SHA1: `$SHA1SUM $osx_zip`
231
232http://$webpath/${rcpath}${module}/$release_num/$win_exe/download
233
234MD5:  `$MD5SUM $win_exe`
235SHA1: `$SHA1SUM $win_exe`
236
237http://$webpath/${rcpath}${module}/$release_num/$win_zip/download
238
239MD5:  `$MD5SUM $win_zip`
240SHA1: `$SHA1SUM $win_zip`
241
242http://$webpath/${rcpath}${module}/$release_num/$src_bz2/download
243
244MD5:  `$MD5SUM $src_bz2`
245SHA1: `$SHA1SUM $src_bz2`
246
247http://$webpath/${rcpath}${module}/$release_num/$src_gz/download
248
249MD5:  `$MD5SUM $src_gz`
250SHA1: `$SHA1SUM $src_gz`
251
252EMAIL_FOOTER
253}
254
255case $release_num in
256    *git)
257	echo "Aborting.  Should not release untracked version number."
258	exit 1
259	;;
260    *rc?|*rc??)
261	echo "Release candidate detected. Disabling web update."
262	update_web=no
263	rcpath="release_candidates/"
264	;;
265esac
266
267if [ ! -f $osx_zip ]; then
268    echo "$osx_zip files not found.  Place those in base directory and try again."
269    exit 1
270fi
271
272if [ $build_files = "yes" ]; then
273    build
274    echo
275fi
276
277if [ ! -f $src_gz -o ! -f $src_bz2 ]; then
278    echo "$src_gz or $src_bz2 not found.  Rebuild and try again"
279    exit 1
280fi
281
282if [ ! -f $win_zip -o ! -f $win_exe ]; then
283    echo "$win_zip or $win_exe not found.  Rebuild and try again"
284    exit 1
285fi
286
287# Check for uncommitted/queued changes.
288if [ "$ignore_changes" != "yes" ]; then
289    set +e
290    git diff --exit-code > /dev/null 2>&1
291    if [ $? -ne 0 ]; then
292	echo "Uncommitted changes found. Did you forget to commit? Aborting."
293	echo "Use --ignore-local-changes to skip this check."
294	exit 1
295    fi
296    set -e
297fi
298
299create_email > $email_file
300
301username="${user},sox"
302
303if [ $update_web = "yes" -o $release_files = "yes" ]; then
304    echo "Creating shell on sourceforge for $username"
305    ssh ${username}@${hostname} create
306fi
307
308if [ $update_web = "yes" ]; then
309    echo "Updating web pages..."
310    # Delete only PNG filenames which have random PID #'s in them.
311    ssh ${username}@${hostname} rm -rf ${web_path}/soxpng
312    scp -pr *.pdf *.html soxpng ${username}@${hostname}:${web_path}
313    scp -p Docs.Features ${username}@${hostname}:${web_path/wiki.d}
314fi
315
316if [ $release_files = "yes" ]; then
317    ssh ${username}@${hostname} mkdir -p ${release_path}/${rcpath}${module}/${release_num}
318    rsync -avz --delete --progress $release_list ${username}@${hostname}:${release_path}/${rcpath}${module}/${release_num}
319    # FIXME: Stop pushing this and need to find a solution to help push it later.
320    #scp -p NEWS ${username}@${hostname}:${release_path}/${rcpath}${module}/${release_num}/README
321fi
322