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 --match 'v[0-9].[0-9].[0-9]' | \
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 # 3= 0 to disallow equal versions as ok
274 # return (in checkVersionIncrementingResult) = 0 when new version > last version,
276 declare -i checkVersionIncrementingResult=0
277 function checkVersionIncrementing() {
278 checkVersionIncrementingResult=0
279 local lastVersion="$(stringTrim "${1}")"
280 local newVersion="$(stringTrim "${2}")"
281 local -i allowEqualVersions=${3}
283 local -a lastVersionDigits=( ${lastVersion//\./ } )
284 local -a newVersionDigits=( ${newVersion//\./ } )
286 # if the last version is in the format 0.6.4 then assume 0.6.4.0
287 if [[ ${#lastVersionDigits[*]} -ne 4 ]]; then
288 lastVersionDigits[3]=0
291 # if the new version is in the format 0.6.4 then assume 0.6.4.0
292 if [[ ${#newVersionDigits[*]} -ne 4 ]]; then
293 newVersionDigits[3]=0
297 if [[ ${newVersionDigits[0]} -lt ${lastVersionDigits[0]} ]]; then
298 checkVersionIncrementingResult=1
301 if [[ ${newVersionDigits[0]} -gt ${lastVersionDigits[0]} ]]; then
306 if [[ ${newVersionDigits[1]} -lt ${lastVersionDigits[1]} ]]; then
307 checkVersionIncrementingResult=1
310 if [[ ${newVersionDigits[1]} -gt ${lastVersionDigits[1]} ]]; then
315 if [[ ${newVersionDigits[2]} -lt ${lastVersionDigits[2]} ]]; then
316 checkVersionIncrementingResult=1
319 if [[ ${newVersionDigits[2]} -gt ${lastVersionDigits[2]} ]]; then
324 if [[ ${newVersionDigits[3]} -lt ${lastVersionDigits[3]} ]]; then
325 checkVersionIncrementingResult=1
328 if [[ ${newVersionDigits[3]} -gt ${lastVersionDigits[3]} ]]; then
332 # everything is equal
333 if [[ ${allowEqualVersions} -eq 0 ]]; then
334 checkVersionIncrementingResult=1
341 # Commit the current changes, allow an empty commit, or amend (when the commit
342 # message is the same as that of the last commit)
344 # 1=non-zero to allow an empty commit
346 function commitChanges() {
347 local -i allowEmpty=${1}
348 local msg="$(stringTrim "${2}")"
350 local lastMsg="$(git log -1 --format="%s")"
351 lastMsg="$(stringTrim "${lastMsg}")"
353 if [[ ${allowEmpty} -ne 0 ]]; then
354 extra="${extra} --allow-empty"
356 if [[ "${msg}" == "${lastMsg}" ]]; then
357 extra="${extra} --amend"
360 git commit -s -q ${extra} -m "${msg}" &> /dev/null
366 # Get the version from the Makefile
368 function getVersionFromMakefile() {
370 local regex="([[:space:]]*VERS[[:space:]]*=[[:space:]]*)${versionRegexSources}[[:space:]]*"
371 grep -E "^${regex}\$" "${src}" | sed -r "s/^${regex}\$/\3/"
376 # Update the version in all relevant files
378 # 1=the new version (in the format of versionRegexSources)
379 function updateVersions() {
380 local newVersion="$(stringTrim "${1}")"
383 # Adjust debug settings in Makefile.inc
385 local src="Makefile.inc"
387 -e 's/^[[:space:]]*DEBUG[[:space:]]*?=.*$/DEBUG ?= 1/' \
388 -e 's/^[[:space:]]*NO_DEBUG_MESSAGES[[:space:]]*?=.*$/NO_DEBUG_MESSAGES ?= 0/' \
396 # Adjust version in Makefile
399 sed -ri "s/^([[:space:]]*VERS[[:space:]]*=[[:space:]]*)${versionRegexSources}[[:space:]]*\$/\1${newVersion}/" "${src}"
406 # Adjust version in win32 gui installer
408 local src="gui/win32/Inst/installer.nsi"
409 local grepStr="^([[:space:]]*MessageBox[[:space:]]+MB_YESNO[[:space:]]+\".+?[[:space:]]+olsr\.org[[:space:]]+)${versionRegexSources}([[:space:]]+.+?\"[[:space:]]+IDYES[[:space:]]+NoAbort)[[:space:]]*$"
410 local replStr="\1${newVersion}\6"
411 sed -ri "s/${grepStr}/${replStr}/" "${src}"
418 # Adjust version in win32 gui front-end
420 local src="gui/win32/Main/Frontend.rc"
421 local grepStr="^([[:space:]]*CAPTION[[:space:]]+\"olsr\.org[[:space:]]+Switch[[:space:]]+)${versionRegexSources}([[:space:]]*\")[[:space:]]*\$"
422 local replStr="\1${newVersion}\6"
423 sed -ri "s/${grepStr}/${replStr}/" "${src}"
434 function signTextFile() {
435 local txtFile="$(stringTrim "${1}")"
436 gpg -u "$(git config --get user.name)" --clearsign "${txtFile}"
437 mv "${txtFile}.asc" "${txtFile}"
443 # ##############################################################################
445 # ##############################################################################
447 declare script="$(pathCanonicalPath "${0}")"
448 declare scriptDir="$(dirname "${script}")"
449 declare baseDir="$(dirname "${scriptDir}")"
453 declare -i masterWasUpdated=0
456 # Check the number of arguments
458 if [[ ${#} -lt 1 ]]; then
459 echo "* Need at least 1 argument:"
466 # Get the mode and check it
468 declare mode="$(stringTrim "${1}")"
470 if [[ ! "${mode}" == "${MODE_BRANCH}" ]] && \
471 [[ ! "${mode}" == "${MODE_RELEASE}" ]]; then
472 echo "* Wrong mode: ${mode}"
479 # Further mode/argument parsing
481 declare branchVersion=""
482 if [[ "${mode}" == "${MODE_BRANCH}" ]]; then
483 MODE_TXT="${MODE_BRANCH_TXT}"
484 MODE_TXT_LOWER="${MODE_BRANCH_TXT_LOWER}"
487 # Get the branch version to create
489 if [[ ${#} -ne 1 ]]; then
490 echo "* Need the version to branch:"
494 branchVersion="$(stringTrim "${1}")"
498 # Check branch version
500 if [[ -z "$(echo "${branchVersion}" | grep -E "^${versionRegexDigitsBasic}\$")" ]]; then
501 echo "* Version to branch ${branchVersion} has invalid format"
502 echo " Expected format is: 0.6.4"
506 MODE_TXT="${MODE_RELEASE_TXT}"
507 MODE_TXT_LOWER="${MODE_RELEASE_TXT_LOWER}"
509 if [[ ${#} -ne 0 ]]; then
510 echo "* Need no additional arguments."
517 checkIsOlsrdGitCheckout
519 if [[ "${mode}" == "${MODE_RELEASE}" ]]; then
520 checkGitSigningKeyIsConfigured
524 declare prevTagVersionDigits="$(getVersionDigitsFromReleaseTag "${prevRelTagVersion}")"
528 # Get the current branch and check that we're on a release branch (for the
529 # release mode) or on the master branch (for the branch mode)
531 declare relBranch="$(git rev-parse --abbrev-ref HEAD)"
532 declare relBranch="$(stringTrim "${relBranch}")"
533 if [[ "${mode}" == "${MODE_BRANCH}" ]]; then
534 if [[ -z "$(echo "${relBranch}" | grep -E "^master\$")" ]]; then
535 echo "* You are not on the master branch"
538 relBranch="release-${branchVersion}"
540 # check that the branch does not yet exist
541 declare -i branchTestResult=0
543 git rev-parse --abbrev-ref "${relBranch}" &> /dev/null
544 branchTestResult=${?}
546 if [[ ${branchTestResult} -eq 0 ]]; then
547 echo "* Branch ${relBranch} already exists"
551 if [[ -z "$(echo "${relBranch}" | grep -E "^${relBranchRegex}\$")" ]]; then
552 echo "* You are not on a release branch (format: release-0.6.4 or release-0.6.4.1)"
559 # Get the version to release from the current branch
561 declare relBranchVersionDigits=""
562 if [[ "${mode}" == "${MODE_BRANCH}" ]]; then
563 relBranchVersionDigits="${branchVersion}"
565 relBranchVersionDigits="$(echo "${relBranch}" | \
566 sed -r "s/${relBranchRegex}/\1/")"
570 declare relTagVersion="v${relBranchVersionDigits}"
571 declare relBranchVersionDigitsNextMicro="$(getNextVersionDigitsMicro "${relBranchVersionDigits}")"
572 declare relBranchVersionDigitsNextPatchLevel="$(getNextVersionDigitsPatchLevel "${relBranchVersionDigits}")"
576 # Check that the version is incrementing
578 checkVersionIncrementing "${prevTagVersionDigits}" "${relBranchVersionDigits}" 0
579 if [[ ${checkVersionIncrementingResult} -ne 0 ]]; then
580 echo "* The new version ${relBranchVersionDigits} is not greater than the previous version ${prevTagVersionDigits}"
586 # When branching, check that the version is incrementing (allow equal versions),
587 # w.r.t. the version in the Makefile
589 if [[ "${mode}" == "${MODE_BRANCH}" ]]; then
590 declare currentMasterVersion="$(getVersionFromMakefile)"
591 checkVersionIncrementing "${currentMasterVersion}" "${relBranchVersionDigits}" 1
592 if [[ ${checkVersionIncrementingResult} -ne 0 ]]; then
593 echo "* The new version ${relBranchVersionDigits} is not greater than the current version ${currentMasterVersion}"
600 # Confirm the branch/release
605 * All checks pass, ready to ${MODE_TXT_LOWER} ${relBranchVersionDigits}.
607 * The previous version found is: ${prevTagVersionDigits}
608 Note: If this is not the version you were expecting, then maybe that
609 version wasn't merged into this branch.
610 * Continuing will DESTROY any modifications you currently have in your tree!
613 read -p "Press [enter] to continue or CTRL-C to exit..."
619 # Clean up the checkout
621 echo "Cleaning the git checkout..."
626 if [[ "${mode}" == "${MODE_BRANCH}" ]]; then
628 # Update the versions for branch
630 echo "Updating the version to pre-${relBranchVersionDigits}..."
631 updateVersions "pre-${relBranchVersionDigits}"
632 commitChanges 1 "${MODE_TXT} ${relTagVersion}"
635 # create release branch
636 echo "Creating the release branch ${relBranch}..."
637 git branch "${relBranch}"
641 # Update the version to the next release
643 echo "Updating the version to pre-${relBranchVersionDigitsNextMicro}..."
644 updateVersions "pre-${relBranchVersionDigitsNextMicro}"
645 commitChanges 0 "Update version after ${MODE_TXT_LOWER} of ${relTagVersion}"
648 # Update the versions for release
650 echo "Updating the version to ${relBranchVersionDigits}..."
651 updateVersions "${relBranchVersionDigits}"
652 commitChanges 1 "${MODE_TXT} ${relTagVersion}"
656 # Generate the changelog
658 echo "Generating the changelog..."
659 declare src="CHANGELOG"
660 declare dst="mktemp -q -p . -t "${src}.XXXXXXXXXX""
661 cat > "${dst}" << EOF
662 ${relBranchVersionDigits} -------------------------------------------------------------------
665 git rev-list --pretty=short "${prevRelTagVersion}..HEAD" | \
666 git shortlog -w80 -- >> "${dst}"
667 cat "${src}" >> "${dst}"
672 commitChanges 1 "${MODE_TXT} ${relTagVersion}"
678 echo "Tagging ${relTagVersion}..."
680 git tag -d "${relTagVersion}" &> /dev/null
682 git tag -s -m "OLSRd release ${relBranchVersionDigits}" "${relTagVersion}"
686 # Update the version to the next release
688 echo "Updating the version to pre-${relBranchVersionDigitsNextPatchLevel}..."
689 updateVersions "pre-${relBranchVersionDigitsNextPatchLevel}"
690 commitChanges 1 "Update version after ${MODE_TXT_LOWER} of ${relTagVersion}"
694 # Update the version (on the master branch) to the next release
696 echo "Updating the version to pre-${relBranchVersionDigitsNextMicro} on the master branch..."
697 git checkout -q master
701 declare oldMasterVersion="$(getVersionFromMakefile)"
702 declare newMasterVersion="${relBranchVersionDigitsNextMicro}"
703 checkVersionIncrementing "${oldMasterVersion}" "${newMasterVersion}" 0
704 if [[ ${checkVersionIncrementingResult} -ne 0 ]]; then
705 echo "* Skipped updating the version on the master branch:"
706 echo " The new version ${newMasterVersion} is not greater than the previous version ${oldMasterVersion}"
708 updateVersions "pre-${relBranchVersionDigitsNextMicro}"
709 commitChanges 0 "Update version after ${MODE_TXT_LOWER} of ${relTagVersion}"
713 git checkout -q "${relBranch}"
719 # Make the release tarballs
721 echo "Generating the release tarballs..."
722 declare tarFile="${scriptDir}/olsrd-${relBranchVersionDigits}.tar"
723 declare tarGzFile="${tarFile}.gz"
724 declare tarBz2File="${tarFile}.bz2"
725 git archive --format=tar --prefix="olsrd-${relBranchVersionDigits}/" --output="${tarFile}" "${relTagVersion}"
726 gzip -c "${tarFile}" > "${tarGzFile}"
727 bzip2 -c "${tarFile}" > "${tarBz2File}"
729 echo "Generating the release tarball checksums..."
730 declare md5File="${scriptDir}/MD5SUM-${relBranchVersionDigits}"
731 declare sha256File="${scriptDir}/SHA256SUM-${relBranchVersionDigits}"
732 md5sum "${tarGzFile}" "${tarBz2File}" > "${md5File}"
733 sha256sum "${tarGzFile}" "${tarBz2File}" > "${sha256File}"
734 echo "Signing the release tarball checksums..."
735 signTextFile "${md5File}"
736 signTextFile "${sha256File}"
745 echo "==================="
746 echo "= Git Updates ="
747 echo "==================="
748 if [[ ${masterWasUpdated} -ne 0 ]]; then
749 echo "Branch : master"
751 echo "Branch : ${relBranch}"
752 if [[ "${mode}" == "${MODE_RELEASE}" ]]; then
753 echo "Tag : ${relTagVersion}"
758 echo "==================="
759 echo "= Generated Files ="
760 echo "==================="
772 echo "==================="
773 echo "= Manual Actions ="
774 echo "==================="
775 if [[ "${mode}" == "${MODE_RELEASE}" ]]; then
776 echo "1. Check that everything is in order. For example, run:"
777 if [[ ${masterWasUpdated} -ne 0 ]]; then
778 echo " gitk master ${relBranch} ${relTagVersion}"
780 echo " gitk ${relBranch} ${relTagVersion}"
782 echo "2. Push. For example, run:"
783 if [[ ${masterWasUpdated} -ne 0 ]]; then
784 echo " git push origin master ${relBranch} ${relTagVersion}"
786 echo " git push origin ${relBranch} ${relTagVersion}"
788 echo "3. Upload the generated files to"
789 echo " http://www.olsr.org/releases/${relBranchVersionDigits}"
790 echo "4. Add a release article on olsr.org."
793 echo "1. Check that everything is in order. For example, run:"
794 if [[ ${masterWasUpdated} -ne 0 ]]; then
795 echo " gitk master ${relBranch}"
797 echo " gitk ${relBranch}"
799 echo "2. Push. For example, run:"
800 if [[ ${masterWasUpdated} -ne 0 ]]; then
801 echo " git push origin master ${relBranch}"
803 echo " git push origin ${relBranch}"
805 echo "3. Send a 'release branch created' email to olsr-dev@lists.olsr.org."