#!/bin/bash
#
# Pre-commit hook: warn when committing generated files without their sources.
# This catches the common mistake of editing generated output instead of the
# real source (e.g., editing art_scan.cpp instead of art_scan.rl).
#
# Uses parallel arrays (not associative arrays) for bash 3.2 compatibility,
# since macOS still ships /bin/bash as 3.2.

# Generated file (index N) maps to source file at GENERATED_SRCS[N], and
# optionally to the build rule that produces it at GENERATED_RULES[N].
# Use "NEVER_EDIT" for third-party vendored files that should not be edited.
#
# The rule counts as a source (#1950).  Changing how a file is generated --
# a ragel flag, the #line strip -- legitimately rewrites the output while the
# .rl is untouched, and without this the hook rejects exactly the commits it
# should be happiest about.  Leave the entry empty where there is no single
# rule file.
GENERATED_GENS=(
    # Ragel scanners
    "mux/modules/engine/art_scan.cpp"
    "mux/modules/engine/ast_scan.cpp"
    "mux/lib/color_ops.c"
    "mux/lib/date_scan.cpp"
    "mux/muxescape/muxescape.cpp"

    # Unicode tables (source is the utf/ pipeline, not a single file)
    "mux/include/utf8tables.h"
    "mux/lib/utf8tables.cpp"
    "mux/include/unicode_tables_c.h"
    "mux/lib/unicode_tables.c"
    "mux/include/ducet_cetable.h"
    "mux/rv64/src/unicode_tables.c"

    # Autoconf
    "mux/configure"
    "mux/aclocal.m4"

    # Protocol Buffers
    "client/console/src/hydra.pb.h"
    "client/console/src/hydra.pb.cc"
    "client/console/src/hydra.grpc.pb.h"
    "client/console/src/hydra.grpc.pb.cc"
    "client/win32gui/src/hydra.pb.h"
    "client/win32gui/src/hydra.pb.cc"
    "client/win32gui/src/hydra.grpc.pb.h"
    "client/win32gui/src/hydra.grpc.pb.cc"
    "client/tf/src/proto/hydra.pb.h"
    "client/tf/src/proto/hydra.pb.cc"
    "client/tf/src/proto/hydra.grpc.pb.h"
    "client/tf/src/proto/hydra.grpc.pb.cc"

    # SQLite amalgamation (third-party)
    "mux/sqlite/sqlite3.c"
    "mux/sqlite/sqlite3.h"
)
GENERATED_SRCS=(
    "mux/modules/engine/art_scan.rl"
    "mux/modules/engine/ast_scan.rl"
    "mux/lib/color_ops.rl"
    "mux/lib/date_scan.rl"
    "mux/muxescape/muxescape.rl"

    "utf/"
    "utf/"
    "utf/"
    "utf/"
    "utf/"
    "utf/"

    "mux/configure.ac"
    "mux/configure.ac"

    "mux/proxy/hydra.proto"
    "mux/proxy/hydra.proto"
    "mux/proxy/hydra.proto"
    "mux/proxy/hydra.proto"
    "mux/proxy/hydra.proto"
    "mux/proxy/hydra.proto"
    "mux/proxy/hydra.proto"
    "mux/proxy/hydra.proto"
    "mux/proxy/hydra.proto"
    "mux/proxy/hydra.proto"
    "mux/proxy/hydra.proto"
    "mux/proxy/hydra.proto"

    "NEVER_EDIT"
    "NEVER_EDIT"
)
# Build rule that generates GENERATED_GENS[N], where there is a single one.
# Same index; "" means none, and the source check stands alone.
GENERATED_RULES=(
    "mux/modules/engine/Makefile.am"
    "mux/modules/engine/Makefile.am"
    "mux/lib/Makefile.am"
    "mux/lib/Makefile.am"
    "mux/muxescape/Makefile.am"

    "" "" "" "" "" ""

    "" ""

    "" "" "" "" "" "" "" "" "" "" "" ""

    "" ""
)

staged=$(git diff --cached --name-only)
warnings=""

for i in "${!GENERATED_GENS[@]}"; do
    gen="${GENERATED_GENS[$i]}"
    src="${GENERATED_SRCS[$i]}"
    if echo "$staged" | grep -qx "$gen"; then
        if [ "$src" = "NEVER_EDIT" ]; then
            # Third-party vendored file — should never be hand-edited
            warnings="${warnings}  ${gen}  (third-party vendored file — replace, don't edit)\n"
        elif ! echo "$staged" | grep -q "^${src}"; then
            # Source is not staged.  The build rule counts too: a change to
            # how the file is generated rewrites the output without touching
            # the source, and that is a legitimate commit (#1950).
            rule="${GENERATED_RULES[$i]}"
            if [ -z "$rule" ] || ! echo "$staged" | grep -qx "$rule"; then
                warnings="${warnings}  ${gen}  (source: ${src})\n"
            fi
        fi
    fi
done

if [ -n "$warnings" ]; then
    echo ""
    echo "WARNING: Generated file(s) staged WITHOUT their source:"
    echo ""
    printf "$warnings"
    echo ""
    echo "Did you edit a generated file by mistake?"
    echo "Edit the source and regenerate instead."
    echo ""
    echo "To commit anyway:  git commit --no-verify"
    exit 1
fi
