#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
#
# Copyright 2024 Google LLC
#
# Author: Lee Jones <lee@kernel.org>
#
# Usage
#   voting_results [ v6.7.1..v6.7.2 ]
#
# * Conducts 3 way voting system between the present reviewers
#   - If reviewers change, future work will involve making this more generic
#
# Requires:
#  * Remember to change the user-specific variables a few lines down
#  * Expected to be executed from inside a kernel Git repository

# set -x                       # Uncomment to enable debugging

# -------   ACTION REQUIRED   -------
# Change these to suit your own setup
STABLEREMOTE=stable     # Whatever you called your Stable remote

print_red()
{
    if [[ -t 1 ]]; then
        echo -e "\e[01;31m$@\e[0m"
    else
	echo -e "$@"
    fi
}

print_blue()
{
    if [[ -t 1 ]]; then
        echo -e "\e[01;34m$@\e[0m"
    else
	echo -e "$@"
    fi
}

function print_annotations()
{
    oneline="${1}"
    sha="$(echo ${oneline} | cut -d' ' -f1)"

    for f in ${ANNOTATEDFILES}; do
        annotation=$(grep -A1 ${sha} ${PROPOSED}/${f} | tail -n1)
        if [ "${annotation}" != "" ]; then
            echo "  ${annotation}"
        fi
    done
}

while [ $# -gt 0 ]; do
    case $1 in
        *..*)
            RANGE=${1}
            ;;
        *)
            print_red "Unrecognised argument: ${1}"
            usage
            ;;
    esac
    shift
done

if [ "${RANGE}" == "" ]; then
    print_red "Please supply a Git range (e.g v6.7.1..v6.7.2)"
    exit
fi

if [ ! -e .git ] || [ ! -f MAINTAINERS ]; then
    print_red "Not in a kernel directory"
    exit 1
fi

print_blue "Fetching from ${STABLEREMOTE}"
git fetch ${STABLEREMOTE}

TOP=${RANGE#*..}
BOTTOM=${RANGE%..*}
SCRIPTDIR=$(dirname ${0})
PROPOSED=${SCRIPTDIR}/../cve/review/proposed
REVIEWFILES=$(ls ${PROPOSED} | grep -E "${TOP}-(lee|sasha|greg|ruiqi)$")
ANNOTATEDFILES=$(ls ${PROPOSED} | grep -E "${TOP}.*-annotated-(lee|sasha|greg|ruiqi)$")

CVE=()
ALL=()

GREGLEESASHA=()
GREGLEEGUEST=()
GREGSASHAGUEST=()
LEESASHAGUEST=()

GREGLEE=()
GREGSASHA=()
GREGGUEST=()
LEESASHA=()
LEEGUEST=()
SASHAGUEST=()

GREG=()
LEE=()
SASHA=()
GUEST=()

for stablesha in $(git log --format=%h ${BOTTOM}..${TOP}); do
    mainlinelongsha=$(git --no-pager log -n1 ${stablesha} | grep -i upstream | grep -oE "[a-f0-9]{40,}") || true

    # If the commit does not contain a Mainline SHA, we'll assume it's Stable only
    if [ "${mainlinesha}" == "" ]; then
        mainlinesha=${stablesha}
    fi

    oneline=$(git --no-pager log --format="%h %s" -n1 ${mainlinelongsha})
    subject=$(echo ${oneline} | cut -d' ' -f 2-)
    mainlinesha=$(echo ${oneline} | cut -d' ' -f 1)
    cve=0; greg=0; lee=0; sasha=0; guest=0; votes=0

    for f in ${REVIEWFILES}; do
        USER=${f#*-}

        if grep -qF "${subject}" ${PROPOSED}/${f}; then
            case ${USER} in
                greg)
                    greg=1
                    ;;
                lee)
                    lee=1
                    ;;
                sasha)
                    sasha=1
                    ;;
                ruiqi)
                    guest=1
                    ;;
                *)
                    echo "Unexpected user '${USER}' - exiting"
                    exit 1
            esac
            votes=$((votes + 1))
        fi
    done

    if [ ${votes} == 0 ]; then
        continue
    fi

    found=$(${SCRIPTDIR}/cve_search ${mainlinesha})
    found_result=$?
    if [ "${found_result}" == "0" ]; then
        cve=1
    fi

    if [ ${cve} == 1 ]; then
         CVE+=("${oneline}")
    elif [ ${greg} == 1 -a ${lee} == 1 -a ${sasha} == 1 -a ${guest} == 1 ]; then
        ALL+=("${oneline}")
    elif [ ${greg} == 1 -a ${lee} == 1 -a ${sasha} == 1 ]; then
        GREGLEESASHA+=("${oneline}")
    elif [ ${greg} == 1 -a ${lee} == 1 -a ${guest} == 1 ]; then
        GREGLEEGUEST+=("${oneline}")
    elif [ ${greg} == 1 -a ${sasha} == 1 -a ${guest} == 1 ]; then
        GREGSASHAGUEST+=("${oneline}")
    elif [ ${lee} == 1 -a ${sasha} == 1 -a ${guest} == 1 ]; then
        LEESASHAGUEST+=("${oneline}")
    elif [ ${greg} == 1 -a ${lee} == 1 ]; then
        GREGLEE+=("${oneline}")
    elif [ ${greg} == 1 -a ${sasha} == 1 ]; then
        GREGSASHA+=("${oneline}")
    elif [ ${greg} == 1 -a ${guest} == 1 ]; then
        GREGGUEST+=("${oneline}")
    elif [ ${lee} == 1 -a ${sasha} == 1 ]; then
        LEESASHA+=("${oneline}")
    elif [ ${lee} == 1 -a ${guest} == 1 ]; then
        LEEGUEST+=("${oneline}")
    elif [ ${sasha} == 1 -a ${guest} == 1 ]; then
        SASHAGUEST+=("${oneline}")
    elif [ ${greg} == 1 ]; then
        GREG+=("${oneline}")
    elif [ ${lee} == 1 ]; then
        LEE+=("${oneline}")
    elif [ ${sasha} == 1 ]; then
        SASHA+=("${oneline}")
    elif [ ${guest} == 1 ]; then
        GUEST+=("${oneline}")
    fi

    echo "${oneline}"
    echo -e "\tCVE:\t${cve}\tGreg:\t${greg}\tLee:\t${lee}\tSasha:\t${sasha}\tGuest:\t${guest}"
