1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
|
#!/bin/bash
# Author: Lea Wiemann
# Contact: grubert@users.sourceforge.net
# Revision: $Revision$
# Date: $Date$
# Copyright: This script has been placed in the public domain.
# USAGE see: docutils/docs/dev/release.txt
# must be run from docutils trunk/docutils,
# because HISTORY and RELEASE_NOTES.txt are modified.
set -e
function print_command()
{
# Print "$@", quoting parameters containing spaces.
echo -n $
for param in "$@"; do
echo "$param" | grep -Fq ' ' && echo -n " '$param'" || echo -n " $param"
done
}
function run()
{
# Print and run "$@".
print_command "$@"
echo
"$@"
}
function confirm()
{
# Print, let the user confirm and run "$@".
echo 'Press enter to run (or enter anything to skip):'
print_command "$@"
read
test "$REPLY" && echo Skipped. || "$@"
}
function svn_up()
{
if test $svn == svk; then
confirm svk sync "$depot"
fi
confirm $svn up
}
function checkin()
{
# Parameters: log_message, file, file, file ...
log_message="$1"
shift
confirm $svn diff "$@"
confirm $svn ci -m "$log_prefix $log_message" "$@"
}
function set_ver()
{
# Parameters: old_version new_version
shopt -s extglob
echo Determining list of files to be changed...
# BUG ls lists directories but does not descend
files="docutils/__init__.py setup.py `$svn ls test/functional/expected/ | sed 's|^|test/functional/expected/|'`"
echo "Now I'll change the version number to $2 in the following files:"
echo $files
echo
echo 'Press enter to proceed (or enter anything to skip)...'
read
if [ ! "$REPLY" ]; then
echo 'Modifying files with ed...'
old_ver_regex="`echo "$1" | sed 's/\./\\\\./g'`"
# "ed" returns an error code if there has been no substitution, so
# we temporarily deactivate exit-on-error.
set +e
for F in $files; do
(echo ",s/$old_ver_regex/$2/g"; echo 'wq') | ed "$F"
done
set -e
fi
echo
echo 'CAUTION: please look at the diffs carefully, for wrongly'
echo ' replaced embedded numbers.'
checkin "set version number to $2" $files
}
function usage()
{
echo 'Usage:'
echo
echo ' release.sh new_version svn_version[:branch_version] [stage]'
echo
echo 'The following things will be done:'
echo
echo '* Change version number to new_version. (stage 1)'
echo '* SVN-export, test, and release Docutils version new_version. (stage 2)'
echo '* Change version number to svn_version. (stage 3)'
echo
echo 'If stage is supplied (1, 2 or 3), only the specified stage will'
echo 'be executed. Otherwise, it defaults to executing all stages.'
echo
echo 'Before doing dangerous things, you will be asked to press enter.'
echo
echo 'A maintenance branch called docutils-new_version will be created'
echo 'if branch_version is given. The version number inside the'
echo 'maintenance branch will be set to branch_version.'
echo
echo 'Access ssh,scp and sftp access to shell/frs.sourceforge.net'
echo 'must be configured.'
exit 1
}
function initialize()
{
if [ "$#" -lt 2 ]; then
usage
fi
echo 'Initializing...'
python_versions='2.6 2.7'
for py_ver in $python_versions; do
echo -n "Checking for Python $py_ver (python$py_ver)... "
if ! echo 'print "OK"' | python$py_ver; then
echo "WARN: Python $py_ver (python$py_ver) not found."
fi
done
echo -n 'Clearing $PYTHONPATH... '
export PYTHONPATH=
echo 'done'
echo -n 'Checking whether we are in a working copy... '
if [ -f HISTORY.txt ]; then
echo yes
else
echo "no (HISTORY.txt doesn't exist)"
echo 'Aborting.'
echo 'Please cd to a working copy before running this script.'
exit 1
fi
echo -n 'Subversion binary to use: '
# TODO breaks for newer svn, .svn is in upper. is this for svk
svn=svn
echo $svn
working_copy="`pwd -P`"
echo "Working copy: $working_copy"
svnurl="`$svn info . | grep ^URL: | sed 's/URL: //'`"
if test -z "$svnurl"; then
echo 'Unable to detect Subversion URL. Aborting.'
exit 1
fi
echo "Subversion URL: $svnurl"
if ! echo "$svnurl" | grep -q 'branches\|trunk'; then
echo 'Subversion URL contains neither "branches" nor "trunk".'
echo 'Aborting.'
exit 1
fi
if test `uname` = "Darwin" ; then
svnroot="`echo "$svnurl" | sed -E 's/\/(branches|trunk).*//'`"
else
svnroot="`echo "$svnurl" | sed 's/\/\(branches\|trunk\).*//'`"
fi
echo "Subversion root URL: $svnroot"
if test "$svnurl" = "$svnroot"; then
echo 'Error: Subversion URL and Subversion root URL are the same.'
echo ' probably a MacOSX sed problem.'
exit 1
fi
echo -n 'Detecting current Docutils version... '
old_ver="`python -c 'import docutils; print docutils.__version__'`"
echo "$old_ver"
new_ver="$1"
# log_prefix is for SVN logs.
log_prefix="Release $new_ver:"
echo "New version number (for releasing): $new_ver"
svn_ver="$2"
if echo "$svn_ver" | grep -q :; then
# Split at colon: svn_ver:branch_ver
branch_ver="${svn_ver#*:}"
svn_ver="${svn_ver%:*}"
else
branch_ver=
fi
echo "New Subversion version number (after releasing): $svn_ver"
echo -n 'Create maintenance branch: '
if test "$branch_ver"; then
echo yes
echo "New version number on maintenance branch: $branch_ver"
else
echo no
fi
if test "$branch_ver"; then
echo -n 'Checking that we have a full checkout... '
if echo "$working_copy" | grep -q 'branches\|trunk'; then
echo OK
else
echo 'no'
echo 'Working copy path contains neither "branches" nor "trunk".'
echo 'You need a full checkout in order to branch.'
echo 'Aborting.'
exit 1
fi
wcroot="`echo "$working_copy" | sed 's/\/\(branches\|trunk\).*//'`"
echo "Working copy root: $wcroot"
fi
tarball=docutils-"$new_ver".tar.gz
echo "Tarball name: $tarball"
echo 'Initialization completed.'
echo
}
function test_tarball()
{
# Assume we have the tarball in the current directory.
# Pass test number as first parameter.
echo 'Testing the release tarball.'
run mkdir tarball_test/
run cd tarball_test/
confirm tar xzvf "../$tarball"
echo
run cd docutils-"$new_ver"
echo 'Deleteing old installations. Installing the distribution.'
echo "WARN: might not find installation."
for py_ver in '"$python_versions"'; do
echo "python$py_ver install/update and test."
bash release-test.sh
echo "Enter to test next."
read
done
}
function upload_tarball()
{
# Assume we have the tarball in the working area.
run cd "$working_area"
mkdir $new_ver
cp docutils-$new_ver.tar.gz $new_ver
cp docutils/RELEASE-NOTES.txt $new_ver
# README.txt would be displayed automatically on sf.
# BUG user grubert hardcoded
# short path "/home/frs/project/docutils/docutils/" also exists
scp -r $new_ver grubert,docutils@frs.sourceforge.net:/home/frs/project/d/do/docutils/docutils/
echo 'Upload completed.'
}
function upload_htdocs()
{
# Assume we have the tarball in the working area.
run cd "$working_area"
echo "Upload htdocs for $new_ver"
run mkdir htdocs
run cd htdocs
confirm tar xzvf "../$tarball"
run cd docutils-"$new_ver"/tools/
echo "BUG no docutils installation left."
echo "DO NOT call manually in $(pwd)"
confirm ./buildhtml.py --local ..
confirm ./buildhtml.py ../docs
run cd ..
echo '$ find . -name test -type d -prune -o -name \*.css -print0 \
-o -name \*.html -print0 -o -name \*.txt -print0 \
| tar -cjvf docutils-docs.tar.bz2 -T - --null'
find . -name test -type d -prune -o -name \*.css -print0 \
-o -name \*.html -print0 -o -name \*.txt -print0 \
| tar -cjvf docutils-docs.tar.bz2 -T - --null
echo 'Upload docs to SF.net...'
echo 'Press enter (or enter anything to skip).'
read
if [ ! "$REPLY" ]; then
mkdir $new_ver
cd $new_ver
tar xjvf ../docutils-docs.tar.bz2
cd ..
chmod -R g+rw $new_ver
scp -r -p -C $new_ver web.sourceforge.net:/home/groups/d/do/docutils/htdocs
fi
}
function create_maintenance_branch()
{
echo 'Creating maintenance branch.'
branch_name="docutils-$new_ver"
echo "Branch name: $branch_name"
branch_url="$svnroot/branches/$branch_name"
echo "Branch URL: $branch_url"
confirm svn cp "$svnurl" "$branch_url" -m \
"$log_prefix created maintenance branch for version $new_ver"
cd "$wcroot"
svn_up
cd branches/"$branch_name"
set_ver "$new_ver" "$branch_ver"
}
function run_stage()
{
if [ ! "$1" ]; then
run_stage 1
echo
run_stage 2
echo
run_stage 3
else
echo "Press enter to run stage $1 (or enter anything to skip this stage)."
read
if [ ! "$REPLY" ]; then
cd "$working_copy"
if [ "$1" == 1 ]; then
stage_1
elif [ "$1" == 2 ]; then
stage_2
elif [ "$1" == 3 ]; then
stage_3
else
echo 'Invalid stage.'
echo
usage
fi
echo
echo "Stage $1 completed."
else
echo "Skipped stage $1."
fi
fi
}
function stage_1()
{
svn_up
echo
# update __version_details__ string
(echo ",s/^__version_details__ = .*\$/__version_details__ = 'release'/";
echo wq) | ed docutils/__init__.py 2> /dev/null
set_ver "$old_ver" "$new_ver"
echo
history_files='HISTORY.txt RELEASE-NOTES.txt'
echo "Now updating the following files: $history_files"
old_string="Changes Since [0-9.]+"
new_string="Release $new_ver (`date --utc --iso-8601`)"
echo 'Press enter to replace "'"$old_string"'" with "'"$new_string"\",
echo 'or enter anything to skip.'
read
test "$REPLY" || python -c "for filename in '$history_files'.split():
import re
h = file(filename).read()
h = re.sub('$old_string\\n=+', '$new_string\\n' + '=' * len('$new_string'), h, count=1)
file(filename, 'w').write(h)"
checkin 'closed "Changes Since ..." section' $history_files
}
function stage_2()
{
echo 'Creating working area...'
working_area="`echo ~/tmp/docutils-release.$$`"
run mkdir -p "$working_area"
echo
echo 'Getting a fresh export.'
echo 'Press enter to proceed (or enter anything to skip)...'
read
if [ ! "$REPLY" ]; then
run cd "$working_area"
confirm svn export "$svnurl"
echo
echo 'Building the release tarball.'
run cd docutils
confirm ./setup.py sdist
run cd ..
echo 'Tarball built.'
run cp docutils/dist/"$tarball" .
echo 'BETTER run release-test.sh manually for each installed python version.'
echo "DO: cd $working_area and call sandbox/infrastructure/release-test.sh py_ver docutils_ver"
confirm test_tarball
echo "Testing documentation and uploading htdocs of version $new_ver..."
confirm upload_htdocs
echo "Tagging current revision..."
confirm svn cp "$svnurl" "$svnroot/tags/docutils-$new_ver/" -m "$log_prefix tagging released revision"
echo "Uploading $tarball to SF.net."
confirm upload_tarball
echo 'Now go to https://sourceforge.net/projects/docutils/files/docutils'
echo 'and follow the instructions at'
echo 'http://docutils.sf.net/docs/dev/release.html#file-release-system'
echo
echo 'Then press enter.'
read
fi
run cd $working_area
echo 'Downloading the tarball to verify its integrity.'
while true; do
# BUG path is wrong. project admin filemanager shows md5sum
confirm wget http://sourceforge.net/projects/docutils/files/"$tarball"
echo 'Was the download successful?'
echo 'If yes, press enter to continue, otherwise enter anything to repeat'
echo '(it is possible that the file will show up in a few minutes).'
read
test "$REPLY" || break
done
confirm test_tarball
echo 'we are registered with PyPI...'
echo 'upload to pypi with twine or set download url for this release'
echo 'Press enter to proceed (or enter anything to skip)...'
read
if [ ! "$REPLY" ]; then
echo "Unpacking tarball..."
ls -l
pwd
run twine upload "$tarball"
echo "verify on PyPI. hide older releases."
echo "TODO TEST build wheels and upload"
run pip wheel docutils
run twine upload docutils-*-py2-none-any.whl
run pip3 wheel docutils
run twine upload wheelhouse/docutils-${new_ver}-py3-none-any.whl
fi
}
function stage_3()
{
svn_up
echo
# update __version_details__ string
(echo ",s/^__version_details__ = .*\$/__version_details__ = 'repository'/";
echo wq) | ed docutils/__init__.py 2> /dev/null
checkin 'set __version_details__ to "repository"'
echo
history_files='HISTORY.txt RELEASE-NOTES.txt'
echo "Now updating the following files: $history_files"
add_string="Changes Since $new_ver"
before="Release "
echo 'Press enter to add "'"$add_string"'" section,'
echo 'or enter anything to skip.'
read
test "$REPLY" || python -c "for filename in '$history_files'.split():
import re
h = file(filename).read()
h = re.sub('\n$before', '\\n$add_string\\n' + '=' * len('$add_string') +
'\\n\\n\\n$before', h, count=1)
file(filename, 'w').write(h)"
checkin "added empty \"Changes Since $new_ver\" section" $history_files
echo
if test "$branch_ver"; then
create_maintenance_branch
cd "$working_copy"
fi
set_ver "$new_ver" "$svn_ver"
echo 'Please change version number in README.txt'
echo
echo 'Please update the web page now (web/index.txt).'
echo 'cd into sandbox/infrastructure'
echo 'and call docutils-update.local (requires linux, macosx cp misses something)'
echo "Press enter when you're done."
read
}
initialize "$@"
run_stage "$3"
echo
echo 'Finished.'
echo 'Run alltests.py on svn version now.'
# Local Variables:
# indent-tabs-mode: nil
# End:
|