#!/bin/bash
#
# A script to check the versions of bundled dependencies in an RPM spec file.
#
# It looks for a specific pattern in the raw spec file:
#   # See: path/to/version/file
#   Provides: bundled(dependency) = 1.2.3
#
# It then reads the first line of 'path/to/version/file' and ensures
# it exactly matches the literal version '1.2.3' declared in the spec.
#
# It dynamically locates the source directory by using `spectool` to find
# the name of the main source archive.
#
# This script automatically finds the single .spec file in the current directory.
#
# Exits with status 0 on success, 1 on failure.

set -euo pipefail

# --- Main Script ---

# Find the .spec file in the current directory.
spec_files=(*.spec)

# Check how many .spec files were found.
if [[ ${#spec_files[@]} -eq 0 ]]; then
    echo "Error: No .spec file found in the current directory." >&2
    exit 1
elif [[ ${#spec_files[@]} -gt 1 ]]; then
    echo "Error: Multiple .spec files found. Please run this script in a directory with only one .spec file." >&2
    printf "Found files:\n" >&2
    printf " - %s\n" "${spec_files[@]}" >&2
    exit 1
fi

# We have exactly one spec file.
SPEC_FILE="${spec_files[0]}"
FULL_SPEC_PATH=$(realpath "$SPEC_FILE")

if [[ ! -f "$FULL_SPEC_PATH" ]]; then
    # This check is somewhat redundant with realpath but good for clarity
    echo "Error: Spec file not found at '$SPEC_FILE'" >&2
    exit 1
fi

# Check for spectool dependency
if ! command -v spectool &> /dev/null; then
    echo "Error: 'spectool' command not found." >&2
    echo "Please ensure 'rpm-build' is installed and 'spectool' is in your PATH." >&2
    exit 1
fi

echo "--- Analyzing spec file: $SPEC_FILE ---"

SPEC_DIR=$(dirname "$FULL_SPEC_PATH")
FOUND_ISSUES=0
CHECKS_PERFORMED=0

# --- Determine the source directory once before looping ---

# Use spectool to find the basename of the primary source archive (Source0)
# This gives us the expected name of the extracted source directory.
SOURCE0_URL=$(spectool -l "$FULL_SPEC_PATH" | head -1 | cut -d' ' -f 2-)
if [[ -z "$SOURCE0_URL" ]]; then
    echo "Error: Could not determine Source0 from spec file using spectool." >&2
    exit 1
fi

# Remove common tarball extensions to get the directory name
SOURCE_DIR_BASENAME=$(basename "$SOURCE0_URL" | sed -E 's/(\.tar\.gz|\.tar\.bz2|\.tar\.xz|\.tgz|\.zip)$//')

# Find the extracted source directory, looking up to 2 levels deep from the spec directory.
# This handles cases where sources are extracted in './' or './SOURCES/'.
EXTRACTED_SOURCE_DIR=$(find "$SPEC_DIR" -maxdepth 2 -type d -name "$SOURCE_DIR_BASENAME" -print -quit)

if [[ -z "$EXTRACTED_SOURCE_DIR" ]]; then
    echo "Error: Could not find extracted source directory named '$SOURCE_DIR_BASENAME' within '$SPEC_DIR'" >&2
    exit 1
fi

echo "Found source directory: $EXTRACTED_SOURCE_DIR"

# Read the raw spec file line-by-line to preserve comments.
while IFS= read -r line || [[ -n "$line" ]]; do
    # Trim leading/trailing whitespace
    line=$(echo "$line" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')

    if [[ "$line" =~ ^#\ See:\ (.*) ]]; then
        # Store the path from the first regex match in its own variable.
        path_from_comment="${BASH_REMATCH[1]}"

        # Found a potential match. Read the next line.
        if read -r next_line; then
            # Trim the next line as well
            next_line=$(echo "$next_line" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')

            if [[ "$next_line" =~ ^Provides:\ bundled\(.*\)\ =\ (.*) ]]; then
                # Now get the version from the second regex match.
                version_from_provides="${BASH_REMATCH[1]}"

                CHECKS_PERFORMED=$((CHECKS_PERFORMED + 1))
                RELATIVE_PATH_RAW="$path_from_comment"
                VERSION_STRING_RAW="$version_from_provides"

                # Clean up trailing whitespace just in case
                RELATIVE_PATH=$(echo "$RELATIVE_PATH_RAW" | sed 's/[[:space:]]*$//')
                EXPECTED_VERSION=$(echo "$VERSION_STRING_RAW" | sed 's/[[:space:]]*$//')

                echo -e "\nChecking: '$RELATIVE_PATH' for version '$EXPECTED_VERSION'"

                VERSION_FILE_PATH="$EXTRACTED_SOURCE_DIR/$RELATIVE_PATH"

                if [[ ! -f "$VERSION_FILE_PATH" ]]; then
                    echo "  [FAIL] Error: Version file not found at '$VERSION_FILE_PATH'"
                    FOUND_ISSUES=1
                    continue
                fi

                # Read the first line of the version file
                ACTUAL_VERSION=$(head -n 1 "$VERSION_FILE_PATH")

                if [[ -z "$ACTUAL_VERSION" ]]; then
                    echo "  [FAIL] Error: Version file is empty or contains only a newline: '$VERSION_FILE_PATH'"
                    FOUND_ISSUES=1
                    continue
                fi

                # If the version read from the file is prefixed with 'v', remove it.
                if [[ "$ACTUAL_VERSION" == v* ]]; then
                    ACTUAL_VERSION="${ACTUAL_VERSION#v}"
                fi

                if [[ "$ACTUAL_VERSION" != "$EXPECTED_VERSION" ]]; then
                    echo "  [FAIL] Version mismatch in '$VERSION_FILE_PATH'"
                    echo "    - Expected (from spec): '$EXPECTED_VERSION'"
                    echo "    - Found (in file):    '$ACTUAL_VERSION'"
                    FOUND_ISSUES=1
                else
                    echo "  [OK] Version matches: '$ACTUAL_VERSION'"
                fi
            fi
        fi
    fi
done < "$FULL_SPEC_PATH" # Pipe the raw spec file into the while loop

if [[ "$CHECKS_PERFORMED" -eq 0 ]]; then
    echo "Warning: No 'bundled()' provides with '# See:' comments were found to check."
fi


if [[ "$FOUND_ISSUES" -eq 0 ]]; then
    echo -e "\n--- Verification successful! ---"
    exit 0
else
    echo -e "\n--- Verification failed. One or more bundled versions do not match. ---" >&2
    exit 1
fi


