#!/usr/bin/env bash
#
# O deploy do teste recusa ligar o vhost sem a senha HTTP escolhida (D451), e o
# public/app.json mudado pela tela nao trava mais o deploy seguinte (D549)?
#
#     bash scripts/ensaiar-escolhas-do-deploy-teste.sh
#     bash scripts/ensaiar-escolhas-do-deploy-teste.sh <copia do scripts/deploy-teste.sh>
#
# Sai com 0 quando todo caso abaixo da a saida esperada; 1 quando algum nao da, e
# diz qual; 2 quando nao consegue medir (falta git, mktemp ou python3, ou as
# funcoes nao estao onde deviam) -- e so se nada falhou antes: um defeito ja
# achado sai com 1. O argumento aponta o ensaio para uma COPIA do roteiro -- e
# como se falsifica sem tocar no de verdade.
#
# ---------------------------------------------------------------------------
# POR QUE ISTO EXISTE (08/11/2026, a fatia 129, DEPLOY-TESTE-E-PUBLICAR)
#
# D451: sem a linha SENHA_HTTP no .env, o `conferir_env` punha `nao` na memoria,
# e o `publicar`, o `atualizar` e o `voltar` ligavam o vhost ABERTO -- a escolha
# do dono desde 02/10/2026 e a senha (D326). Agora nao ha padrao: sem a escolha,
# os quatro que ligam (o _aplicar tambem) recusam logo depois do conferir_env, e
# o instalar_vhost, o ponto por onde os tres passam, recusa de novo.
#
# D549: as conferencias de "mudanca versionada" (o atualizar, o voltar e a do
# composer no subir_e_ajustar) recusavam o public/app.json, que a tela da
# versao do aplicativo grava no clone. Agora ignoram so ele; e o atualizar e o
# voltar recusam ANTES de tirar o site quando o alvo tambem muda o arquivo (o
# merge e o checkout parariam nele, com o site ja fora).
#
# ---------------------------------------------------------------------------
# COMO
#
# A. O ROTEIRO INTEIRO, num clone de mentira (um repositorio git temporario com
#    o roteiro, um docker-compose.teste.yml vazio e um .env do teste), com
#    dubles no comeco do PATH: `docker`, `sudo`, `nginx`, `systemctl`,
#    `hostname`, `realpath` e `curl` so anotam o pedido num registro e
#    respondem o minimo;
#    o git e o de verdade. A trava do servidor fica de fora
#    (DEPLOY_TESTE_TRAVADO=1): quem a prova e o ensaiar-trava-do-deploy-teste.sh.
#    Os casos, sem a linha SENHA_HTTP no .env e sem a variavel:
#
#      publicar                          sai 1 com a recusa e os dois comandos
#                                        (o htpasswd e o SENHA_HTTP=sim), e o
#                                        freio armado roda (o tirar_do_ar
#                                        desliga o vhost deste dominio)
#      atualizar, o site fora SEM a      sai 1 com a recusa, o HEAD parado
#      marca do tirar (o .deploy-teste/
#      de um publicar, sem o `tirado`)
#      voltar <commit>                   sai 1 com a recusa, o HEAD parado
#      _aplicar <HEAD>                   sai 1 com a recusa
#
#    em nenhum o registro tem o vhost instalado (`install -m 644`), o link em
#    sites-enabled (`ln -sf`), o nginx da pilha subindo (`up`) ou o `docker
#    compose config` do passo seguinte (a recusa que imprime e segue chega a
#    ele), e o .env segue sem a linha. E os controles: com SENHA_HTTP=sim no
#    .env, ou na linha de comando, os quatro passam da recusa e param no passo
#    seguinte (o conferir_compose, com o `{}` do duble, e o compose config no
#    registro) -- a recusa e a da escolha.
#
#    O QUE A PARTE A NAO PERCORRE: o caminho atualizar -> _aplicar -> por_no_ar
#    -> instalar_vhost. Sem a escolha, a recusa vem na entrada, antes de tudo; e
#    o instalar_vhost, o ponto por onde os tres passam, recusa sozinho (a parte
#    B) -- a segunda linha, para um caminho que nao passe pela entrada.
#
# B. O instalar_vhost, tirado inteiro do roteiro com o exigir_a_escolha_da_senha,
#    sobre o docker/nginx/teste-host.conf.modelo de verdade, com o ativar_vhost
#    de mentira (guarda o vhost gerado): vazio recusa sem ativar; `nao` ativa
#    sem auth_basic; `sim` com o htpasswd ativa com auth_basic; `sim` sem o
#    htpasswd recusa.
#
# C. O conferir_publico, tirado inteiro, com as sondas de mentira (403 nas
#    negadas, 200 no / e no /novo/): o site no ar sem senha e sem a linha
#    reprova; com SENHA_HTTP=nao passa.
#
# D. O app.json, num repositorio git temporario com tres commits (o B nao toca
#    o arquivo, o C toca): a mudancas_versionadas ignora so o public/app.json
#    (mudado ou no indice), e acusa o resto; a
#    recusar_se_o_alvo_toca_o_app_json deixa o B (e o merge --ff-only leva a
#    mudanca local junto) e recusa o C (o merge, sem ela, para no arquivo).
#
# E. A ORDEM, lida no roteiro sem os comentarios: no cmd_atualizar e no
#    cmd_voltar a recusa do app.json vem antes do primeiro tirar_do_ar;
#    nenhum `git status --porcelain` fica fora da mudancas_versionadas; e
#    nenhuma frase manda o `publicar` curto (sem o SENHA_HTTP) fora do
#    comando_de_publicar -- o fim do `base` tambem.
#
# O QUE ELE NAO AFIRMA: nada do BVIP. O nginx, o certbot e o docker sao dubles;
# que o vhost gerado passe no `nginx -t` de verdade e o
# ensaiar-build-do-publicar.sh (fora do corredor: pede docker e rede).

