#!/bin/sh

# warning: this is rawslop
# POSIX-compliant git pre-push hook to detect if a cherry-picked commit 
# has associated "Fixes:" commits on the main branch that are missing.

remote="$1"
url="$2"

# Define your primary development branch (change 'main' if needed)
MAIN_BRANCH="main"

# In POSIX sh, we read from stdin line by line using a standard while loop
while read local_ref local_sha remote_ref remote_sha; do

    # Skip branch deletions
    if [ "$local_sha" = "0000000000000000000000000000000000000000" ]; then
        continue
    fi

    # Determine commit range being pushed
    if [ "$remote_sha" = "0000000000000000000000000000000000000000" ]; then
        commit_range="$local_sha"
    else
        commit_range="$remote_sha..$local_sha"
    fi

    # Fetch latest remote state to ensure accurate history checks
    # Using 'sed' to safely strip 'refs/heads/' prefix for the local tracking path
    remote_branch_name=$(echo "$remote_ref" | sed 's|^refs/heads/||')
    target_branch_local="refs/remotes/$remote/$remote_branch_name"
    
    git fetch "$remote" "$remote_branch_name" >/dev/null 2>&1

    # Get all commits in the current push range
    commits=$(git rev-list "$commit_range")

    for commit in $commits; do
        # Extract original upstream hash from standard cherry-pick trailer
        # Uses POSIX grep and sed (avoiding -E and non-standard regex extensions)
        commit_body=$(git log -1 --format="%B" "$commit")
        upstream_hash=$(echo "$commit_body" | grep -i "cherry picked from commit" | sed 's/.*cherry picked from commit \([0-9a-fA-F]\{7,40\}\).*/\1/')

        if [ -n "$upstream_hash" ]; then
            # Grab just a short 7-char indicator for output readability
            short_upstream=$(echo "$upstream_hash" | cut -c1-7)
            echo "ℹ️  Found cherry-picked commit $commit (Original: $short_upstream)"

            # Ensure we have the latest main branch data to look for fixes
            git fetch "$remote" "$MAIN_BRANCH:$MAIN_BRANCH" >/dev/null 2>&1

            # Search main branch history for any commits containing "Fixes: <upstream_hash>"
            fixing_commits=$(git log "$MAIN_BRANCH" --grep="Fixes: $short_upstream" --format="%H")

            for fix_commit in $fixing_commits; do
                # Check if this fixing commit is already an ancestor of what we are pushing
                if ! git merge-base --is-ancestor "$fix_commit" "$local_sha" >/dev/null 2>&1; then
                    
                    # Double-check: Maybe the fix was also cherry-picked, changing its hash?
                    fix_already_cherry_picked=$(git log "$local_sha" --grep="cherry picked from commit $fix_commit" --format="%H")

                    if [ -z "$fix_already_cherry_picked" ]; then
                        fix_summary=$(git log -1 --oneline "$fix_commit")
                        
                        echo "------------------------------------------------------------------------"
                        echo "⚠️  [WARNING] Missing associated fix!"
                        echo "    - You are pushing cherry-picked commit: $short_upstream"
                        echo "    - On '$MAIN_BRANCH', there is a follow-up fix: $fix_commit"
                        echo "    - Fix details: $fix_summary"
                        echo "    - Status: This fix is MISSING from your target branch ($remote_ref)."
                        echo "    - Recommendation: You should probably cherry-pick $fix_commit as well."
                        echo "------------------------------------------------------------------------"
                    fi
                fi
            done
        fi
    done
done <&0 # Explicitly redirect stdin into the loop for strict POSIX safety

exit 0
