#!/bin/sh -e

usage() {
    echo "usage: $0 [options] [cmd...]
options:
    -h,--help                   Show this help
    -r,--retries=RETRIES        How many retries to do on command failure after
                                the initial try. Defaults to 3.
    -s,--sleep=SLEEP            How many seconds to sleep between retries.
                                Defaults to 3 seconds.
    -e,--exponential[=FACTOR]   Enable simple exponential back-off algorithm.
                                Disabled by default, factor defaults to 2
                                (binary exponential back-off).
    "
    exit "$1"
}

# parse arguments
opts=$(getopt \
    --options h,r:,s:,e:: \
    --longoptions help,retries:,sleep:,exponential:: \
    --name "$(basename "$0")" -- "$@") || usage 1
eval set -- "$opts"
while [ $# -gt 0 ]; do
  case "$1" in
    -h | --help        ) usage 0; shift ;;
    -r | --retries     ) retries=$2; shift 2 ;;
    -s | --sleep       ) sleep=$2; shift 2 ;;
    -e | --exponential ) exponential=${2:-2}; shift 2 ;;
    --                 ) shift; break ;;
    *                  ) break ;;
  esac
done

retries="${retries:-3}"
sleep="${sleep:-3}"

until "$@"; do
    [ "$retries" -gt 0 ] || break
    echo "Retrying up to $retries more times after sleeping ${sleep}s …" >&2
    retries=$((retries-1))
    sleep "$sleep"
    [ -n "$exponential" ] && sleep=$((sleep*exponential))
done
[ $retries -gt 0 ]
