Fix: complete path in message
[docutils/kirr.git] / sandbox / infrastructure / release.sh
blob5aff6f7fb3b0e52175ab759264d1c62da9c889ed
1 #!/bin/bash
3 # Author: Lea Wiemann
4 # Contact: LeWiemann@gmail.com
5 # Revision: $Revision$
6 # Date: $Date$
7 # Copyright: This script has been placed in the public domain.
9 # USAGE see: docutils/docs/dev/release.txt
11 set -e
13 function print_command()
15 # Print "$@", quoting parameters containing spaces.
16 echo -n $
17 for param in "$@"; do
18 echo "$param" | grep -Fq ' ' && echo -n " '$param'" || echo -n " $param"
19 done
22 function run()
24 # Print and run "$@".
25 print_command "$@"
26 echo
27 "$@"
30 function confirm()
32 # Print, let the user confirm and run "$@".
33 echo 'Press enter to run (or enter anything to skip):'
34 print_command "$@"
35 read
36 test "$REPLY" && echo Skipped. || "$@"
39 function svn_up()
41 if test $svn == svk; then
42 confirm svk sync "$depot"
44 confirm $svn up
47 function checkin()
49 # Parameters: log_message, file, file, file ...
50 log_message="$1"
51 shift
52 confirm $svn diff "$@"
53 confirm $svn ci -m "$log_prefix $log_message" "$@"
56 function set_ver()
58 # Parameters: old_version new_version
59 shopt -s extglob
60 echo Determining list of files to be changed...
61 # BUG ls lists directories but does not descend
62 files="docutils/__init__.py setup.py `$svn ls test/functional/expected/ | sed 's|^|test/functional/expected/|'`"
63 echo "Now I'll change the version number to $2 in the following files:"
64 echo $files
65 echo
66 echo 'Press enter to proceed (or enter anything to skip)...'
67 read
68 if [ ! "$REPLY" ]; then
69 echo 'Modifying files with ed...'
70 old_ver_regex="`echo "$1" | sed 's/\./\\\\./g'`"
71 # "ed" returns an error code if there has been no substitution, so
72 # we temporarily deactivate exit-on-error.
73 set +e
74 for F in $files; do
75 (echo ",s/$old_ver_regex/$2/g"; echo 'wq') | ed "$F"
76 done
77 set -e
79 echo
80 echo 'CAUTION: please look at the diffs carefully, for wrongly'
81 echo ' replaced embedded numbers.'
82 checkin "set version number to $2" $files
85 function usage()
87 echo 'Usage:'
88 echo
89 echo ' release.sh new_version svn_version[:branch_version] [stage]'
90 echo
91 echo 'The following things will be done:'
92 echo
93 echo '* Change version number to new_version. (stage 1)'
94 echo '* SVN-export, test, and release Docutils version new_version. (stage 2)'
95 echo '* Change version number to svn_version. (stage 3)'
96 echo
97 echo 'If stage is supplied (1, 2 or 3), only the specified stage will'
98 echo 'be executed. Otherwise, it defaults to executing all stages.'
99 echo
100 echo 'Before doing dangerous things, you will be asked to press enter.'
101 echo
102 echo 'A maintenance branch called docutils-new_version will be created'
103 echo 'if branch_version is given. The version number inside the'
104 echo 'maintenance branch will be set to branch_version.'
105 echo
106 echo 'Access ssh,scp and sftp access to shell/frs.sourceforge.net'
107 echo 'must be configured.'
108 exit 1
111 function initialize()
113 if [ "$#" -lt 2 ]; then
114 usage
116 echo 'Initializing...'
117 python_versions='2.3 2.4 2.5 2.6 2.7'
118 for py_ver in $python_versions; do
119 echo -n "Checking for Python $py_ver (python$py_ver)... "
120 if ! echo 'print "OK"' | python$py_ver; then
121 echo "Python $py_ver (python$py_ver) not found."
122 echo Aborting.
123 exit 1
125 done
126 echo -n 'Clearing $PYTHONPATH... '
127 export PYTHONPATH=
128 echo 'done'
129 echo -n 'Checking whether we are in a working copy... '
130 if [ -f HISTORY.txt ]; then
131 echo yes
132 else
133 echo "no (HISTORY.txt doesn't exist)"
134 echo 'Aborting.'
135 echo 'Please cd to a working copy before running this script.'
136 exit 1
138 echo -n 'Subversion binary to use: '
139 if [ -d .svn ]; then
140 svn=svn
141 else
142 svn=svk
144 echo $svn
145 working_copy="`pwd -P`"
146 echo "Working copy: $working_copy"
147 if test $svn = svk; then
148 depot_path="`svk info . | grep ^Depot\ Path: | sed 's/Depot Path: //'`"
149 depot="`echo "$depot_path" | sed 's|\(//[^/]\+/[^/]\+\).*|\1|'`"
150 echo "SVK depot: $depot"
151 mirrored_from="`svk info . | grep ^Mirrored\ From: | sed 's/Mirrored From: //;s/, Rev\. .*//'`"
152 svnurl="$mirrored_from`echo "$depot_path" | sed 's|//[^/]\+/[^/]\+||'`"
153 else
154 svnurl="`$svn info . | grep ^URL: | sed 's/URL: //'`"
156 if test -z "$svnurl"; then
157 echo 'Unable to detect Subversion URL. Aborting.'
158 exit 1
160 echo "Subversion URL: $svnurl"
161 if ! echo "$svnurl" | grep -q 'branches\|trunk'; then
162 echo 'Subversion URL contains neither "branches" nor "trunk".'
163 echo 'Aborting.'
164 exit 1
166 svnroot="`echo "$svnurl" | sed 's/\/\(branches\|trunk\).*//'`"
167 echo "Subversion root URL: $svnroot"
168 if test "$svnurl" = "$svnroot"; then
169 echo 'Error: Subversion URL and Subversion root URL are the same.'
170 exit 1
172 echo -n 'Detecting current Docutils version... '
173 old_ver="`python -c 'import docutils; print docutils.__version__'`"
174 echo "$old_ver"
175 new_ver="$1"
176 # log_prefix is for SVN logs.
177 log_prefix="Release $new_ver:"
178 echo "New version number (for releasing): $new_ver"
179 svn_ver="$2"
180 if echo "$svn_ver" | grep -q :; then
181 # Split at colon: svn_ver:branch_ver
182 branch_ver="${svn_ver#*:}"
183 svn_ver="${svn_ver%:*}"
184 else
185 branch_ver=
187 echo "New Subversion version number (after releasing): $svn_ver"
188 echo -n 'Create maintenance branch: '
189 if test "$branch_ver"; then
190 echo yes
191 echo "New version number on maintenance branch: $branch_ver"
192 else
193 echo no
195 if test "$branch_ver"; then
196 echo -n 'Checking that we have a full checkout... '
197 if echo "$working_copy" | grep -q 'branches\|trunk'; then
198 echo OK
199 else
200 echo 'no'
201 echo 'Working copy path contains neither "branches" nor "trunk".'
202 echo 'You need a full checkout in order to branch.'
203 echo 'Aborting.'
204 exit 1
206 wcroot="`echo "$working_copy" | sed 's/\/\(branches\|trunk\).*//'`"
207 echo "Working copy root: $wcroot"
209 tarball=docutils-"$new_ver".tar.gz
210 echo "Tarball name: $tarball"
211 echo 'Initialization completed.'
212 echo
215 function test_tarball()
217 # Assume we have the tarball in the current directory.
218 # Pass test number as first parameter.
219 echo 'Testing the release tarball.'
220 run mkdir tarball_test/
221 run cd tarball_test/
222 confirm tar xzvf "../$tarball"
223 echo
224 run cd docutils-"$new_ver"
225 echo 'Installing the distribution.'
226 # Extra files, with leading comma.
227 extras="`cd extras; for extrafile in *.py; do echo -n ",$extrafile{,c,o}"; done`"
228 confirm su -c '
229 for py_ver in '"$python_versions"'; do
230 echo "Deleting and installing Docutils on Python $py_ver."
231 echo "Press enter."
232 read
233 site_packages="/usr/local/lib/python$py_ver/site-packages"
234 echo "BUG prefers /usr/local too /usr"
235 if test ! -d "$site_packages"; then
236 site_packages="/usr/lib/python$py_ver/site-packages"
238 if test ! -d "$site_packages"; then
239 echo "Error: \"$site_packages\" does not exist."
240 exit 1
242 if test -e "$site_packages/docutils-test"; then
243 echo "Error: \"$site_packages/docutils-test\" exists."
244 echo "removing left over from previous release. Ctrl-C to abort."
245 read
246 rm -rf $site_packages/docutils-test
248 rm -rfv /usr/{local,}lib/python$py_ver/site-packages/{docutils'"$extras"'}
249 echo "TODO for python3 rm local build, but building takes a long time then "
250 python$py_ver setup.py install
251 echo
252 echo "Copying the test suite to the site-packages directory of Python $py_ver."
253 echo "TODO for python3 copy test3"
254 echo "Press enter."
255 read
256 cp -rv test "$site_packages/docutils-test"
257 done'
258 echo
259 echo 'Running the test suite as root with all Python versions.'
260 for py_ver in $python_versions; do
261 site_packages="/usr/local/lib/python$py_ver/site-packages"
262 if test ! -d "$site_packages"; then
263 site_packages="/usr/lib/python$py_ver/site-packages"
265 if test ! -d "$site_packages"; then
266 echo "Error: \"$site_packages\" does not exist."
267 exit 1
269 # BUG
270 echo "WARNING shell script exits if any test fails, maybe run in separate shell."
271 confirm su -c "python$py_ver -u \"$site_packages/docutils-test/alltests.py\""
272 done
273 run cd ../..
274 echo "Cleaning up..."
275 confirm su -c "rm -rf tarball_test"
276 confirm su -c '
277 for py_ver in '"$python_versions"'; do
278 rm -rfv /usr{/local,}/lib/python$py_ver/site-packages/docutils{-test,}
279 done'
280 echo
283 function upload_tarball()
285 # Assume we have the tarball in the working area.
286 run cd "$working_area"
287 mkdir $new_ver
288 cp docutils-$new_ver.tar.gz $new_ver
289 cp docutils/RELEASE-NOTES.txt $new_ver
290 # README.txt would be displayed automatically on sf.
291 # BUG user grubert hardcoded
292 # short path "/home/frs/project/docutils/docutils/" also exists
293 scp -r $new_ver grubert,docutils@frs.sourceforge.net:/home/frs/project/d/do/docutils/docutils/
294 echo 'Upload completed.'
297 function upload_htdocs()
299 # Assume we have the tarball in the working area.
300 run cd "$working_area"
301 echo "Upload htdocs for $new_ver"
302 run mkdir htdocs
303 run cd htdocs
304 confirm tar xzvf "../$tarball"
305 run cd docutils-"$new_ver"/tools/
306 echo "BUG no docutils installation left."
307 echo "DO NOT let call but manually in $(pwd)"
308 confirm ./buildhtml.py --local ..
309 confirm ./buildhtml.py ../docs
310 run cd ..
311 echo '$ find -name test -type d -prune -o -name \*.css -print0 \
312 -o -name \*.html -print0 -o -name \*.txt -print0 \
313 | tar -cjvf docutils-docs.tar.bz2 -T - --null'
314 find -name test -type d -prune -o -name \*.css -print0 \
315 -o -name \*.html -print0 -o -name \*.txt -print0 \
316 | tar -cjvf docutils-docs.tar.bz2 -T - --null
317 echo 'Upload docs to SF.net...'
318 echo 'Press enter (or enter anything to skip).'
319 read
320 if [ ! "$REPLY" ]; then
321 mkdir $new_ver
322 cd $new_ver
323 tar xjvf ../docutils-docs.tar.bz2
324 cd ..
325 chmod -R g+rw $new_ver
326 scp -r -p -C $new_ver web.sourceforge.net:/home/groups/d/do/docutils/htdocs
330 function create_maintenance_branch()
332 echo 'Creating maintenance branch.'
333 branch_name="docutils-$new_ver"
334 echo "Branch name: $branch_name"
335 branch_url="$svnroot/branches/$branch_name"
336 echo "Branch URL: $branch_url"
337 confirm svn cp "$svnurl" "$branch_url" -m \
338 "$log_prefix created maintenance branch for version $new_ver"
339 cd "$wcroot"
340 svn_up
341 cd branches/"$branch_name"
342 set_ver "$new_ver" "$branch_ver"
345 function run_stage()
347 if [ ! "$1" ]; then
348 run_stage 1
349 echo
350 run_stage 2
351 echo
352 run_stage 3
353 else
354 echo "Press enter to run stage $1 (or enter anything to skip this stage)."
355 read
356 if [ ! "$REPLY" ]; then
357 cd "$working_copy"
358 if [ "$1" == 1 ]; then
359 stage_1
360 elif [ "$1" == 2 ]; then
361 stage_2
362 elif [ "$1" == 3 ]; then
363 stage_3
364 else
365 echo 'Invalid stage.'
366 echo
367 usage
369 echo
370 echo "Stage $1 completed."
371 else
372 echo "Skipped stage $1."
377 function stage_1()
379 svn_up
380 echo
381 # update __version_details__ string
382 (echo ",s/^__version_details__ = .*\$/__version_details__ = 'release'/";
383 echo wq) | ed docutils/__init__.py 2> /dev/null
384 set_ver "$old_ver" "$new_ver"
385 echo
386 history_files='HISTORY.txt RELEASE-NOTES.txt'
387 echo "Now updating the following files: $history_files"
388 old_string="Changes Since [0-9.]+"
389 new_string="Release $new_ver (`date --utc --iso-8601`)"
390 echo 'Press enter to replace "'"$old_string"'" with "'"$new_string"\",
391 echo 'or enter anything to skip.'
392 read
393 test "$REPLY" || python -c "for filename in '$history_files'.split():
394 import re
395 h = file(filename).read()
396 h = re.sub('$old_string\\n=+', '$new_string\\n' + '=' * len('$new_string'), h, count=1)
397 file(filename, 'w').write(h)"
398 checkin 'closed "Changes Since ..." section' $history_files
401 function stage_2()
403 echo 'Creating working area...'
404 working_area="`echo ~/tmp/docutils-release.$$`"
405 run mkdir -p "$working_area"
406 echo
407 echo 'Getting a fresh export.'
408 echo 'Press enter to proceed (or enter anything to skip)...'
409 read
410 if [ ! "$REPLY" ]; then
411 run cd "$working_area"
412 confirm svn export "$svnurl"
413 echo
414 echo 'Building the release tarball.'
415 run cd docutils
416 confirm ./setup.py sdist
417 run cd ..
418 echo 'Tarball built.'
419 run cp docutils/dist/"$tarball" .
420 confirm test_tarball
421 echo "Testing documentation and uploading htdocs of version $new_ver..."
422 confirm upload_htdocs
423 echo "Tagging current revision..."
424 confirm svn cp "$svnurl" "$svnroot/tags/docutils-$new_ver/" -m "$log_prefix tagging released revision"
425 echo "Uploading $tarball to SF.net."
426 confirm upload_tarball
427 echo 'Now go to https://sourceforge.net/projects/docutils/files/docutils'
428 echo 'and follow the instructions at'
429 echo 'http://docutils.sf.net/docs/dev/release.html#file-release-system'
430 echo
431 echo 'Then press enter.'
432 read
434 run cd $working_area
435 echo 'Downloading the tarball to verify its integrity.'
436 while true; do
437 # BUG path is wrong. project admin filemanager shows md5sum
438 confirm wget http://sourceforge.net/projects/docutils/files/"$tarball"
439 echo 'Was the download successful?'
440 echo 'If yes, press enter to continue, otherwise enter anything to repeat'
441 echo '(it is possible that the file will show up in a few minutes).'
442 read
443 test "$REPLY" || break
444 done
445 confirm test_tarball
446 echo 'Registering with PyPI...'
447 echo 'Press enter to proceed (or enter anything to skip)...'
448 read
449 if [ ! "$REPLY" ]; then
450 echo "Unpacking tarball..."
451 ls -l
453 run tar xzvf "$tarball"
454 run cd docutils-"$new_ver"
455 confirm ./setup.py register
459 function stage_3()
461 svn_up
462 echo
463 # update __version_details__ string
464 (echo ",s/^__version_details__ = .*\$/__version_details__ = 'repository'/";
465 echo wq) | ed docutils/__init__.py 2> /dev/null
466 checkin 'set __version_details__ to "repository"'
467 echo
468 history_files='HISTORY.txt RELEASE-NOTES.txt'
469 echo "Now updating the following files: $history_files"
470 add_string="Changes Since $new_ver"
471 before="Release "
472 echo 'Press enter to add "'"$add_string"'" section,'
473 echo 'or enter anything to skip.'
474 read
475 test "$REPLY" || python -c "for filename in '$history_files'.split():
476 import re
477 h = file(filename).read()
478 h = re.sub('\n$before', '\\n$add_string\\n' + '=' * len('$add_string') +
479 '\\n\\n\\n$before', h, count=1)
480 file(filename, 'w').write(h)"
481 checkin "added empty \"Changes Since $new_ver\" section" $history_files
482 echo
483 if test "$branch_ver"; then
484 create_maintenance_branch
485 cd "$working_copy"
487 set_ver "$new_ver" "$svn_ver"
488 echo
489 echo 'Please update the web page now (web/index.txt).'
490 echo 'cd into sandbox/infrastructure'
491 echo 'and call docutils-update.local (requires linux, macosx cp misses something)'
492 echo "Press enter when you're done."
493 read
496 initialize "$@"
497 run_stage "$3"
498 echo
499 echo 'Finished.'
500 echo 'Run alltests.py on svn version now.'
502 # Local Variables:
503 # indent-tabs-mode: nil
504 # End: