diff options
Diffstat (limited to 'build-root/autowank')
-rwxr-xr-x | build-root/autowank | 308 |
1 files changed, 308 insertions, 0 deletions
diff --git a/build-root/autowank b/build-root/autowank new file mode 100755 index 00000000..05897065 --- /dev/null +++ b/build-root/autowank @@ -0,0 +1,308 @@ +#!/bin/bash + +# Copyright (c) 2015 Cisco and/or its affiliates. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This aptly-named script verifies and fixes time ordering +# problems with Makefile.{am,in} aclocal.m4 configure* files. + +set -eu +#set -vx + +touch="" +commit="" +comma_v="" +aclocal="" +optimize="" + +# The old autowank scheme used "touch <foo> ; sleep 1" +# to ensure differentiable, ordered timestamps. Worked, but +# took N seconds given N files to fix. We have an example +# which wastes multiple minutes given the old scheme. +# +# This version generates a sequence of timestamps +# starting an hour ago. That gives us +# lots to play with, in case some obnoxious program feels the need +# to complain about timestamps in the future. + +# If we're in UTC+N land, generate UTC+(N+1) +# If we're in UTC-N land, generate UTC-(N-1) + +my_tz=`date +%z` +sign=`echo $my_tz | sed -n -e 's/^\(.\{1\}\).*$/\1/p'` +t=`echo $my_tz | sed -n -e 's/^\(.\{1\}\)//p'` +tz_hour=`echo $t | sed -n -e 's/^\(.\{2\}\).*$/\1/p'` +tz_hour=`echo $tz_hour | sed 's/^0//'` + +if [ $sign = "-" ] ; then + sign="+" + let tz_hour=$tz_hour+1 + if [[ $tz_hour -ge "24" ]] ; then + tz_hour=0 + fi +else + sign="-" + let tz_hour=$tz_hour-1 || true + if [[ $tz_hour -lt "0" ]] ; then + tz_hour=23 + fi +fi + +# Timestamp, an hour ago: +ts_begin=`TZ=UTC${sign}${tz_hour} date +%Y%m%d%H%M.%S` + +# break into constituent parts +year=`echo $ts_begin | sed -n -e 's/^\(.\{4\}\).*$/\1/p'` +t=`echo $ts_begin | sed -n -e 's/^\(.\{4\}\)//p'` +month=`echo $t | sed -n -e 's/^\(.\{2\}\).*$/\1/p'` +t=`echo $t | sed -n -e 's/^\(.\{2\}\)//p'` +day=`echo $t | sed -n -e 's/^\(.\{2\}\).*$/\1/p'` +t=`echo $t | sed -n -e 's/^\(.\{2\}\)//p'` +hour=`echo $t | sed -n -e 's/^\(.\{2\}\).*$/\1/p'` +t=`echo $t | sed -n -e 's/^\(.\{2\}\)//p'` +min=`echo $t | sed -n -e 's/^\(.\{2\}\).*$/\1/p'` +t=`echo $t | sed -n -e 's/^\(.\{2\}\)//p'` +sec=`echo $t | sed -n -e 's/\.//p'` + +# How many days in the current month? +# Good until someone changes the calendar rules +days_in_current_month() { + if [[ $month -eq 9 || $month -eq 4 \ + || $month -eq 6 || $month -eq 11 ]] ; then + return 30; + fi + if [[ $month -eq 2 ]] ; then + let t=($year/400)*400 + if [[ $t -eq $year ]] ; then + return 29; + fi + let t=($year/100)*100 + if [[ $t -eq $year ]] ; then + return 28; + fi + let t=($year/4)*4 + if [[ $t -eq $year ]] ; then + return 29; + fi + return 28; + fi + return 31; +} + +# The next timestamp to issue via touch +# A real hemorrhoid because bash isnt easily convinced +# that 08 is a decimal number +next_ts() { + sec=`echo $sec | sed 's/^0//'` + let sec=$sec+1 + if [[ "$sec" -lt "60" ]] ; then + if [[ "$sec" -lt "10" ]] ; then + sec=0$sec + fi + return 0; + fi + sec="00" + min=`echo $min | sed 's/^0//'` + let min=$min+1 + if [[ "$min" -lt "60" ]] ; then + if [[ "$min" -lt "10" ]] ; then + min=0$min + fi + return 0; + fi + min="00" + hour=`echo $hour | sed 's/^0//'` + let hour=$hour+1 + if [[ "$hour" -lt "24" ]] ; then + if [[ "$hour" -lt "10" ]] ; then + hour=0$hour + fi + return 0; + fi + hour="00" + days_in_current_month + days_in_month=$? + if [[ "$day" -lt "$days_in_month" ]] ; then + day=`echo $day | sed 's/^0//'` + let day=$day+1 + if [[ "$day" -lt "10" ]] ; then + day=0$day + fi + return 0; + fi + day="01" + month=`echo $month | sed 's/^0//'` + let month=$month+1 + if [[ "$month" -lt "13" ]] ; then + if [[ "$month" -lt "10" ]] ; then + month=0$month + fi + return 0; + fi + month="01" + let year=$year+1 + return 0; +} + +while [ $# != 0 ] ; do + case "$1" in + (--commav) comma_v=",v" ;; + (--touch) touch=yes ;; + (--aclocal) aclocal=yes ;; + (--nooptimize) optimize="" ;; + (--commit=*) commit="$1" ;; + (*) echo "$0: usage [--touch|--commit|]" > /dev/stderr + exit 17 ;; + esac + shift +done + +if [ "${aclocal}" != "" ] ; then + if [ -f aclocal.m4 ] ; then + echo touching aclocal.m4 + sleep 1 + touch aclocal.m4 + else + echo aclocal.m4 not found + fi +fi + +if [ "${comma_v}" != "" -a "${commit}" != "" ] ; then + echo "No, you may NOT molest ,v files directly. Go away." > /dev/stderr + exit 1 +fi + +function touchme () +{ + local victim="${1}" + shift + local touchmebaby="" + local sein="is" + local newer="no" + local older="no" + + if [ ! -r "$victim" ] ; then + echo " Possible problem: No $victim exists. " > /dev/stderr + return + fi + + while [ $# != 0 ] ; do + if [ "${1}" -nt "${victim}" ] ; then + newer="yes" + fi + if [ "${1}" -ot "${victim}" ] ; then + older="yes" + fi + if [ "${newer}" = "no" -a "${older}" = "no" ] ; then + newer="yes" + fi + + if [ "${newer}" = "yes" ] ; then + if [ "${touchmebaby}" = "" ] ; then + touchmebaby="${1}" + else + sein="are" + touchmebaby="${touchmebaby} ${1}" + fi + fi + shift + done + if [ -n "${touchmebaby}" ] ; then + echo "*** ${touchmebaby} ${sein} newer than ${victim} " + if [ -n "${touch}" ] ; then + # + # This is the old version, in case something backfires... + if [ "${optimize}" != "yes" ] ; then + echo "Fixing " ;touch -c "$victim" ; sleep 1 + else + echo "Fixing " + # echo touch -c -t $year$month$day$hour$min.$sec "$victim" + touch -c -t $year$month$day$hour$min.$sec "$victim" + next_ts + fi + fi + fi +} + +makefileins="`/usr/bin/find . -name Attic -prune -o -name Makefile.in${comma_v}`" + +# aclocal.m4 depends on ***/Makefile.am, configure.ac, acinclude.m4, *.m4 crap +touchme aclocal.m4${comma_v} \ + `/usr/bin/find . -name Attic -prune -o -name Makefile.am${comma_v}` \ + "configure.in${comma_v}" "configure.ac${comma_v}" \ + "acinclude.m4${comma_v}" + +# Makefile.in must be newer than Makefile.am +for f in $makefileins ; do + d="`dirname ${f}`" + touchme "${d}/Makefile.in${comma_v}" "${d}/Makefile.am${comma_v}" +done + +# Makefile.in depends on aclocal.m4 +for f in $makefileins ; do + d="`dirname $f`" + touchme "${d}/Makefile.in${comma_v}" "aclocal.m4${comma_v}" +done + +# config.in must be newer than aclocal.m4 and configure.ac +if [ -f "config.in${comma_v}" ] ; then + touchme "config.in${comma_v}" "aclocal.m4${comma_v}" \ + "configure.ac${comma_v}" \ + "configure.in${comma_v}" +fi + +# config.h.in (or More Thoroughly Modern configh.in) +# must be newer than aclocal.m4 and (obsolete) acconfig.h +for c_h_in in config.h.in configh.in ; do + if [ -f "${c_h_in}${comma_v}" ]; then + touchme "${c_h_in}${comma_v}" "aclocal.m4${comma_v}" "acconfig.h${comma_v}" + #>>>> WTF? Why? This is nonsensical + ## ***/Makefile.in must be newer than config.h.in + #for f in $makefileins ; do + # touchme "$f" "${c_h_in}${comma_v}" + #done + fi +done + +# configure must be newer than everything +# touchme configure $makefileins -- why would this be needed? +touchme "configure${comma_v}" "aclocal.m4${comma_v}" "acconfig.h${comma_v}" \ + "config.in${comma_v}" "config.h.in${comma_v}" \ + "configh.in${comma_v}" + +if [ -n "${commit}" ] ; then + commit="${commit:9}" # strip off "--commit=" + # First ***/Makefile.am, + # configure.in, configure.ac, + # ***/*.m4 + # acconfig.h + cvs commit -m "${commit}" \ + `for f in ${makefileins} ; do \ + [ -f "$${f%.in}.am" ] && echo "$${f%.in}.am" ; \ + done` \ + `[ -f configure.in ] && echo configure.in` \ + `[ -f configure.ac ] && echo configure.ac` \ + `[ -f acconfig.h ] && echo acconfig.h` \ + `/usr/bin/find . -name '*.m4' -mindepth 2` + + # Next aclocal.m4 + [ -f "aclocal.m4" ] && cvs commit -m "${commit}" aclocal.m4 + + # Next config.in, config.h.in, configh.in + [ -f "config.in" ] && cvs commit -m "${commit}" config.in + [ -f "config.h.in" ] && cvs commit -m "${commit}" config.h.in + [ -f "configh.in" ] && cvs commit -m "${commit}" configh.in + + # Last ***/Makefile.in, configure + cvs commit -m "${commit}" ${makefileins} configure +fi |