#!/bin/sh

# part of even-more-utils, version 0.4

# run make as soon as needed

if [ "x$1" = 'x-r' ]; then
  mode='recursive'
  shift
elif [ "x$1" = 'x-g' ]; then
  mode='git'
  shift
else
  mode='Makefile'
fi

make "$@"

while true; do
  case ${mode} in
    'recursive')
      inotifywait -e DELETE_SELF,CLOSE_WRITE -r * || break
    ;;
    'git')
      inotifywait -e DELETE_SELF,CLOSE_WRITE $(git archive HEAD | tar -t | grep '[^/]$') || break
    ;;
    'Makefile')
      make_content=$(
        sed '
          :a
            \/\\$/ {
              N
              s/\\\n//
              ta
            }
          /^\(\s\|$\)/d
        ' 'Makefile' \
        | while read -r line; do
          if [ -z "${line##\$(foreach *,*,*)*}" ]; then
            line="${line#\$(foreach }"
            var="${line%%,*}"
            line="${line#${var}*,}"
            runs="${line%,*}"
            line="${line#${runs},}"
            body="${line%%)*}"
            line="${line#${body})}"
            while [ $(printf '%s\n' "${body}" | tr -d '\n' | tr ')' '\n' | wc -l) -lt $(printf '%s\n' "${body}" | tr -d '\n' | tr '(' '\n' | wc -l) ] \
            && [ -z "${line##*)*}" ]; do
              new_body="${line%%)*}"
              body="${body})${new_body}"
              line="${line#${new_body})}"
            done
            for s in ${runs}; do
              printf '%s' "${body}" \
              | sed '
                s#\$('"${var}"')#'"${s}"'#g
              '
            done \
            | sed '
              s/^\s\+//
              s/\s\+$//
            '
          fi
          printf '%s\n' "${line}"
        done
      )
      substs=$(
        printf '%s\n' "${make_content}" \
        | sed '
          s/^\([^[:space:]=]\+\)=\(.*\)$/s@\1@ \2 @g;\n/
          t
          d
        '
      )
      watch_files=$(
        printf '%s\n' "${make_content}" \
        | sed "${substs}" \
        | sed -n '
          s/^\S.*: //
          T
          y/ /\n/
          p
        ' \
        | sed '
          /^\s*$/d
          y/%/*/
        ' \
        | xargs -r readlink -f \
        | sort -u
      )
      inotifywait -e DELETE_SELF,CLOSE_WRITE $(find ${watch_files} -type f) || break
    ;;
    *)
      >& printf 'internal error: mode %s not implemented\n' "${mode}"
      exit 1
    ;;
  esac
  while make "$@"; do
    make -q "$@" && break
  done
done
