1#!/usr/bin/env bash 2# 3# Licensed to the Apache Software Foundation (ASF) under one 4# or more contributor license agreements. See the NOTICE file 5# distributed with this work for additional information 6# regarding copyright ownership. The ASF licenses this file 7# to you under the Apache License, Version 2.0 (the 8# "License"); you may not use this file except in compliance 9# with the License. You may obtain a copy of the License at 10# 11# http://www.apache.org/licenses/LICENSE-2.0 12# 13# Unless required by applicable law or agreed to in writing, 14# software distributed under the License is distributed on an 15# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16# KIND, either express or implied. See the License for the 17# specific language governing permissions and limitations 18# under the License. 19# 20 21# 22# The veralign script sets the appropriate versions in all of 23# the package configuration files for all of the supported 24# languages. It is used to prepare a release or move master 25# forward to the next anticipated version. 26# 27# USAGE 28# ----------------------------------------------------------- 29# usage: veralign.sh <oldVersion> <newVersion> 30# 31# EXAMPLE 32# ----------------------------------------------------------- 33# $ ./veralign.sh 0.12.0 1.0.0 34# $ ./veralign.sh 1.0.0 1.1.0 35# 36# IMPORTANT USAGE NOTE 37# ----------------------------------------------------------- 38# Define the environment variable DRYRUN to have the script 39# print out all matches to the oldVersion hilighted so that 40# you can verify it will change the right things. 41# 42 43declare -A FILES 44 45# These files require a manual touch: 46FILES[CHANGES.md]=manual 47FILES[debian/changelog]=manual 48FILES[doap.rdf]=manual 49 50# These files can be updated automatically: 51FILES[ApacheThrift.nuspec]=simpleReplace 52FILES[appveyor.yml]=simpleReplace 53FILES[bower.json]=jsonReplace 54FILES[CMakeLists.txt]=simpleReplace 55FILES[compiler/cpp/src/thrift/version.h]=simpleReplace 56FILES[configure.ac]=configureReplace 57FILES[contrib/Rebus/Properties/AssemblyInfo.cs]=simpleReplace 58FILES[contrib/thrift.spec]=simpleReplace 59FILES[contrib/zeromq/csharp/AssemblyInfo.cs]=simpleReplace 60FILES[doc/specs/idl.md]=simpleReplace 61FILES[lib/as3/gradle.properties]=simpleReplace 62FILES[lib/d/src/thrift/base.d]=simpleReplace 63FILES[lib/dart/pubspec.yaml]=pubspecReplace 64FILES[lib/delphi/src/Thrift.pas]=simpleReplace 65FILES[lib/erl/src/thrift.app.src]=simpleReplace 66FILES[lib/haxe/haxelib.json]=simpleReplace 67FILES[lib/hs/thrift.cabal]=simpleReplace 68FILES[lib/java/gradle.properties]=simpleReplace 69FILES[lib/js/package-lock.json]=jsonReplace 70FILES[lib/js/package.json]=jsonReplace 71FILES[lib/js/src/thrift.js]=simpleReplace 72FILES[lib/lua/Thrift.lua]=simpleReplace 73FILES[lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Properties/AssemblyInfo.cs]=simpleReplace 74FILES[lib/netstd/Thrift/Properties/AssemblyInfo.cs]=simpleReplace 75FILES[lib/netstd/Thrift/Properties/AssemblyInfo.cs]=simpleReplace 76FILES[lib/netstd/Thrift/Thrift.csproj]=simpleReplace 77FILES[lib/ocaml/_oasis]=simpleReplace 78FILES[lib/perl/lib/Thrift.pm]=simpleReplace 79FILES[lib/py/setup.py]=simpleReplace 80FILES[lib/rb/thrift.gemspec]=simpleReplace 81FILES[lib/rs/Cargo.toml]=simpleReplace 82FILES[lib/st/package.xml]=simpleReplace 83FILES[lib/swift/Sources/Thrift.swift]=simpleReplace 84FILES[lib/swift/Tests/ThriftTests/ThriftTests.swift]=simpleReplace 85FILES[lib/ts/package-lock.json]=jsonReplace 86FILES[lib/ts/package.json]=jsonReplace 87FILES[package-lock.json]=jsonReplace 88FILES[package.json]=jsonReplace 89FILES[sonar-project.properties]=simpleReplace 90FILES[test/dart/test_client/pubspec.yaml]=pubspecReplace 91FILES[test/erl/src/thrift_test.app.src]=simpleReplace 92FILES[test/netstd/Client/Properties/AssemblyInfo.cs]=simpleReplace 93FILES[test/netstd/Server/Properties/AssemblyInfo.cs]=simpleReplace 94FILES[Thrift.podspec]=simpleReplace 95FILES[tutorial/dart/client/pubspec.yaml]=pubspecReplace 96FILES[tutorial/dart/console_client/pubspec.yaml]=pubspecReplace 97FILES[tutorial/dart/server/pubspec.yaml]=pubspecReplace 98FILES[tutorial/delphi/DelphiClient/DelphiClient.dproj]=simpleReplace 99FILES[tutorial/delphi/DelphiServer/DelphiServer.dproj]=simpleReplace 100FILES[tutorial/hs/ThriftTutorial.cabal]=simpleReplace 101FILES[tutorial/netstd/Client/Properties/AssemblyInfo.cs]=simpleReplace 102FILES[tutorial/netstd/Interfaces/Properties/AssemblyInfo.cs]=simpleReplace 103FILES[tutorial/netstd/Server/Properties/AssemblyInfo.cs]=simpleReplace 104FILES[tutorial/ocaml/_oasis]=simpleReplace 105 106 107 108if [ ! -f "CHANGES.md" ]; then 109 >&2 echo "error: run veralign.sh while in the thrift root directory" 110 exit 1 111fi 112 113if [ $# -ne 2 ]; then 114 >&2 echo "usage: veralign.sh <oldVersion> <newVersion>" 115 exit 1 116fi 117 118jq --version 1>/dev/null 2>/dev/null 119if [ $? -ne 0 ]; then 120 >&2 echo "error: the 'jq' package is not installed" 121 exit 1 122fi 123 124# 125# validateVersion: check that a version matches the major.minor.patch 126# format which is the lowest common denominator supported by all 127# project systems. 128# \param $1 the version 129# \returns 0 if the version is compliant 130# 131function validateVersion 132{ 133 local result 134 local valid 135 valid=$(echo "$1" | sed '/^[[:digit:]]\+\.[[:digit:]]\+\.[[:digit:]]\+$/!{q22}') 136 result=$? 137 if [ $result -eq 22 ]; then 138 >&2 echo "error: version '$1' does not conform to the required major.minor.patch format" 139 return ${result} 140 fi 141} 142 143OLDVERSION=$1 144NEWVERSION=$2 145validateVersion "${OLDVERSION}" || exit $? 146validateVersion "${NEWVERSION}" || exit $? 147 148# 149# escapeVersion: escape the version for use as a sed search 150# \param $1 the version to escape 151# \output the escaped string 152# \returns 0 153# \example VERSEARCH=$(escapeVersion "[1.0.0]"); echo $VERSEARCH; => "\[1\.0\.0\]" 154# 155function escapeVersion 156{ 157 echo "$(echo $1 | sed 's/\./\\./g' | sed 's/\[/\\\[/g' | sed 's/\]/\\\]/g')" 158} 159 160# Set up verbose hilighting if running interactive 161if [ "$(tput colors)" -ne 0 ]; then 162 reverse=$(tput rev) 163 red=$(tput setaf 1) 164 green=$(tput setaf 2) 165 yellow=$(tput setaf 3) 166 normal=$(tput sgr0) 167fi 168 169declare -A MANUAL 170 171# 172# manual: note that update of said file is manual 173# \param $1 filename to do replacements on 174# \returns 0 175# 176function manual 177{ 178 MANUAL["$1"]="" 179 return 0 180} 181 182# 183# configureReplace: replace the AC_INIT field in configure.ac 184# \param $1 filename to do replacements on 185# \returns 0 on success 186# 187 188function configureReplace 189{ 190 replace "$1" "[thrift], [${OLDVERSION}]" "[thrift], [${NEWVERSION}]" 191} 192 193# 194# jsonReplace: replace a specific version field in a JSON file 195# must be a top level "version" field in the json structure 196# \param $1 filename to do replacements on 197# \returns 0 on success 198# 199 200function jsonReplace 201{ 202 local result 203 local output 204 if [ ! -z "$DRYRUN" ]; then 205 output=$(jq -e ".version" "$1") 206 else 207 output=$(jq -e ".version = \"${NEWVERSION}\"" "$1" > tmp.$$.json && mv tmp.$$.json "$1") 208 fi 209 result=$? 210 if [ $? -ne 0 ]; then 211 printf "%-60s | %5d | ${red}ERROR${normal}: version tag not found" "$1" "$count" 212 echo 213 return 1 214 elif [ ! -z "$DRYRUN" ]; then 215 output=${output%\"} 216 output=${output#\"} 217 printf "%-60s | %5d | MATCHES: version: \"${reverse}${green}${output}${normal}\"" "$1" 1 218 echo 219 return 0 220 fi 221 printf "%-60s | %5d | ${green}OK${normal}" "$1" 1 222 echo 223 return 0 224} 225 226# 227# pubspecReplace: replace a specific version field in a YAML file 228# must be a top level "version" field in the yaml structure 229# did not find a package that preserves comments so this is 230# somewhat brain-dead, but it gets the job done 231# \param $1 filename to do replacements on 232# \returns 0 on success 233# 234 235function pubspecReplace 236{ 237 replace "$1" "version: ${OLDVERSION}" "version: ${NEWVERSION}" 238} 239 240# 241# replace: replace occurrences of one string with another 242# the file specified must contain the old string at least once 243# in order to be successful. 244# \param $1 filename to do replacements on 245# \param $2 the "old" string to be replaced 246# \param $3 the "new" striing to replace it with 247# \returns 0 on success 248# 249function replace 250{ 251 local result 252 local output 253 local oldString="$2" 254 local newString="$3" 255 local oldRegex=$(escapeVersion "${oldString}") 256 local count=$(grep -Ec "${oldRegex}" "$1") 257 local verbose 258 if [ $count -eq 0 ]; then 259 printf "%-60s | %5d | ${red}NOT FOUND${normal}: ${oldString}" "$1" 0 260 echo 261 return 1 262 elif [ ! -z "$DRYRUN" ]; then 263 printf "%-60s | %5d | MATCHES:" "$1" "$count" 264 echo 265 while read -r line; do 266 echo " > $(echo "$line" | sed "s/${oldRegex}/${reverse}${green}${oldString}${normal}/g")" 267 done < <(grep -E "${oldRegex}" "$1") 268 return 0 269 fi 270 output=$(sed -i "s/${oldRegex}/${newString}/g" "$1") 271 result=$? 272 if [ $result -ne 0 ]; then 273 printf "%-60s | %5d | ${red}ERROR${normal}: %s" "$1" "$count" "$output" 274 echo 275 return 1 276 fi 277 printf "%-60s | %5d | ${green}OK${normal}" "$1" "$count" 278 echo 279 return 0 280} 281 282# 283# simpleReplace: replace occurrences of ${OLDVERSION} with ${NEWVERSION} 284# the file specified must contain OLDVERSION at least once 285# in order to be successful. 286# \param $1 filename to do replacements on 287# \param $2 the "old" string to be replaced 288# \param $3 the "new" striing to replace it with 289# \returns 0 on success 290# 291function simpleReplace 292{ 293 replace "$1" "${OLDVERSION}" "${NEWVERSION}" 294} 295 296echo "" 297echo "Apache Thrift Version Alignment Tool" 298echo "------------------------------------" 299echo "" 300echo "Previous Version: ${OLDVERSION}" 301echo " New Version: ${NEWVERSION}" 302echo "" 303echo "-------------------------------------------------------------+-------+----------------------" 304echo "Filename | Count | Status " 305echo "-------------------------------------------------------------+-------+----------------------" 306 307for file in $(echo "${!FILES[@]}" | sort); do 308 ${FILES[$file]} $file || exit $? 309done 310 311echo 312echo "Files that must be modified manually:" 313echo 314for manu in $(echo "${!MANUAL[@]}" | sort); do 315 echo " > ${yellow}${manu}${normal}" 316done 317 318exit 0 319