diff --git a/maint/bumplibs.sh b/maint/bumplibs.sh index 3231532022..74bd3b5a29 100755 --- a/maint/bumplibs.sh +++ b/maint/bumplibs.sh @@ -1,136 +1,222 @@ #!/bin/bash # # Copyright 2012-2019 the Pacemaker project contributors # # The version control history for this file may have further details. # # This source code is licensed under the GNU General Public License version 2 # or later (GPLv2+) WITHOUT ANY WARRANTY. # -declare -A headers -headers[crmcommon]="include/crm/common include/crm/crm.h" -headers[crmcluster]="include/crm/cluster.h" -headers[crmservice]="include/crm/services.h" -headers[transitioner]="include/crm/transition.h" -headers[cib]="include/crm/cib.h include/crm/cib/util.h" -headers[pe_rules]="include/crm/pengine/rules.h" -headers[pe_status]="include/crm/pengine/common.h include/crm/pengine/complex.h include/crm/pengine/rules.h include/crm/pengine/status.h" -headers[pengine]="include/crm/pengine/common.h include/crm/pengine/complex.h include/crm/pengine/rules.h include/crm/pengine/status.h" -headers[stonithd]="include/crm/stonith-ng.h" -headers[lrmd]="include/crm/lrmd.h" - -if [ ! -z $1 ]; then - LAST_RELEASE=$1 -else - LAST_RELEASE=`test -e /Volumes || git tag -l | grep Pacemaker | grep -v rc | sort -Vr | head -n 1` -fi -libs=$(find . -name "*.am" -exec grep "lib.*_la_LDFLAGS.*version-info" \{\} \; | sed -e s/_la_LDFLAGS.*// -e s/^lib//) -for lib in $libs; do - if [ -z "${headers[$lib]}" ]; then - echo "Unknown headers for lib$lib" - exit 0 +declare -A HEADERS +HEADERS[cib]="include/crm/cib.h include/crm/cib/*.h" +HEADERS[crmcommon]="include/crm/crm.h + include/crm/attrd.h + include/crm/msg_xml.h + include/crm/common/*.h" +HEADERS[crmcluster]="include/crm/cluster.h include/crm/cluster/*.h" +HEADERS[crmservice]="include/crm/services.h" +HEADERS[lrmd]="include/crm/lrmd*.h" +HEADERS[pacemaker]="include/pacemaker*.h include/pcmki/*.h" +HEADERS[pe_rules]="include/crm/pengine/rules*.h" +HEADERS[pe_status]="include/crm/pengine/*.h" +HEADERS[stonithd]="include/crm/stonith-ng.h include/crm/fencing/*.h" + +prompt_to_continue() { + local RESPONSE + + read -p "Continue? " RESPONSE + case "$RESPONSE" in + y|Y|yes|ano|ja|si|oui) ;; + *) exit 0 ;; + esac +} + +find_last_release() { + if [ ! -z "$1" ]; then + echo "$1" + else + git tag -l | grep Pacemaker | grep -v rc | sort -Vr | head -n 1 fi - git diff -w $LAST_RELEASE..HEAD ${headers[$lib]} - echo "" +} + +find_libs() { + find . -name "*.am" -exec grep "lib.*_la_LDFLAGS.*version-info" \{\} \; \ + | sed -e 's/lib\(.*\)_la_LDFLAGS.*/\1/' +} - am=`find . -name Makefile.am -exec grep -lr "lib${lib}_la.*version-info" \{\} \;` - am_dir=`dirname $am` +find_makefile() { + find . -name Makefile.am -exec grep -l "lib${1}_la.*version-info" \{\} \; +} +find_sources() { + local LIB="$1" + local AMFILE="$2" + local SOURCES + + # Library makefiles should use "+=" to break up long sources lines rather + # than backslashed continuation lines, to allow this script to detect + # source files correctly. Warn if that's not the case. if - grep "lib${lib}_la_SOURCES.*\\\\" $am + grep "lib${LIB}_la_SOURCES.*\\\\" $AMFILE then - echo -e "\033[1;35m -- Sources list for lib$lib is probably truncated! --\033[0m" - echo "" + echo -e "\033[1;35m -- Sources list for lib$LIB is probably truncated! --\033[0m" + echo "Edit to use '+=' rather than backslashed continuation lines" + prompt_to_continue fi - sources=`grep "lib${lib}_la_SOURCES" $am | sed s/.*=// | sed 's:$(top_builddir)/::' | sed 's:$(top_srcdir)/::' | sed 's:\\\::' | sed 's:$(libpe_rules_la_SOURCES):rules.c\ common.c:'` - - full_sources="" - for f in $sources; do - if - echo $f | grep -q "/" - then - full_sources="$full_sources $f" - else - full_sources="$full_sources $am_dir/$f" - fi + SOURCES=$(grep "lib${LIB}_la_SOURCES" "$AMFILE" \ + | sed -e 's/.*=//' -e 's/\\//' -e 's:\.\./gnu/:lib/gnu/:') + + for SOURCE in $SOURCES; do + if + echo $SOURCE | grep -q "/" + then + echo "$SOURCE" + else + echo "$(dirname $AMFILE)/$SOURCE" + fi done +} - lines=`git diff -w $LAST_RELEASE..HEAD ${headers[$lib]} $full_sources | wc -l` - - if [ $lines -gt 0 ]; then - echo "- Headers: ${headers[$lib]}" - echo "- Sources: $full_sources" - echo "- Changed Sources since $LAST_RELEASE:" - git diff -w $LAST_RELEASE..HEAD --stat $full_sources - echo "" - echo "New arguments to functions or changes to the middle of structs are incompatible additions" - echo "" - echo "Where possible:" - echo "- move new fields to the end of structs" - echo "- use bitfields instead of booleans" - echo "- when adding arguments, create new functions that the old version can call" - echo "" - read -p "Are the changes to lib$lib: [a]dditions, [i]ncompatible additions, [r]emovals or [f]ixes? [None]: " CHANGE - - git show $LAST_RELEASE:$am | grep version-info - VER=`git show $LAST_RELEASE:$am | grep "lib.*${lib}_la.*version-info" | sed s/.*version-info// | awk '{print $1}'` - VER_NOW=`grep "lib.*${lib}_la.*version-info" $am | sed s/.*version-info// | awk '{print $1}'` - VER_1=`echo $VER | awk -F: '{print $1}'` - VER_2=`echo $VER | awk -F: '{print $2}'` - VER_3=`echo $VER | awk -F: '{print $3}'` - VER_1_NOW=`echo $VER_NOW | awk -F: '{print $1}'` - - case $CHANGE in - i|I) - echo "New version with incompatible extensions: x+1:0:0" - VER_1=`expr $VER_1 + 1` - VER_2=0 - VER_3=0 - for h in ${headers[$lib]}; do - sed -i.sed "s/lib${lib}.so.${VER_1_NOW}/lib${lib}.so.${VER_1}/" $h - done - ;; - a|A) - echo "New version with backwards compatible extensions: x+1:0:z+1" - VER_1=`expr $VER_1 + 1` - VER_2=0 - VER_3=`expr $VER_3 + 1` - ;; - R|r) - echo "New backwards incompatible version: x+1:0:0" - VER_1=`expr $VER_1 + 1` - VER_2=0 - VER_3=0 - for h in ${headers[$lib]}; do - sed -i.sed "s/lib${lib}.so.${VER_1_NOW}/lib${lib}.so.${VER_1}/" $h - done - ;; - F|f) - echo "Bugfix: x:y+1:z" - VER_2=`expr $VER_2 + 1` - ;; - esac - VER_NEW=$VER_1:$VER_2:$VER_3 - - if [ ! -z $CHANGE ]; then - if [ $VER_NEW != $VER_NOW ]; then - echo "Updating $lib library version: $VER -> $VER_NEW" - sed -i.sed "s/version-info\ $VER_NOW/version-info\ $VER_NEW/" $am - else - echo "No further version changes needed" - sed -i.sed "s/version-info\ $VER_NOW/version-info\ $VER_NEW/" $am - fi - else - echo "Skipping $lib version" - fi - else - echo "No changes to $lib interface" +extract_version() { + grep "lib${1}_la.*version-info" | sed -e 's/.*version-info\s*\(\S*\)/\1/' +} + +shared_lib_name() { + local LIB="$1" + local VERSION="$2" + + echo "lib${LIB}.so.$(echo $VERSION | cut -d: -f 1)" +} + +process_lib() { + local LIB="$1" + local LAST_RELEASE="$2" + local AMFILE + local SOURCES + local CHANGE + local CHANGES + + if [ -z "${HEADERS[$LIB]}" ]; then + echo "Can't check lib$LIB until this script is updated with its headers" + prompt_to_continue + fi + + AMFILE="$(find_makefile "$LIB")" + + # Get current shared library version + VER_NOW=$(cat $AMFILE | extract_version $LIB) + + # Check whether library existed at last release + git cat-file -e $LAST_RELEASE:$AMFILE 2>/dev/null + if [ $? -ne 0 ]; then + echo "lib$LIB is new, not changing version ($VER_NOW)" + prompt_to_continue + echo "" + return + fi + + # Check whether there were any changes to headers or sources + SOURCES="$(find_sources "$LIB" "$AMFILE")" + CHANGES=$(git diff -w $LAST_RELEASE..HEAD ${HEADERS[$LIB]} $SOURCES | wc -l) + if [ $CHANGES -eq 0 ]; then + echo "No changes to $LIB interface" + prompt_to_continue + echo "" + return + fi + + # Show all header changes since last release + git diff -w $LAST_RELEASE..HEAD ${HEADERS[$LIB]} + + # Show summary of source changes since last release + echo "" + echo "- Headers: ${HEADERS[$LIB]}" + echo "- Changed sources since $LAST_RELEASE:" + git diff -w $LAST_RELEASE..HEAD --stat $SOURCES + echo "" + + # Ask for human guidance + # @TODO: change default based on intelligent analysis + echo "Are the changes to lib$LIB:" + read -p "[c]ompatible additions, [i]ncompatible additions/removals or [f]ixes? [None]: " CHANGE + + # Get (and show) shared library version at last release + VER=$(git show $LAST_RELEASE:$AMFILE | extract_version $LIB) + VER_1=$(echo $VER | awk -F: '{print $1}') + VER_2=$(echo $VER | awk -F: '{print $2}') + VER_3=$(echo $VER | awk -F: '{print $3}') + echo "lib$LIB version at $LAST_RELEASE: $VER" + + # Show current shared library version if changed + if [ $VER_NOW != $VER ]; then + echo "lib$LIB version currently: $VER_NOW" fi - read -p "Continue?" + # Calculate new library version + case $CHANGE in + i|I) + echo "New backwards-incompatible version: x+1:0:0" + VER_1=$(expr $VER_1 + 1) + VER_2=0 + VER_3=0 + + # Some headers define constants for shared library names, + # update them if the name changed + for H in ${HEADERS[$LIB]}; do + sed -i -e "s/$(shared_lib_name "$LIB" "$VER_NOW")/$(shared_lib_name "$LIB" "$VER_1:0:0")/" $H + done + ;; + c|C) + echo "New version with backwards-compatible extensions: x+1:0:z+1" + VER_1=$(expr $VER_1 + 1) + VER_2=0 + VER_3=$(expr $VER_3 + 1) + ;; + F|f) + echo "Code changed though interfaces didn't: x:y+1:z" + VER_2=$(expr $VER_2 + 1) + ;; + *) + echo "Not updating lib$LIB version" + prompt_to_continue + CHANGE="" + ;; + esac + VER_NEW=$VER_1:$VER_2:$VER_3 + + if [ ! -z $CHANGE ]; then + if [ "$VER_NEW" != "$VER_NOW" ]; then + echo "Updating lib$LIB version from $VER_NOW to $VER_NEW" + prompt_to_continue + sed -i "s/version-info\s*$VER_NOW/version-info $VER_NEW/" $AMFILE + else + echo "No version change needed for lib$LIB" + prompt_to_continue + fi + fi echo "" +} + +echo "Definitions:" +echo "- Compatible additions: new public API functions, structs, etc." +echo "- Incompatible additions/removals: new arguments to public API functions," +echo " new members added to the middle of public API structs," +echo " removal of any public API, etc." +echo "- Fixes: any other code changes at all" +echo "" +echo "When possible, improve backward compatibility first:" +echo "- move new members to the end of structs" +echo "- use bitfields instead of booleans" +echo "- when adding arguments, create a new function that the old one can wrap" +echo "" +prompt_to_continue + +LAST_RELEASE=$(find_last_release "$1") +for LIB in $(find_libs); do + process_lib "$LIB" "$LAST_RELEASE" done +# Show all proposed changes git diff -w