#! /bin/zsh -feu

# This is recursive. First time it invokes find(1)
# and the second time (invoked by find) it will invoke (correctly)
# the user's command.
# The key aim is to invoke the command in the "found" directory.

if getopt -T; then # should test (( $? = -4 ))
    echo "incompatible  getopt(1) installed. Abort"
    exit -1
fi


# note: must not be set in environment already!
# 0 parent
# 1 child with parameters
# 2       with more parameters
: ${FOR_EACH_DIR_CHILD=0}
export FOR_EACH_DIR_CHILD

usage()
{
    setopt POSIX_ARGZERO
    cat <<EOF
Usage $0 [-d] [-p] cmd ....

--debug  | -d  debug ... print the DIR before invoking the CMD.
--pass   | -p  pass the relative path as first argument.
--help   | -h
--wait   | -w  wait 3 seconds between
--exit-on-error | -e
EOF

# fixme:
    unsetopt POSIX_ARGZERO
}


## Executed in the parent:
if [ $FOR_EACH_DIR_CHILD = 0 ]
then
    # This is unused now.
    typeset -a print_args WAIT_AFTER args
    print_args=()
    WAIT_AFTER=()

    # default
    FOR_EACH_DIR_CHILD=2
    error_exit=n

    cmd_options=$(getopt --name $0 --shell bash \
        --longoptions pass,debug,help,wait,exit-on-error,verbose --options +edDhpw \
        -- "$@" ) || { usage && exit 1 }
    # note + -> first non-option is like --
    eval set -- "$cmd_options"

    while (( $# > 0 )) do
        case $1 in
            -p|--pass)
                FOR_EACH_DIR_CHILD=1
                ;;
            -d|--debug | -D| --verbose )
                # %h ?
                print_args=(-printf '\033[01;34m%h\033[0m\n')
                ;;
            -e)
                error_exit=y
                ;;
            --help|-h)
                usage
                exit 0
                ;;
            --wait| -w)
                # so not -e!
                WAIT_AFTER=(-exec sleep 3 \;)
                ;;
            --)
                shift
                break;
        esac
        shift
    done


    if [ $# = 0 ]; then
        usage; exit 1
    fi

    # continue:
    # -execdir $0 \{\} $args "$@" \;  $AFTER -prune
    # exit-on-error
    # \( -execdir $0 \{\} $args "$@" \; -o -quit \) $AFTER -prune

    typeset -a invoke_command
    invoke_command+=( -execdir $0 '{}' $args "$@" \; )
    if [[ $error_exit = y ]]; then
        invoke_command=(
                 '(' $invoke_command -o -printf 'Quit on error!\n' -quit ')' )
    fi

    set -x
    find . -name ".repo" -prune \
         -o \
         -type d -name .git $print_args \
         $WAIT_AFTER $invoke_command -prune
    # I have to wait before, since the command can fail, and the rest is not executed!

    # find -type d  -execdir test -d {}/.git \;  -print -exec pwd \;   -prune
    # is slower!
    # todo -execdir
else
    # return from the .git

    # back from from dir/.git into dir:
    # todo: if only there was a test for test -f .git

    # echo $1
    dir=${1%/.git}
    shift
    if [[ $dir != "." ]];
    then
        cd $dir
    fi

    if [[ $FOR_EACH_DIR_CHILD = 2 ]]; then
        eval $@[1] $@[2,-1]
    else
        # pass the relative path
        eval $@[1] $dir $@[2,-1]
    fi
fi
