#!/bin/bash
# Copyright (C) 2026 taylor.fish <contact@taylor.fish>
#
# This file is part of ncc.
#
# ncc is free software: you can redistribute it and/or modify it under
# the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# ncc is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General
# Public License for more details.
#
# You should have received a copy of the GNU Affero General Public
# License along with ncc. If not, see <https://www.gnu.org/licenses/>.

# This script should be placed in ../.git/hooks, or core.hooksPath should be
# set to this directory. This script:
#
# * Makes sure that the next commit after a release bumps the version to a
#   `-dev` version.
# * Checks whether `make -C .misc` needs to be run to update the READMEs.
#
# If necessary, you can bypass the hook with `SKIP_HOOKS=1 git ...`.

set -eufo pipefail

if [ -n "${SKIP_HOOKS-}" ]; then
    printf >&2 '%s\n' "warning: skipping hooks"
    exit 0
fi

show() { # <file> <revision>
    if git show "${2-}:$1" 2> /dev/null; then
        return 0
    fi
    if [ -n "${2-}" ]; then
        printf >&2 '%s\n' "warning: $1 is not in $2"
    else
        printf >&2 '%s\n' "warning: $1 is not staged"
    fi
    return 1
}

get_toml_string() {
    grep "^$1"'\s*=' |
        sed -n "s/^$1"'\s*=\s*"\([^"]*\)"\s*$/\1/p' |
        head -n1
}

if ! name=$(show Cargo.toml | get_toml_string name); then
    printf >&2 '%s\n' "warning: could not determine package name"
    exit 0
fi

if ! version=$(show Cargo.toml | get_toml_string version); then
    printf >&2 '%s\n' "warning: could not determine package version"
    exit 0
fi

if ! prev_version=$(show Cargo.toml HEAD | get_toml_string version); then
    printf >&2 '%s\n' "warning: could not determine previous package version"
elif [ "$prev_version" = "$version" ]; then
    case "$version" in
        *-dev) ;;
        *)
            printf >&2 '%s\n' "error: package version should be bumped"
            exit 1
            ;;
    esac
fi

if ! lock_version=$(show Cargo.lock | grep -A1 '^name\s*=\s*'"\"$name\"" |
    get_toml_string version)
then
    printf >&2 '%s\n' "warning: could not determine version in Cargo.lock"
elif [ "$lock_version" != "$version" ]; then
    printf >&2 '%s\n' "error: Cargo.lock is out of date"
    exit 1
fi

check_readme() { # <file> [m4-arg...]
    local file="$1"
    shift
    local current
    current=$(show "$file")
    local newest
    newest=$(cd .misc && m4 -DVERSION="$version" "$@" README.m4)
    set +e
    diff -q <(printf '%s\n' "$current") <(printf '%s\n' "$newest") > /dev/null
    local status="$?"
    set -e
    case "$status" in
        0)
            return 0
            ;;
        1)
            printf >&2 '%s\n' "error: $file is not up to date"
            return 1
            ;;
        *)
            exit "$status"
            ;;
    esac
}

check_readme README.md
check_readme .misc/package-readme.md -DRUST