done

print_blue "\nAlready assigned a CVE"
for c in "${CVE[@]}"; do
    echo "  ${c}"
    print_annotations "${c}"
done

print_blue "\nEveryone agrees"
for c in "${ALL[@]}"; do
    echo "  ${c}"
    print_annotations "${c}"
done

print_blue "\nGreg, Lee and Sasha agree"
for c in "${GREGLEESASHA[@]}"; do
    echo "  ${c}"
    print_annotations "${c}"
done

print_blue "\nGreg and Lee agree"
for c in "${GREGLEE[@]}"; do
    echo "  ${c}"
    print_annotations "${c}"
done

print_blue "\nGreg and Sasha agree"
for c in "${GREGSASHA[@]}"; do
    echo "  ${c}"
    print_annotations "${c}"
done

print_blue "\nLee and Sasha agree"
for c in "${LEESASHA[@]}"; do
    echo "  ${c}"
    print_annotations "${c}"
done

print_blue "\nGreg, Lee and Guest agree"
for c in "${GREGLEEGUEST[@]}"; do
    echo "  ${c}"
    print_annotations "${c}"
done

print_blue "\nGreg, Sasha and Guest agree"
for c in "${GREGSASHAGUEST[@]}"; do
    echo "  ${c}"
    print_annotations "${c}"
done

print_blue "\nLee, Sasha and Guest agree"
for c in "${LEESASHAGUEST[@]}"; do
    echo "  ${c}"
    print_annotations "${c}"
done

print_blue "\nGreg only"
for c in "${GREG[@]}"; do
    echo "  ${c}"
    print_annotations "${c}"
done

print_blue "\nLee only"
for c in "${LEE[@]}"; do
    echo "  ${c}"
    print_annotations "${c}"
done

print_blue "\nSasha only"
for c in "${SASHA[@]}"; do
    echo "  ${c}"
    print_annotations "${c}"
done

print_blue "\n------------ GUEST RESULTS BELOW, use for re-review only at this time ----------------"

print_blue "\nGreg and Guest agree"
for c in "${GREGGUEST[@]}"; do
    echo "  ${c}"
    print_annotations "${c}"
done

print_blue "\nLee and Guest agree"
for c in "${LEEGUEST[@]}"; do
    echo "  ${c}"
    print_annotations "${c}"
done

print_blue "\nSasha and Guest agree"
for c in "${SASHAGUEST[@]}"; do
    echo "  ${c}"
    print_annotations "${c}"
done

print_blue "\nGuest only"
for c in "${GUEST[@]}"; do
    echo "  ${c}"
    print_annotations "${c}"
done
