7 # ##############################################################################
9 # ##############################################################################
11 declare MODE_BRANCH="branch"
12 declare MODE_RELEASE="release"
14 declare MODE_BRANCH_TXT="Branch"
15 declare MODE_BRANCH_TXT_LOWER="branch"
16 declare MODE_RELEASE_TXT="Release"
17 declare MODE_RELEASE_TXT_LOWER="release"
20 declare MODE_TXT_LOWER=""
23 # The digit representation of a basic version can be in the format 0.6.4
24 declare versionRegexDigitsBasic="([[:digit:]]+\.[[:digit:]]+\.[[:digit:]]+)"
26 # The digit representation of a release branch version can be in the format
28 declare versionRegexDigits="${versionRegexDigitsBasic}(\.[[:digit:]]+)?"
30 # The version for source code can be in the format:
31 # - 0.6.4 or 0.6.4.1 or pre-0.6.4 or pre-0.6.4.1
32 declare versionRegexSources="(|pre-)(${versionRegexDigits})"
34 # The version for a release tag is in the format v0.6.4 or v0.6.4.1
35 declare versionRegexReleaseTag="v(${versionRegexDigits})"
37 # A release branch is in the format release-0.6.4 or release-0.6.4.1
38 declare relBranchRegex="release-(${versionRegexDigits})"
43 # ##############################################################################
45 # ##############################################################################
52 echo " $(basename "${script}") ${MODE_BRANCH} 0.6.4"
53 echo " - create the release branch for version 0.6.4"
54 echo " $(basename "${script}") ${MODE_RELEASE}"
55 echo " - release the (checked-out) release branch"
60 # Trim a string: remove spaces from the beginning and end of the string
63 # return=trimmed string
64 function stringTrim() {
65 if [[ -z "${1}" ]]; then
69 # remove leading whitespace characters
70 local var="${1#${1%%[![:space:]]*}}"
72 # remove trailing whitespace characters
73 echo "${var%${var##*[![:space:]]}}"
78 # Get the canonical path of a file or directory
79 # This is the physical path without any links
81 # 1=the file or directory
82 function pathCanonicalPath() {
83 local src="$(stringTrim "${1}")"
85 if [[ -h "${src}" ]] && [[ -d "${src}" ]]; then
86 # src is a link to a directory
88 cd -P "${src}" &> /dev/null
94 # we're not dealing with a directory here
95 while [[ -h "${src}" ]]; do
96 # keep getting the link target while src is a link
97 src="$(ls -la "${src}" | \
98 sed -r 's#^.*?[[:space:]]+->[[:space:]]+(.*)$#\1#')"
100 # src is no longer a link here
103 cd -P "$(dirname "${src}")" &> /dev/null
104 echo "$(pwd -P)/$(basename "${src}")"
110 # Determine whether a given directory is a git repository directory
113 # return=0 not a git dir, 1 a git dir
114 function gitIsGitDirectory() {
115 local place="$(stringTrim "${1}")"
118 if [[ -d "${place}" ]]; then
119 pushd "${place}" &> /dev/null
121 git rev-parse --git-dir &> /dev/null
127 if [[ ${result} -ne 0 ]]; then
136 # Go into the root of the checkout and check some key files
138 function checkIsOlsrdGitCheckout() {
139 if [[ "$(gitIsGitDirectory ".")" == "0" ]] || \
140 [[ ! -r ./Makefile.inc ]] || \
141 [[ ! -r ./files/olsrd.conf.default.full ]]; then
142 echo "* You do not appear to be running the script from an olsrd git checkout"
149 # Check that a signing key is configured
151 function checkGitSigningKeyIsConfigured() {
152 local gpgKeyId="$(git config --get user.signingkey)"
153 if [[ -z "${gpgKeyId}" ]]; then
155 * No signing key is setup for git, please run
156 git config --global user.signingkey <key ID>
158 You can get keys and IDs by running 'gpg --list-keys'
164 # Check that the signing key is present
167 gpg --list-key "${gpgKeyId}" &> /dev/null
168 local -i gpgKeyIdPresentResult=${?}
170 if [[ ${gpgKeyIdPresentResult} -ne 0 ]]; then
172 * Your signing key with ID ${gpgKeyId} is not found, please run
173 git config --global user.signingkey <key ID>
174 to setup a valid key ID.
176 You can get keys and IDs by running 'gpg --list-keys'
184 # Get the version digits from a release tag version
186 # 1=release tag version
187 # return=version digits
188 function getVersionDigitsFromReleaseTag() {
189 echo "$(stringTrim "${1}")" | sed -r "s/${versionRegexReleaseTag}/\1/"
194 # Get the previous release tag and check
196 declare prevRelTagVersion=""
197 function getPrevRelTag() {
199 prevRelTagVersion="$(git describe --abbrev=0 | \
200 grep -E "^${versionRegexReleaseTag}$")"
202 if [[ -z "${prevRelTagVersion}" ]]; then
203 echo "* Could not find the previous release tag"
210 # Get the next version digits by incrementing the micro digit
212 # 1=version in format 0.6.4 or 0.6.4.1
213 # return=incremented version in format 0.6.5
214 function getNextVersionDigitsMicro() {
215 local version="$(stringTrim "${1}")"
216 local -a versionDigits=( ${version//\./ } )
217 local -i versionMicroNext=$(( ${versionDigits[2]} + 1 ))
218 echo "${versionDigits[0]}.${versionDigits[1]}.${versionMicroNext}"
223 # Get the next version digits by incrementing the patchlevel digit
225 # 1=version in format 0.6.4 or 0.6.4.0
226 # return=incremented version in format 0.6.4.1
227 function getNextVersionDigitsPatchLevel() {
228 local version="$(stringTrim "${1}")"
229 local -a versionDigits=( ${version//\./ } )
230 local -i versionPatchLevelNext=1
231 if [[ ${#versionDigits[*]} -ne 3 ]]; then
232 versionPatchLevelNext=$(( ${versionDigits[3]} + 1 ))
234 echo "${versionDigits[0]}.${versionDigits[1]}.${versionDigits[2]}.${versionPatchLevelNext}"
239 # Adjust the branch name so that we can release 0.6.4.x from the
240 # release-0.6.4 branch
242 # prevTagVersionDigits relBranchVersionDigits relBranchVersionDigits (adjusted)
243 # 0.6.4 0.6.4 0.6.4.1
247 # 0.6.4.5 0.6.4 0.6.4.6
251 function adjustBranchName() {
252 local -a prevTagVersionDigitsArray=( ${prevTagVersionDigits//\./ } )
253 local -a relBranchVersionDigitsArray=( ${relBranchVersionDigits//\./ } )
254 local -i prevTagVersionDigitsCount=${#prevTagVersionDigitsArray[*]}
255 local -i relBranchVersionDigitsCount=${#relBranchVersionDigitsArray[*]}
256 local prevTagVersionTrain="$(echo "$(stringTrim "${prevTagVersionDigits}")" | \
257 sed -r "s/${versionRegexDigits}/\1/")"
259 if [[ "${prevTagVersionDigits}" == "${relBranchVersionDigits}" ]] || \
260 ([[ "${prevTagVersionTrain}" == "${relBranchVersionDigits}" ]] && \
261 [[ ${prevTagVersionDigitsCount} -eq 4 ]] && \
262 [[ ${relBranchVersionDigitsCount} -eq 3 ]]); then
263 relBranchVersionDigits="$(getNextVersionDigitsPatchLevel "${prevTagVersionDigits}")"
269 # Check that the new version is incrementing
273 function checkVersionIncrementing() {
274 local lastVersion="$(stringTrim "${1}")"
275 local newVersion="$(stringTrim "${2}")"
276 local errorstr="* The new version ${newVersion} is not greater than the previous version ${lastVersion}"
278 local -a lastVersionDigits=( ${lastVersion//\./ } )
279 local -a newVersionDigits=( ${newVersion//\./ } )
281 # if the last version is in the format 0.6.4 then assume 0.6.4.0
282 if [[ ${#lastVersionDigits[*]} -ne 4 ]]; then
283 lastVersionDigits[3]=0
286 # if the new version is in the format 0.6.4 then assume 0.6.4.0
287 if [[ ${#newVersionDigits[*]} -ne 4 ]]; then
288 newVersionDigits[3]=0
292 if [[ ${newVersionDigits[0]} -lt ${lastVersionDigits[0]} ]]; then
296 if [[ ${newVersionDigits[0]} -gt ${lastVersionDigits[0]} ]]; then
301 if [[ ${newVersionDigits[1]} -lt ${lastVersionDigits[1]} ]]; then
305 if [[ ${newVersionDigits[1]} -gt ${lastVersionDigits[1]} ]]; then
310 if [[ ${newVersionDigits[2]} -lt ${lastVersionDigits[2]} ]]; then
314 if [[ ${newVersionDigits[2]} -gt ${lastVersionDigits[2]} ]]; then
319 if [[ ${newVersionDigits[3]} -lt ${lastVersionDigits[3]} ]]; then
323 if [[ ${newVersionDigits[3]} -gt ${lastVersionDigits[3]} ]]; then
327 # everything is equal
334 # Commit the current changes, allow an empty commit, or amend (when the commit
335 # message is the same as that of the last commit)
337 # 1=non-zero to allow an empty commit
339 function commitChanges() {
340 local -i allowEmpty=${1}
341 local msg="$(stringTrim "${2}")"
343 local lastMsg="$(git log -1 --format="%s")"
344 lastMsg="$(stringTrim "${lastMsg}")"
346 if [[ ${allowEmpty} -ne 0 ]]; then
347 extra="${extra} --allow-empty"
349 if [[ "${msg}" == "${lastMsg}" ]]; then
350 extra="${extra} --amend"
353 git commit -s -q ${extra} -m "${msg}" &> /dev/null
359 # Update the version in all relevant files
361 # 1=the new version (in the format of versionRegexSources)
362 function updateVersions() {
363 local newVersion="$(stringTrim "${1}")"
366 # Adjust debug settings in Makefile.inc
368 local src="Makefile.inc"
370 -e 's/^[[:space:]]*DEBUG[[:space:]]*?=.*$/DEBUG ?= 1/' \
371 -e 's/^[[:space:]]*NO_DEBUG_MESSAGES[[:space:]]*?=.*$/NO_DEBUG_MESSAGES ?= 0/' \
379 # Adjust version in Makefile
382 sed -ri "s/^([[:space:]]*VERS[[:space:]]*=[[:space:]]*)${versionRegexSources}[[:space:]]*\$/\1${newVersion}/" "${src}"
389 # Adjust version in win32 gui installer
391 local src="gui/win32/Inst/installer.nsi"
392 local grepStr="^([[:space:]]*MessageBox[[:space:]]+MB_YESNO[[:space:]]+\".+?[[:space:]]+olsr\.org[[:space:]]+)${versionRegexSources}([[:space:]]+.+?\"[[:space:]]+IDYES[[:space:]]+NoAbort)[[:space:]]*$"
393 local replStr="\1${newVersion}\6"
394 sed -ri "s/${grepStr}/${replStr}/" "${src}"
401 # Adjust version in win32 gui front-end
403 local src="gui/win32/Main/Frontend.rc"
404 local grepStr="^([[:space:]]*CAPTION[[:space:]]+\"olsr\.org[[:space:]]+Switch[[:space:]]+)${versionRegexSources}([[:space:]]*\")[[:space:]]*\$"
405 local replStr="\1${newVersion}\6"
406 sed -ri "s/${grepStr}/${replStr}/" "${src}"
417 function signTextFile() {
418 local txtFile="$(stringTrim "${1}")"
419 gpg -u "$(git config --get user.name)" --clearsign "${txtFile}"
420 mv "${txtFile}.asc" "${txtFile}"
426 # ##############################################################################
428 # ##############################################################################
430 declare script="$(pathCanonicalPath "${0}")"
431 declare scriptDir="$(dirname "${script}")"
432 declare baseDir="$(dirname "${scriptDir}")"
438 # Check the number of arguments
440 if [[ ${#} -lt 1 ]]; then
441 echo "* Need at least 1 argument:"
448 # Get the mode and check it
450 declare mode="$(stringTrim "${1}")"
452 if [[ ! "${mode}" == "${MODE_BRANCH}" ]] && \
453 [[ ! "${mode}" == "${MODE_RELEASE}" ]]; then
454 echo "* Wrong mode: ${mode}"
461 # Further mode/argument parsing
463 declare branchVersion=""
464 if [[ "${mode}" == "${MODE_BRANCH}" ]]; then
465 MODE_TXT="${MODE_BRANCH_TXT}"
466 MODE_TXT_LOWER="${MODE_BRANCH_TXT_LOWER}"
469 # Get the branch version to create
471 if [[ ${#} -ne 1 ]]; then
472 echo "* Need the version to branch:"
476 branchVersion="$(stringTrim "${1}")"
480 # Check branch version
482 if [[ -z "$(echo "${branchVersion}" | grep -E "^${versionRegexDigitsBasic}\$")" ]]; then
483 echo "* Version to branch ${branchVersion} has invalid format"
484 echo " Expected format is: 0.6.4"
488 MODE_TXT="${MODE_RELEASE_TXT}"
489 MODE_TXT_LOWER="${MODE_RELEASE_TXT_LOWER}"
491 if [[ ${#} -ne 0 ]]; then
492 echo "* Need no additional arguments."
499 checkIsOlsrdGitCheckout
501 if [[ "${mode}" == "${MODE_RELEASE}" ]]; then
502 checkGitSigningKeyIsConfigured
506 declare prevTagVersionDigits="$(getVersionDigitsFromReleaseTag "${prevRelTagVersion}")"
510 # Get the current branch and check that we're on a release branch (for the
511 # release mode) or on the master branch (for the branch mode)
513 declare relBranch="$(git rev-parse --abbrev-ref HEAD)"
514 declare relBranch="$(stringTrim "${relBranch}")"
515 if [[ "${mode}" == "${MODE_BRANCH}" ]]; then
516 if [[ -z "$(echo "${relBranch}" | grep -E "^master\$")" ]]; then
517 echo "* You are not on the master branch"
520 relBranch="release-${branchVersion}"
522 # check that the branch does not yet exist
523 declare -i branchTestResult=0
525 git rev-parse --abbrev-ref "${relBranch}" &> /dev/null
526 branchTestResult=${?}
528 if [[ ${branchTestResult} -eq 0 ]]; then
529 echo "* Branch ${relBranch} already exists"
533 if [[ -z "$(echo "${relBranch}" | grep -E "^${relBranchRegex}\$")" ]]; then
534 echo "* You are not on a release branch (format: release-0.6.4 or release-0.6.4.1)"
541 # Get the version to release from the current branch
543 declare relBranchVersionDigits=""
544 if [[ "${mode}" == "${MODE_BRANCH}" ]]; then
545 relBranchVersionDigits="${branchVersion}"
547 relBranchVersionDigits="$(echo "${relBranch}" | \
548 sed -r "s/${relBranchRegex}/\1/")"
552 declare relTagVersion="v${relBranchVersionDigits}"
553 declare relBranchVersionDigitsNextMicro="$(getNextVersionDigitsMicro "${relBranchVersionDigits}")"
554 declare relBranchVersionDigitsNextPatchLevel="$(getNextVersionDigitsPatchLevel "${relBranchVersionDigits}")"
558 # Check that the version is incrementing
560 checkVersionIncrementing "${prevTagVersionDigits}" "${relBranchVersionDigits}"
564 # Confirm the branch/release
569 * All checks pass, ready to ${MODE_TXT_LOWER} ${relBranchVersionDigits}.
571 * The previous version found is: ${prevTagVersionDigits}
572 Note: If this is not the version you were expecting, then maybe that
573 version wasn't merged into this branch.
574 * Continuing will DESTROY any modifications you currently have in your tree!
577 read -p "Press [enter] to continue or CTRL-C to exit..."
583 # Clean up the checkout
585 echo "Cleaning the git checkout..."
590 if [[ "${mode}" == "${MODE_BRANCH}" ]]; then
592 # Update the versions for branch
594 echo "Updating the version to pre-${relBranchVersionDigits}..."
595 updateVersions "pre-${relBranchVersionDigits}"
596 commitChanges 1 "${MODE_TXT} ${relTagVersion}"
598 # create release branch
599 echo "Creating the release branch ${relBranch}..."
600 git branch "${relBranch}"
604 # Update the version to the next release
606 echo "Updating the version to pre-${relBranchVersionDigitsNextMicro}..."
607 updateVersions "pre-${relBranchVersionDigitsNextMicro}"
608 commitChanges 0 "Update version after ${MODE_TXT_LOWER} of ${relTagVersion}"
611 # Update the versions for release
613 echo "Updating the version to ${relBranchVersionDigits}..."
614 updateVersions "${relBranchVersionDigits}"
615 commitChanges 1 "${MODE_TXT} ${relTagVersion}"
619 # Generate the changelog
621 echo "Generating the changelog..."
622 declare src="CHANGELOG"
623 declare dst="mktemp -q -p . -t "${src}.XXXXXXXXXX""
624 cat > "${dst}" << EOF
625 ${relBranchVersionDigits} -------------------------------------------------------------------
628 git rev-list --pretty=short "${prevRelTagVersion}..HEAD" | \
629 git shortlog -w80 -- >> "${dst}"
630 cat "${src}" >> "${dst}"
635 commitChanges 1 "${MODE_TXT} ${relTagVersion}"
641 echo "Tagging ${relTagVersion}..."
643 git tag -d "${relTagVersion}" &> /dev/null
645 git tag -s -m "OLSRd release ${relBranchVersionDigits}" "${relTagVersion}"
649 # Update the version to the next release
651 echo "Updating the version to pre-${relBranchVersionDigitsNextPatchLevel}..."
652 updateVersions "pre-${relBranchVersionDigitsNextPatchLevel}"
653 commitChanges 1 "Update version after ${MODE_TXT_LOWER} of ${relTagVersion}"
657 # Update the version (on the master branch) to the next release
659 echo "Updating the version to pre-${relBranchVersionDigitsNextMicro} on the master branch..."
660 git checkout -q master
663 updateVersions "pre-${relBranchVersionDigitsNextMicro}"
664 commitChanges 0 "Update version after ${MODE_TXT_LOWER} of ${relTagVersion}"
665 git checkout -q "${relBranch}"
671 # Make the release tarballs
673 echo "Generating the release tarballs..."
674 declare tarFile="${scriptDir}/olsrd-${relBranchVersionDigits}.tar"
675 declare tarGzFile="${tarFile}.gz"
676 declare tarBz2File="${tarFile}.bz2"
677 git archive --format=tar --prefix="olsrd-${relBranchVersionDigits}/" --output="${tarFile}" "${relTagVersion}"
678 gzip -c "${tarFile}" > "${tarGzFile}"
679 bzip2 -c "${tarFile}" > "${tarBz2File}"
681 echo "Generating the release tarball checksums..."
682 declare md5File="${scriptDir}/MD5SUM-${relBranchVersionDigits}"
683 declare sha256File="${scriptDir}/SHA256SUM-${relBranchVersionDigits}"
684 md5sum "${tarGzFile}" "${tarBz2File}" > "${md5File}"
685 sha256sum "${tarGzFile}" "${tarBz2File}" > "${sha256File}"
686 echo "Signing the release tarball checksums..."
687 signTextFile "${md5File}"
688 signTextFile "${sha256File}"
697 echo "==================="
698 echo "= Git Updates ="
699 echo "==================="
700 echo "Branch : master"
701 echo "Branch : ${relBranch}"
702 if [[ "${mode}" == "${MODE_RELEASE}" ]]; then
703 echo "Tag : ${relTagVersion}"
708 echo "==================="
709 echo "= Generated Files ="
710 echo "==================="
722 echo "==================="
723 echo "= Manual Actions ="
724 echo "==================="
725 if [[ "${mode}" == "${MODE_RELEASE}" ]]; then
726 echo "1. Check that everything is in order. For example, run:"
727 echo " gitk master ${relBranch} ${relTagVersion}"
728 echo "2. Push. For example, run:"
729 echo " git push origin master ${relBranch} ${relTagVersion}"
730 echo "3. Upload the generated files to"
731 echo " http://www.olsr.org/releases/${relBranchVersionDigits}"
732 echo "4. Add a release article on olsr.org."
735 echo "1. Check that everything is in order. For example, run:"
736 echo " gitk master ${relBranch}"
737 echo "2. Push. For example, run:"
738 echo " git push origin master ${relBranch}"
739 echo "3. Send a 'release branch created' email to olsr-dev@lists.olsr.org."