#!/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 ; 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" ] ;