2 # release.sh: openocd release process automation
3 # Copyright (C) 2009 by Zachary T Welch <zw@superlucidity.net>
4 # Release under the GNU GPL v2 (or later versions).
6 ## set these to control the build process
10 ## DO NOT PERFORM LIVE RELEASES UNLESS YOU ARE THE RELEASE MANAGER!!!
12 ## set this to perform individual steps on past releases
21 svn info | grep "$1" | cut -d':' -f2- | cut -c2-
25 SVN_ROOT="$(svn_info_get 'Repository Root')"
26 SVN_URL="$(svn_info_get 'URL')"
28 SVN_TRUNK="${SVN_ROOT}/trunk"
30 SVN_BRANCHES="${SVN_ROOT}/branches"
31 PACKAGE_BRANCH="${SVN_BRANCHES}/${PACKAGE_RELEASE}"
33 SVN_TAGS="${SVN_ROOT}/tags"
34 PACKAGE_TAG="${SVN_TAGS}/${PACKAGE_RELEASE}"
36 if [ "${SVN_URL}" = "${SVN_TRUNK}" ]; then
38 elif [ "${SVN_URL/${SVN_BRANCHES}/}" != "${SVN_URL}" ]; then
41 echo "error: bad URL: ${SVN_URL}" >&2
42 die "unable to branch from the current location"
47 Release Type: ${RELEASE_TYPE}
48 Branch URL: ${PACKAGE_BRANCH}
49 Tag URL: ${PACKAGE_TAG}
53 do_svn_echo_msg() { echo "svn: $1: $3"; }
59 [ "$*" ] && echo "Files: $@"
69 echo "svn: ${ACTION}: $@"
75 [ "${RELEASE_DRY_RUN}" ] || svn "$@"
83 package_info_load_name() {
84 grep AC_INIT configure.in | perl -ne 's/^.+\(\[([-\w]*)\],.+$/$1/ and print'
86 package_info_load_version() {
87 grep AC_INIT configure.in | perl -ne 's/^.+\[([-\w\.]*)\],$/$1/ and print'
91 [ -f "configure.in" ] || \
92 die "package_info_load: configure.in is missing"
94 PACKAGE_NAME="$(package_info_load_name)"
96 PACKAGE_TARNAME="${PACKAGE_NAME}"
98 PACKAGE_VERSION="$(package_info_load_version)"
99 [ "${RELEASE_VERSION}" ] || \
100 RELEASE_VERSION=${PACKAGE_VERSION/-in-development/}
102 [ "${PACKAGE_NAME}" -a "${PACKAGE_VERSION}" ] || \
103 die "package information is missing from configure script"
105 PACKAGE_VERSION_TAGS=
106 [ "${PACKAGE_VERSION/-/}" = "${PACKAGE_VERSION}" ] || \
107 PACKAGE_VERSION_TAGS="-${PACKAGE_VERSION#*-}"
108 PACKAGE_VERSION_BASE="${PACKAGE_VERSION%%-*}"
109 PACKAGE_MICRO="${PACKAGE_VERSION_BASE##*.}"
110 PACKAGE_MAJOR_AND_MINOR="${PACKAGE_VERSION_BASE%.*}"
111 PACKAGE_MAJOR="${PACKAGE_MAJOR_AND_MINOR%.*}"
112 PACKAGE_MINOR="${PACKAGE_MAJOR_AND_MINOR#*.}"
114 PACKAGE_STRING="${PACKAGE_NAME} ${PACKAGE_VERSION}"
115 if [ "${RELEASE_DRY_RUN}" ]; then
116 PACKAGE_RELEASE="${PACKAGE_TARNAME}-${PACKAGE_VERSION}"
118 PACKAGE_RELEASE="${PACKAGE_TARNAME}-${RELEASE_VERSION}"
122 package_info_show() {
124 Name: ${PACKAGE_TARNAME}
125 Release: ${RELEASE_VERSION}
126 Version: ${PACKAGE_VERSION}
127 Number: ${PACKAGE_VERSION_BASE}
128 Series: ${PACKAGE_MAJOR_AND_MINOR}
129 Major: ${PACKAGE_MAJOR}
130 Minor: ${PACKAGE_MINOR}
131 Micro: ${PACKAGE_MICRO}
132 Tags: ${PACKAGE_VERSION_TAGS}
133 Branch: ${PACKAGE_RELEASE}
134 Release: ${PACKAGE_TARNAME}-${PACKAGE_VERSION_BASE}${PACKAGE_VERSION_TAGS}
143 info Show a summary of the next pending release.
144 release Release the current tree as an archive.
145 upload Upload archives to berliOS project site
148 bootstrap Prepare the working copy for configuration and building.
149 configure Configures the package; runs bootstrap, if needed.
150 build Compiles the project; runs configure, if needed.
153 changelog Generate a new ChangeLog using svn2cl.
154 package Produce new distributable source archives.
155 stage Move archives to staging area for upload.
158 commit Perform branch and tag, as appropriate for the version.
159 branch Create a release branch from the project trunk.
160 tag Create a tag for the current release branch.
163 version ... Perform version number and tag manipulations.
164 maryslamb Mary had a little lamb, but no one noticed.
165 clean Forces regeneration of results.
166 clean_all Removes all traces of the release process.
167 help Provides this list of commands.
169 For more information about this script, see the Release Processes page
170 in the OpenOCD Developer's Manual (doc/manual/release.txt).
172 WARNING: This script should be used by the Release Manager ONLY.
176 do_usage() { usage; }
180 echo "Current Release Analysis:"
192 echo -n "Bootstrapping..."
193 ./bootstrap 2>&1 | perl tools/logger.pl > "release-bootstrap.log"
195 maybe_bootstrap() { [ -f "configure" ] || do_bootstrap; }
199 echo -n "Configuring..."
200 ./configure ${CONFIG_OPTS} 2>&1 | perl tools/logger.pl > "release-config.log"
202 maybe_configure() { [ -f "Makefile" ] || do_configure; }
206 echo -n "Compiling OpenOCD ${PACKAGE_VERSION}"
207 make ${MAKE_OPTS} -C doc stamp-vti 2>&1 \
208 | perl tools/logger.pl > "release-version.log"
209 make ${MAKE_OPTS} 2>&1 \
210 | perl tools/logger.pl > "release-make.log"
212 maybe_build() { [ -f "src/openocd" ] || do_build; }
213 do_build_clean() { [ -f Makefile ] && make maintainer-clean >/dev/null; }
216 echo "Updating working copy to HEAD..."
218 echo "Creating ChangeLog..."
219 svn2cl -i --authors AUTHORS.ChangeLog
222 if [ -z "${RELEASE_DRY_RUN}" ] \
223 || [ ! -f ChangeLog ] \
224 || [ "$(cat ChangeLog | wc -l)" -lt 2 ]
229 do_changelog_clean() {
230 do_svn revert ChangeLog
237 echo "Building distribution packages..."
238 make ${MAKE_OPTS} distcheck 2>&1 | perl tools/logger.pl > "release-pkg.log"
240 maybe_package() { [ -f "${PACKAGE_RELEASE}.zip" ] || do_package; }
242 for EXT in tar.gz tar.bz2 zip; do
249 echo "Staging package archives:"
251 for EXT in tar.gz tar.bz2 zip; do
252 local FILE="${PACKAGE_RELEASE}.${EXT}"
253 # create archive signatures
254 for HASH in md5 sha1; do
255 echo "sign: ${FILE}.${HASH}"
256 ${HASH}sum "${FILE}" > "archives/${FILE}.${HASH}"
259 mv -v "${FILE}" archives/
262 cp -a ChangeLog archives/
264 do_stage_clean() { rm -v -f -r archives; }
271 svn revert configure.in
272 rm -v -f release-*.log
282 usage: $0 version <command>
284 tag {add|remove} <label> Add or remove the specified tag.
285 bump {major|minor|micro|rc} Bump the specified version number;
286 resets less-significant numbers to zero.
287 All but 'rc' releases drop that tag.
292 local OLD_VERSION="${PACKAGE_VERSION}"
293 local NEW_VERSION="$1"
296 sed -i -e "/AC_INIT/ s|${OLD_VERSION}|${NEW_VERSION}|" configure.in
298 echo "${MSG}: ${OLD_VERSION} -> ${NEW_VERSION}"
300 do_version_bump_sed() {
301 local NEW_VERSION="$1"
302 [ -z "${PACKAGE_VERSION_TAGS}" ] || \
303 NEW_VERSION="${NEW_VERSION}${PACKAGE_VERSION_TAGS}"
305 do_version_sed "${NEW_VERSION}" \
306 "Bump ${CMD} package version number"
308 do_version_bump_major() {
309 do_version_bump_sed "$((PACKAGE_MAJOR + 1)).0.0"
311 do_version_bump_minor() {
312 do_version_bump_sed "${PACKAGE_MAJOR}.$((PACKAGE_MINOR + 1)).0"
314 do_version_bump_micro() {
315 do_version_bump_sed "${PACKAGE_MAJOR_AND_MINOR}.$((PACKAGE_MICRO + 1))"
317 do_version_bump_rc() {
318 die "patch missing: -rc support is not implemented"
324 major|minor|micro|rc)
325 eval "do_version_bump_${CMD}"
334 test "${PACKAGE_VERSION/-${1}/}" != "${PACKAGE_VERSION}"
337 do_version_tag_add() {
339 has_version_tag "${TAG}" && \
340 die "error: tag '-${TAG}' exists in '${PACKAGE_VERSION}'"
341 do_version_sed "${PACKAGE_VERSION}-${TAG}" \
342 "Add '-${TAG}' version tag"
344 do_version_tag_remove() {
346 has_version_tag "${TAG}" || \
347 die "error: tag '-${TAG}' missing from '${PACKAGE_VERSION}'"
348 do_version_sed "${PACKAGE_VERSION/-${TAG}/}" \
349 "Remove '-${TAG}' version tag"
358 eval "do_version_tag_${CMD}" "${i}"
367 do_version_commit() {
368 [ "$(svn diff configure.in | wc -l)" -gt 0 ] || \
369 die "error: no version changes to commit"
370 do_svn commit -m "$1" configure.in
379 do_version_commit "$(eval "do_version_${CMD}" "$@")"
383 [ "${MSG}" ] || die "usage: $0 version commit <message>"
384 do_version_commit "${MSG}"
396 do_svn copy -m "Branching version ${PACKAGE_VERSION}" \
397 "${SVN_TRUNK}" "${PACKAGE_BRANCH}"
402 do_svn copy -m "Tagging version ${PACKAGE_VERSION}" \
403 "${PACKAGE_BRANCH}" "${PACKAGE_TAG}"
409 [ "${PACKAGE_VERSION/in-development/}" = "${PACKAGE_VERSION}" ] || \
410 die "'${PACKAGE_NAME}-${PACKAGE_VERSION}' cannot be released"
412 [ "${PACKAGE_VERSION%.0}" = "${PACKAGE_VERSION}" ] || \
418 do_release_step_prep() {
419 do_version tag remove in-development
420 # reset RELEASE_VERSION now to allow release version to be detected
421 export RELEASE_VERSION=
423 do_release_step_commit() { do_commit; }
425 do_release_step_branch_bump() {
427 echo "Bump ${TYPE} version and add tag:"
428 do_version_bump ${TYPE}
429 do_version_tag_add in-development
431 do_release_step_branch() {
432 do_svn_switch "${PACKAGE_BRANCH}"
433 do_version_commit "$(do_release_step_branch_bump micro)"
434 do_svn_switch "${SVN_URL}"
436 do_release_step_news_msg() {
438 Archive released NEWS file: NEWS -> NEWS-${RELEASE_VERSION}
439 Create new NEWS file from relesse script template.
442 do_release_step_news() {
443 # archive NEWS and create new one from template
444 do_svn move "NEWS" "NEWS-${RELEASE_VERSION}"
446 [ "${RELEASE_DRY_RUN}" ] || cat >NEWS <<NEWS
447 This file should include items worth mentioning in the
448 OpenOCD ${PACKAGE_RELEASE} source archive release.
450 The following areas of OpenOCD functionality changed in this release:
455 Board, Target, and Interface Configuration Scripts:
459 For more details about what has changed since the last release,
460 see the ChangeLog associated with this source archive. For older NEWS,
461 see the NEWS files associated with each release (i.e. NEWS-<version>).
463 For more information about contributing test reports, bug fixes, or new
464 features and device support, please read the new Developer Manual (or
465 the BUGS and PATCHES files in the source archive).
469 local MSG="$(do_release_step_news_msg)"
470 do_svn commit -m "${MSG}" NEWS NEWS-${RELEASE_VERSION}
472 do_release_step_bump() {
473 # major and minor releases require branch version update too
474 [ "${RELEASE_TYPE}" = "micro" ] || do_release_step_branch
475 # bump the current tree version as required.
476 do_version_commit "$(do_release_step_branch_bump "${RELEASE_TYPE}")"
478 [ "${RELEASE_TYPE}" = "micro" ] || do_release_step_news
480 do_release_step_package() {
481 local A=${PACKAGE_TAG}
482 local B=${A/https/http}
483 local PACKAGE_BUILD=${B/${USER}@/}
485 do_svn_switch "${PACKAGE_TAG}"
486 do_svn_switch --relocate "${PACKAGE_TAG}" "${PACKAGE_BUILD}"
488 # required to force SVN to update the in-source URL keyword
489 [ "${RELEASE_DRY_RUN}" ] || rm -v -f src/openocd.c
490 do_svn revert src/openocd.c
495 do_svn_switch --relocate "${PACKAGE_BUILD}" "${PACKAGE_TAG}"
496 do_svn_switch "${SVN_URL}"
499 do_release_step_1() { do_release_step_prep; }
500 do_release_step_2() { do_release_step_commit; }
501 do_release_step_3() { do_release_step_bump; }
502 do_release_step_4() { do_release_step_package; }
505 echo -n "Are you sure you want to release '${PACKAGE_RELEASE}'?"
507 if [ "${ANSWER}" != 'y' ]; then
508 echo "Live release aborted!"
514 for i in $(seq 5 -1 1); do
524 if [ -z "${RELEASE_DRY_RUN}" ]; then
526 do_countdown "Starting live release"
530 for i in $(seq 1 4); do
531 eval "do_release_step_${i}"
534 do_all() { do_release "$@"; }
540 svn revert configure.in
543 OPTIONS=$(getopt -o V --long live -n $0 -- "$@")
544 if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi
545 eval set -- "${OPTIONS}"
549 export RELEASE_DRY_RUN=
560 echo "Internal error"
567 [ "${CMD}" ] || usage
570 ACTION_CMDS="bootstrap|configure|build|changelog|package|stage|clean"
571 MISC_CMDS="all|info|version|tag|branch|commit|release|reset|help|usage"
572 CLEAN_CMDS="build_clean|changelog_clean|package_clean|stage_clean|clean_all"
573 CMDS="|${ACTION_CMDS}|${CLEAN_CMDS}|${MISC_CMDS}|"
574 is_command() { echo "${CMDS}" | grep "|$1|" >/dev/null; }
576 if is_command "${CMD}"; then
577 eval "do_${CMD}" "$@"
579 echo "error: unknown command: '${CMD}'"