#! /usr/bin/env python3
# Copyright (C) 2021, meta-linux-mainline contributors
# SPDX-License-Identifier: MIT

import sys

if sys.version_info < (3, 7):
    print("ERROR: This script requires Python 3.7 or later!")
    sys.exit(1)

import re
import subprocess
import textwrap
import urllib.request


def get_srcrev(version, upstream):
    p = subprocess.run(
        [
            "git",
            "ls-remote",
            "--tags",
            f"https://git.kernel.org/pub/scm/linux/kernel/git/{upstream}/linux.git",
            f"v{version}^{{}}",
        ],
        capture_output=True,
        check=True,
    )
    srcrev = p.stdout.decode().split()[0]
    # print(f"Got srcrev {srcrev} for version {version}")
    return srcrev


def update_mainline_recipe(version):
    old_recipe = open("recipes-kernel/linux/linux-mainline.bb", "r").read()
    old_version = re.search(r'LINUX_VERSION = "(.*)"', old_recipe)[1]

    print(f"mainline: {old_version} -> {version}")
    if old_version != version:
        srcrev = get_srcrev(version, "torvalds")

        # Write the new recipe
        open("recipes-kernel/linux/linux-mainline.bb", "w").write(
            textwrap.dedent(
                f"""\
                # Copyright meta-linux-mainline contributors (auto-generated file)
                # SPDX-License-Identifier: CC0-1.0
                LINUX_VERSION = "{version}"
                SRCREV = "{srcrev}"
                require linux-mainline.inc
                """
            )
        )

        msg = f"linux-mainline: Uprev to {version}"
        subprocess.run(
            ["git", "add", "recipes-kernel/linux/linux-mainline.bb"], check=True
        )
        subprocess.run(
            ["git", "commit", "-s", "-F", "-"], input=msg.encode("utf-8"), check=True
        )


def update_stable_recipe(version):
    vsplit = version.split(".")
    if len(vsplit) != 3:
        print(f"{version}.y: Skipping mainline release")
        return

    vmajor, vminor, vpatch = int(vsplit[0]), int(vsplit[1]), int(vsplit[2])

    fname = f"recipes-kernel/linux/linux-stable_{vmajor}.{vminor}.bb"
    try:
        old_recipe = open(fname, "r").read()
        old_vpatch = int(re.search(r'LINUX_VPATCH = "(\d+)"', old_recipe)[1])
    except FileNotFoundError:
        old_vpatch = 0

    print(
        f"{vmajor}.{vminor}.y: {vmajor}.{vminor}.{old_vpatch} -> {vmajor}.{vminor}.{vpatch}"
    )
    if old_vpatch != vpatch:
        srcrev = get_srcrev(version, "stable")

        # Write the new recipe
        open(fname, "w").write(
            textwrap.dedent(
                f"""\
                # Copyright meta-linux-mainline contributors (auto-generated file)
                # SPDX-License-Identifier: CC0-1.0
                LINUX_VMAJOR = "{vmajor}"
                LINUX_VMINOR = "{vminor}"
                LINUX_VPATCH = "{vpatch}"
                SRCREV = "{srcrev}"
                require linux-stable.inc
                """
            )
        )

        if old_vpatch:
            msg = f"linux-stable: Uprev {vmajor}.{vminor} recipe to v{vmajor}.{vminor}.{vpatch}"
        else:
            msg = f"linux-stable: Add {vmajor}.{vminor} recipe at v{vmajor}.{vminor}.{vpatch}"
        subprocess.run(
            ["git", "add", f"recipes-kernel/linux/linux-stable_{vmajor}.{vminor}.bb"],
            check=True,
        )
        subprocess.run(
            ["git", "commit", "-s", "-F", "-"], input=msg.encode("utf-8"), check=True
        )


def update_recipes():
    mainline_version = None
    stable_versions = set()
    # next_version = None

    f = urllib.request.urlopen("https://www.kernel.org/finger_banner")
    for line in f:
        line = line.decode()
        if not line.startswith("The latest "):
            print(f"Unexpected line in finger banner: {line}")
            continue
        release_type = line.split()[2]
        version = line.split(":")[1].replace("(EOL)", "").strip()
        if release_type == "mainline" and not mainline_version:
            mainline_version = version
        if release_type in ("stable", "longterm"):
            stable_versions.add(version)
        # if release_type == "linux-next":
        #    next_version = version

    update_mainline_recipe(mainline_version)
    for version in stable_versions:
        update_stable_recipe(version)
    # TODO: update_next_recipe(next_version)


def check_for_unstaged_changes():
    r = subprocess.run(["git", "diff-index", "--quiet", "HEAD"])
    if r.returncode:
        print("Error: Repository is not clean")
        sys.exit(1)


def main():
    check_for_unstaged_changes()
    update_recipes()
    print("Done.")


main()
