308 lines
8.4 KiB
Plaintext
308 lines
8.4 KiB
Plaintext
|
#!/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
|