source ~/lib/sh/include
include fsetenv
require setenv
require set_invocation_name
require bomb
include time
include util
fsetenv progname set_invocation_name
setenv progname ${progname:2}
setenv custdir ~/work/$(<~/.gowhich)
setenv logbase $custdir/log
setenv taskdir $logbase/tasks
setenv HISTTIMEFORMAT %Y%m%d%H%M%S
setenv now_timefmt $(date +$HISTTIMEFORMAT)
fsetenv now_touchfmt timefmt_to_touchfmt $now_timefmt
setenv random $(uuid)
echo_last ()
{
printf \
"in %s as of %s, %s\n" \
$lastmode \
${lasttime:-never} \
$(
ls -1t $taskdir |
head -1 |
sed -r 's,\.[[:digit:]]+$,,'
)
}
set_time_envs ()
{
fsetenv ttime_touchfmt timefmt_to_touchfmt $arg
fsetenv ttime_time_t timefmt_to_time_t $arg
setenv just_before_time_t $((ttime_time_t - 1))
fsetenv just_before_timefmt time_t_to_timefmt $just_before_time_t
fsetenv just_before_touchfmt timefmt_to_touchfmt $just_before_timefmt
setenv just_after_time_t $((ttime_time_t + 1))
fsetenv just_after_timefmt time_t_to_timefmt $just_after_time_t
fsetenv just_after_touchfmt timefmt_to_touchfmt $just_after_timefmt
}
if (($# > 1)) && [[ "$1" == '-f' ]]; then skip_sanity_check=1; shift; fi
if [[ $progname =~ '^(start|stop|rmstart|rmstop)$' ]]
then
if (($# == 0)); then arg=$now_timefmt
elif (($# == 1)); then arg=$1
else bomb "more than one argument disallowed"
fi
if [[ "$arg" =~ '[[:digit:]]{14}' ]]
then set_time_envs $arg
else bomb "time must be in $HISTTIMEFORMAT format"
fi
fi
test -d $custdir ||
bomb "no such customer"
mkdir -p $logbase/{starts,stops,tasks} ||
bomb "failed to make customer dirs"
declare -i startcount=$(ls -1 $logbase/starts | count)
declare -i stopcount=$(ls -1 $logbase/stops | count)
if ! ((skip_sanity_check))
then
((stopcount > startcount)) &&
bomb "impossible: more stops than starts"
(((startcount - stopcount) > 1)) &&
bomb "impossible: delta greater than one"
(((startcount - stopcount) < 0)) &&
bomb "impossible: delta less than zero"
fi
if (((startcount + stopcount) % 2))
then lastmode=start
else lastmode=stop
fi
lastdir=$logbase/${lastmode}s
lastfile=$(ls -1t $lastdir | head -1)
lastpath=$lastdir/$lastfile
[[ "$lastfile" ]] && lasttime=$(find $lastpath -printf ${HISTTIMEFORMAT//%/%T})
case $progname in
(stat*)
(($# == 0)) || bomb "no argument allowed"
echo_last
;;
(rmlast)
(($# == 0)) || bomb "no argument allowed"
rm $lastpath
;;
(rmstop|rmstart)
newer_than=/tmp/newer-$random
older_than=/tmp/older-$random
invocation=${progname#rm*}
(($# == 1)) || bomb "requires an argument"
touch -t $just_before_touchfmt $newer_than
touch -t $just_after_touchfmt $older_than
potential_matches=($(
for file in $(
find $logbase/${invocation}s/ \
-type f \
-newer $newer_than
); do
if test \
$file -nt $newer_than -a \
$file -ot $older_than
then
echo $file
fi
done
))
((${#potential_matches[@]} > 1)) &&
bomb "too many matches in removal"
((${#potential_matches[@]} == 0)) &&
bomb "no matches for removal"
rm $potential_matches
;;
(stop|start)
if [[ "$lastmode" == $progname ]] && ! ((skip_sanity_check))
then bomb "already $(echo_last)"
fi
setenv logdir $logbase/${progname}s
test -d $logdir ||
bomb "logdir is not a directory"
touch \
-t ${ttime_touchfmt:-$now_touchfmt} \
$logdir/$random
;;
(do)
XXX
(($# == 0)) && { ls -1t $taskdir | head -1; exit 0; }
what=$(IFS=_; echo "$*")
task_maxlen=63
((${#what} > $task_maxlen)) &&
bomb "task length ${#what} exceeds max $task_maxlen"
bash ~/bin/backup-tasks.sh || bomb "backup failed"
[[ $what == "mail" ]] && bomb "messaging, you fool!"
cd $taskdir || bomb "cannot change to task dir"
i=0
while true; do
if ! test -f $what.$i
then
if touch $what.$i
then exit 0
else bomb "error touching task whatfile"
fi
else
let i++
fi
done
;;
(*)
bomb "no such invocation name"
;;
esac