| #!/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 |
| 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 |