set -u

cd "$(dirname "$0")/.." || exit 2
RAIZ=$(pwd)

DEPLOY="${1:-scripts/deploy-teste.sh}"
case "$DEPLOY" in /*) ;; *) DEPLOY="$RAIZ/$DEPLOY" ;; esac
[ -r "$DEPLOY" ] || { echo "NAO CONSEGUI MEDIR: nao li $DEPLOY" >&2; exit 2; }
for c in git mktemp python3 sed grep; do
    command -v "$c" >/dev/null 2>&1 || { echo "NAO CONSEGUI MEDIR: falta o $c" >&2; exit 2; }
done
[ -r "$RAIZ/docker/nginx/teste-host.conf.modelo" ] || { echo "NAO CONSEGUI MEDIR: sem o docker/nginx/teste-host.conf.modelo" >&2; exit 2; }

T=$(mktemp -d 2>/dev/null) || { echo "NAO CONSEGUI MEDIR: mktemp -d falhou" >&2; exit 2; }
trap 'rm -rf "$T"' EXIT INT TERM

falhas=0
casos=0
# UM DEFEITO JA ACHADO VALE MAIS que a medida que faltou: sai 1, e nao 2.
nao_medi() { echo "NAO CONSEGUI MEDIR: $1" >&2; [ "$falhas" -eq 0 ] || exit 1; exit 2; }
falhou() { echo "  - $1"; falhas=$((falhas + 1)); }
caso() { casos=$((casos + 1)); }

# Uma funcao inteira do roteiro: da linha `nome() {` a primeira `}` sozinha.
extrair() {
    awk -v nome="$1" '
        $0 == nome "() {" { dentro = 1 }
        dentro { print }
        dentro && $0 == "}" { achou = 1; exit }
        END { if (!achou) exit 1 }
    ' "$DEPLOY"
}

# O roteiro sem os comentarios (o `#` no comeco da linha, depois de espacos).
SEM_COMENTARIO="$T/sem-comentario.sh"
grep -vE '^[[:space:]]*#' "$DEPLOY" > "$SEM_COMENTARIO"

export GIT_AUTHOR_NAME=ensaio GIT_AUTHOR_EMAIL=ensaio@exemplo.test GIT_COMMITTER_NAME=ensaio GIT_COMMITTER_EMAIL=ensaio@exemplo.test
export GIT_CONFIG_NOSYSTEM=1 HOME="$T/home"
mkdir -p "$HOME"
git config --global init.defaultBranch main 2>/dev/null
git config --global advice.detachedHead false 2>/dev/null

# ---------------------------------------------------------------------------
# A. O roteiro inteiro, com dubles.

BIN="$T/bin"
mkdir -p "$BIN"
REG="$T/registro.txt"
for d in docker nginx systemctl curl certbot; do
    cat > "$BIN/$d" <<'FIM'
#!/usr/bin/env bash
printf '%s %s\n' "$(basename "$0")" "$*" >> "$ENSAIO_REGISTRO"
case "$(basename "$0") $1 $2" in
    "docker compose version") echo "Docker Compose version v2.ensaio"; exit 0 ;;
    "docker compose config") echo '{}'; exit 0 ;;
    "nginx -v"*) echo "nginx version: nginx/1.24.0" >&2; exit 0 ;;
    "curl "*) exit 7 ;;
esac
exit 0
FIM
    chmod +x "$BIN/$d"
done
cat > "$BIN/sudo" <<'FIM'
#!/usr/bin/env bash
case "${1:-}" in -v) exit 0 ;; -n) shift ;; esac
printf 'sudo %s\n' "$*" >> "$ENSAIO_REGISTRO"
exec "$@"
FIM
cat > "$BIN/hostname" <<'FIM'
#!/usr/bin/env bash
echo bvip-ensaio
FIM
# O realpath DEVOLVE O CAMINHO COMO VEIO: no Mac, o /var e um link para o
# /private/var, e a guarda da FRONT_RAIZ (que nao e o assunto daqui) reprovava
# /var/www/<dominio>/front antes de qualquer caso.
cat > "$BIN/realpath" <<'FIM'
#!/usr/bin/env bash
printf '%s\n' "${!#}"
FIM
chmod +x "$BIN/sudo" "$BIN/hostname" "$BIN/realpath"

# O clone de mentira, com dois commits (o voltar precisa de um alvo).
CLONE="$T/clone"
montar_clone() {
    rm -rf "$CLONE"
    mkdir -p "$CLONE/scripts" "$CLONE/docker/nginx"
    cp "$DEPLOY" "$CLONE/scripts/deploy-teste.sh"
    cp "$RAIZ/docker/nginx/teste-host.conf.modelo" "$CLONE/docker/nginx/"
    : > "$CLONE/docker-compose.teste.yml"
    printf '.env\n.deploy-teste/\n' > "$CLONE/.gitignore"
    (
        cd "$CLONE" || exit 1
        git init -q . && git add -A && git commit -qm um && echo dois > dois.txt && git add dois.txt && git commit -qm dois
    ) >/dev/null 2>&1 || nao_medi "nao montei o clone de mentira"
    {
        echo 'COMPOSE_PROJECT_NAME=franquiabv-teste'
        echo 'COMPOSE_FILE=docker-compose.yml:docker-compose.homologacao.yml:docker-compose.teste.yml'
        echo 'DB_NAME=franquiabv_teste'
        echo 'APP_PORT=127.0.0.1:8090'
        echo 'DOMINIO_TESTE=sistema.exemplo.test'
        [ -z "${1:-}" ] || echo "SENHA_HTTP=$1"
    } > "$CLONE/.env"
}

# rodar <saida> <variavel SENHA_HTTP da linha de comando, ou -> <subcomando...>
rodar() {
    local saida="$1" senha="$2"
    shift 2
    : > "$REG"
    (
        cd "$CLONE" || exit 2
        if [ "$senha" = - ]; then unset SENHA_HTTP; else export SENHA_HTTP="$senha"; fi
        unset DOMINIO RAMO FRONT_RAIZ EMAIL_CERTBOT CONFIRMAR DEPLOY_TESTE_RAIZ DEPLOY_TESTE_COPIA
        PATH="$BIN:$PATH" ENSAIO_REGISTRO="$REG" DEPLOY_TESTE_TRAVADO=1 CONFIRMAR=sim \
            timeout 60 bash scripts/deploy-teste.sh "$@"
    ) > "$saida" 2>&1
}

RECUSA='a senha HTTP não foi escolhida'
ligou() { grep -qE '(^| )(ln -sf|install -m 644)|compose .*up ' "$REG"; }
# O PASSO SEGUINTE A RECUSA, o conferir_compose, pede o `docker compose config`:
# a recusa que imprime e segue (um `( exigir... ) || true`) chega a ele.
chegou_ao_compose() { grep -q '^docker compose config' "$REG"; }

for sub in publicar atualizar voltar _aplicar; do
    caso
    montar_clone
    antes=$(git -C "$CLONE" rev-parse HEAD)
    case "$sub" in
        voltar) args=(voltar "$(git -C "$CLONE" rev-parse HEAD~1)") ;;
        _aplicar) args=(_aplicar "$antes") ;;
        *) args=("$sub") ;;
    esac
    # O ATUALIZAR COM O SITE FORA SEM A MARCA DO `tirar`: o estado do deploy
    # existe (um publicar de antes), o site esta fora (nada ligado) e nao ha a
    # marca -- o caso em que o _aplicar religava pelo por_no_ar com o padrao.
    if [ "$sub" = atualizar ]; then
        mkdir -p "$CLONE/.deploy-teste" && echo "$antes publicado" > "$CLONE/.deploy-teste/historico"
    fi
    rodar "$T/saida-$sub.txt" - "${args[@]}"
    codigo=$?
    [ "$codigo" = 1 ] || falhou "$sub sem a escolha: saiu $codigo, e devia sair 1 ($(tail -n 1 "$T/saida-$sub.txt"))"
    grep -qF "$RECUSA" "$T/saida-$sub.txt" || falhou "$sub sem a escolha: a saida nao diz '$RECUSA' ($(grep ABORTADO "$T/saida-$sub.txt" | head -n 1))"
    grep -qF 'sudo htpasswd -c /etc/nginx/.htpasswd-sistema.exemplo.test' "$T/saida-$sub.txt" \
        && grep -qF 'SENHA_HTTP=sim bash scripts/deploy-teste.sh publicar' "$T/saida-$sub.txt" \
        || falhou "$sub sem a escolha: a recusa nao diz os dois comandos (o htpasswd e o SENHA_HTTP=sim)"
    ! ligou || falhou "$sub sem a escolha: o vhost ou o nginx da pilha foi ligado ($(grep -E 'ln -sf|install -m 644|up ' "$REG" | head -n 1))"
    ! grep -q '^SENHA_HTTP' "$CLONE/.env" || falhou "$sub sem a escolha: o .env ganhou a linha SENHA_HTTP sem ninguem escolher"
    [ "$(git -C "$CLONE" rev-parse HEAD)" = "$antes" ] || falhou "$sub sem a escolha: o codigo trocou (o HEAD andou)"
    [ ! -f "$CLONE/.deploy-teste/tirado" ] || falhou "$sub sem a escolha: gravou a marca do tirar"
    # RECUSOU ANTES DE MEXER, medido pelo efeito: nao chegou ao passo seguinte.
    ! chegou_ao_compose || falhou "$sub sem a escolha: passou da recusa e chegou ao conferir_compose (a recusa imprimiu e seguiu)"
    # NO publicar, A RECUSA VEM COM O FREIO ARMADO: o tirar_do_ar rodou (o
    # vhost deste dominio desligado), e um site no ar sem a escolha sai do ar.
    if [ "$sub" = publicar ]; then
        grep -qF 'o passo não chegou ao fim; tirar_do_ar' "$T/saida-$sub.txt" \
            && grep -q 'rm -f /etc/nginx/sites-enabled/sistema.exemplo.test.conf' "$REG" \
            || falhou "publicar sem a escolha: o freio (tirar_do_ar) nao rodou na recusa"
    fi

    # OS CONTROLES: a escolha no .env, e na linha de comando.
    for controle in env linha; do
        caso
        if [ "$controle" = env ]; then montar_clone sim; senha=-; else montar_clone; senha=sim; fi
        antes=$(git -C "$CLONE" rev-parse HEAD)
        case "$sub" in
            voltar) args=(voltar "$(git -C "$CLONE" rev-parse HEAD~1)") ;;
            _aplicar) args=(_aplicar "$antes") ;;
            *) args=("$sub") ;;
        esac
        rodar "$T/controle-$sub-$controle.txt" "$senha" "${args[@]}"
        ! grep -qF "$RECUSA" "$T/controle-$sub-$controle.txt" \
            || falhou "$sub com SENHA_HTTP=sim ($controle): recusou pela escolha"
        # O PASSO SEGUINTE: o conferir_compose, que le o `{}` do duble.
        grep -qF "o compose não sobe o projeto" "$T/controle-$sub-$controle.txt" \
            || falhou "$sub com SENHA_HTTP=sim ($controle): esperava parar no passo seguinte, o conferir_compose ($(grep ABORTADO "$T/controle-$sub-$controle.txt" | head -n 1))"
        # A REGUA DA RECUSA MEDE: com a escolha, o registro tem o compose config.
        chegou_ao_compose || falhou "$sub com SENHA_HTTP=sim ($controle): o registro nao tem o docker compose config (a regua do 'nao chegou ao compose' nao mede)"
    done
done

# ---------------------------------------------------------------------------
# B. O instalar_vhost, com a escolha.

extrair exigir_a_escolha_da_senha > "$T/exigir.sh" || nao_medi "nao achei o exigir_a_escolha_da_senha em $DEPLOY"
extrair instalar_vhost > "$T/instalar.sh" || nao_medi "nao achei o instalar_vhost em $DEPLOY"
grep -q 'ativar_vhost' "$T/instalar.sh" || nao_medi "o instalar_vhost nao chama mais o ativar_vhost: o duble nao sabe medir"
{
    echo 'set -euo pipefail'
    cat <<'FIM'
falhar() { printf 'ABORTADO: %s\n' "$*" >&2; exit 1; }
DOMINIO=sistema.exemplo.test
PORTA_APP=8090
FRONT_RAIZ=/var/www/sistema.exemplo.test/front
HTPASSWD=/etc/nginx/.htpasswd-sistema.exemplo.test
VHOST_LIGADO=/etc/nginx/sites-enabled/sistema.exemplo.test.conf
sudo() {
    case "$1" in
        grep) return 1 ;;
        nginx) echo "nginx version: nginx/1.24.0" >&2; return 0 ;;
        test) [ "${ENSAIO_COM_HTPASSWD:-nao}" = sim ]; return ;;
    esac
    return 0
}
ativar_vhost() { cp "$1" "$ENSAIO_VHOST"; echo ATIVADO; }
FIM
    cat "$T/exigir.sh" "$T/instalar.sh"
    echo 'instalar_vhost'
} > "$T/rodar-instalar.sh"

# vhost <rotulo> <SENHA_HTTP> <com htpasswd> <saida esperada> <com auth_basic: sim|nao|->
vhost() {
    caso
    rm -f "$T/vhost.conf"
    (cd "$CLONE" && SENHA_HTTP="$2" ENSAIO_COM_HTPASSWD="$3" ENSAIO_VHOST="$T/vhost.conf" \
        bash -c 'SENHA_HTTP="$SENHA_HTTP"; . "$0"' "$T/rodar-instalar.sh") > "$T/saida-vhost.txt" 2>&1
    local codigo=$?
    [ "$codigo" = "$4" ] || { falhou "instalar_vhost, $1: saiu $codigo, e devia sair $4 ($(tail -n 1 "$T/saida-vhost.txt"))"; return; }
    case "$5" in
        -) [ ! -f "$T/vhost.conf" ] || falhou "instalar_vhost, $1: ativou o vhost" ;;
        sim) grep -qE '^[[:space:]]*auth_basic[[:space:]]' "$T/vhost.conf" || falhou "instalar_vhost, $1: o vhost nao pede senha" ;;
        nao) [ -f "$T/vhost.conf" ] && ! grep -qE '^[[:space:]]*auth_basic[[:space:]]' "$T/vhost.conf" || falhou "instalar_vhost, $1: o vhost pede senha, ou nao foi ativado" ;;
    esac
}
montar_clone
vhost 'sem a escolha' '' nao 1 -
grep -qF "$RECUSA" "$T/saida-vhost.txt" || falhou "instalar_vhost, sem a escolha: a saida nao diz '$RECUSA'"
vhost 'SENHA_HTTP=nao' nao nao 0 nao
grep -qF 'D326' "$T/vhost.conf" 2>/dev/null || falhou "instalar_vhost, SENHA_HTTP=nao: o comentario do vhost gerado nao cita a escolha do dono de 02/10 (D326)"
! grep -qF '24/09/2026' "$T/vhost.conf" 2>/dev/null || falhou "instalar_vhost, SENHA_HTTP=nao: o vhost gerado ainda da o sem-senha como escolha do dono de 24/09"
vhost 'SENHA_HTTP=sim com o htpasswd' sim sim 0 sim
vhost 'SENHA_HTTP=sim sem o htpasswd' sim nao 1 -

# ---------------------------------------------------------------------------
# C. O conferir_publico, com o site no ar sem senha.

extrair conferir_publico > "$T/publico.sh" || nao_medi "nao achei o conferir_publico em $DEPLOY"
extrair comando_de_publicar > "$T/comando.sh" || nao_medi "nao achei o comando_de_publicar em $DEPLOY"
extrair do_env > "$T/do_env.sh" || nao_medi "nao achei o do_env em $DEPLOY"
{
    echo 'set -euo pipefail'
    cat <<'FIM'
falhar() { printf 'ABORTADO: %s\n' "$*" >&2; exit 1; }
ok() { printf '    ok  %s\n' "$*"; }
DOMINIO=sistema.exemplo.test
HTPASSWD=/etc/nginx/.htpasswd-sistema.exemplo.test
sudo() { return 0; }
com_senha_http() { return 1; }
codigo() { case "$1" in /|/novo/assets/*) echo 200 ;; *) echo 403 ;; esac; }
cabecalhos() { printf 'x-robots-tag: noindex\nstrict-transport-security: max-age=1\n'; }
curl() { printf '<script src="/novo/assets/index-ensaio.js"></script>'; }
FIM
    cat "$T/do_env.sh" "$T/comando.sh" "$T/publico.sh"
    echo 'conferir_publico'
} > "$T/rodar-publico.sh"
publico() {
    caso
    (cd "$CLONE" && bash -c 'SENHA_HTTP="$1"; . "$0"' "$T/rodar-publico.sh" "$2") > "$T/saida-publico.txt" 2>&1
    local codigo=$?
    [ "$codigo" = "$3" ] || falhou "conferir_publico, $1: saiu $codigo, e devia sair $3 ($(tail -n 1 "$T/saida-publico.txt"))"
}
montar_clone
publico 'no ar sem senha e sem a linha' '' 1
grep -qF 'pelo padrão de antes' "$T/saida-publico.txt" || falhou "conferir_publico, sem a linha: a saida nao diz que o site veio do padrao de antes"
publico 'no ar sem senha, SENHA_HTTP=nao escolhido' nao 0

# ---------------------------------------------------------------------------
# D. O app.json num repositorio de verdade.

extrair mudancas_versionadas > "$T/mudancas.sh" || nao_medi "nao achei a mudancas_versionadas em $DEPLOY"
extrair recusar_se_o_alvo_toca_o_app_json > "$T/recusar.sh" || nao_medi "nao achei a recusar_se_o_alvo_toca_o_app_json em $DEPLOY"
{
    echo 'set -euo pipefail'
    echo 'falhar() { printf '"'"'ABORTADO: %s\n'"'"' "$*" >&2; exit 1; }'
    cat "$T/mudancas.sh" "$T/recusar.sh"
    echo '"$@"'
} > "$T/rodar-app-json.sh"
R="$T/repo"
mkdir -p "$R/public" "$R/module"
(
    cd "$R" || exit 1
    git init -q . && printf '[{"push":"inativo","versao_major":"2","versao_minor":"0","versao_patch":"8"}]' > public/app.json \
        && echo um > module/a.php && git add -A && git commit -qm A \
        && echo dois > module/a.php && git commit -qam B && git tag B \
        && printf '[{"push":"ativo","versao_major":"2","versao_minor":"1","versao_patch":"0"}]' > public/app.json && git commit -qam C && git tag C \
        && git checkout -q -b servidor HEAD~2
) >/dev/null 2>&1 || nao_medi "nao montei o repositorio do app.json"
app() { (cd "$R" && bash "$T/rodar-app-json.sh" "$@"); }
TELA='[{"push":"inativo","versao_major":"2","versao_minor":"0","versao_patch":"9"}]'

caso; [ -z "$(app mudancas_versionadas)" ] || falhou "app.json: o clone limpo acusou mudanca"
printf '%s' "$TELA" > "$R/public/app.json"
caso; [ -z "$(app mudancas_versionadas)" ] || falhou "app.json: o public/app.json mudado pela tela foi acusado ($(app mudancas_versionadas))"
(cd "$R" && git add public/app.json)
caso; [ -z "$(app mudancas_versionadas)" ] || falhou "app.json: o public/app.json no indice foi acusado"
(cd "$R" && git reset -q public/app.json)
echo editado > "$R/module/a.php"
caso; app mudancas_versionadas | grep -q 'module/a.php' || falhou "app.json: o module/a.php mudado nao foi acusado (o servidor nao e lugar de editar)"
(cd "$R" && git checkout -q -- module/a.php)

caso; app recusar_se_o_alvo_toca_o_app_json B > "$T/saida-app.txt" 2>&1 || falhou "app.json: o alvo B nao toca o arquivo, e recusou ($(tail -n 1 "$T/saida-app.txt"))"
caso; app recusar_se_o_alvo_toca_o_app_json C > "$T/saida-app.txt" 2>&1 && falhou "app.json: o alvo C muda o arquivo, e nao recusou"
grep -qF 'git checkout -- public/app.json' "$T/saida-app.txt" || falhou "app.json: a recusa do C nao diz como devolver o arquivo"
# O PORQUE DA RECUSA: sem ela, o merge do C para no arquivo; o do B leva a mudanca junto.
caso; (cd "$R" && git merge -q --ff-only C) >/dev/null 2>&1 && falhou "app.json: o merge do C passou com o arquivo mudado (o ensaio nao reproduz o defeito)"
caso; (cd "$R" && git merge -q --ff-only B) >/dev/null 2>&1 || falhou "app.json: o merge do B parou com o arquivo mudado"
[ "$(cat "$R/public/app.json")" = "$TELA" ] || falhou "app.json: o merge do B nao levou a versao da tela"
(cd "$R" && git checkout -q -- public/app.json)
caso; app recusar_se_o_alvo_toca_o_app_json C > "$T/saida-app.txt" 2>&1 || falhou "app.json: sem mudanca local, o alvo C recusou ($(tail -n 1 "$T/saida-app.txt"))"

# ---------------------------------------------------------------------------
# E. A ordem, no roteiro sem comentarios.

corpo() {
    awk -v nome="$1" '
        $0 == nome "() {" { dentro = 1 }
        dentro { print NR ": " $0 }
        dentro && $0 == "}" { exit }
    ' "$SEM_COMENTARIO"
}
for f in cmd_atualizar cmd_voltar; do
    caso
    c=$(corpo "$f")
    r=$(printf '%s\n' "$c" | grep -m1 'recusar_se_o_alvo_toca_o_app_json' | cut -d: -f1)
    t=$(printf '%s\n' "$c" | grep -m1 'tirar_do_ar' | cut -d: -f1)
    [ -n "$t" ] || nao_medi "nao achei o tirar_do_ar no $f"
    [ -n "$r" ] && [ "$r" -lt "$t" ] || falhou "$f: a recusa do app.json nao vem antes do tirar_do_ar"
done
caso
fora=$(grep -n 'git status --porcelain' "$SEM_COMENTARIO" | grep -v ':(exclude)public/app.json' || true)
[ -z "$fora" ] || falhou "ha 'git status --porcelain' fora da mudancas_versionadas: $fora"
# NENHUMA FRASE MANDA O publicar CURTO sem a escolha (o D451; o fim do base
# tambem): toda linha que o cita traz o SENHA_HTTP, ou e o comando_de_publicar.
caso
curto=$(grep -n 'deploy-teste.sh publicar' "$SEM_COMENTARIO" | grep -v 'SENHA_HTTP' \
    | grep -vF "printf 'bash scripts/deploy-teste.sh publicar'" || true)
[ -z "$curto" ] || falhou "ha frase que manda o publicar curto fora do comando_de_publicar: $curto"

if [ "$falhas" -gt 0 ]; then
    echo "O DEPLOY DO TESTE NAO SEGURA A ESCOLHA DA SENHA OU O APP.JSON ($DEPLOY): $falhas falha(s) em $casos caso(s)"
    exit 1
fi
echo "ok: os $casos casos -- sem a senha escolhida, o publicar, o atualizar, o voltar, o _aplicar e o instalar_vhost recusam; o conferir reprova o site aberto sem escolha; o public/app.json da tela nao trava o deploy, e o alvo que o muda e recusado antes do freio"
exit 0
