#!/usr/bin/sh
#
# Copyright (C) 2014, 2017, 2021, 2025  Etersoft
# Copyright (C) 2014, 2017, 2021, 2025  Vitaly Lipatov <lav@etersoft.ru>
#
# This program 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.
#
# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
#

# Check if any argument is a valid task format: 123456, #123456, 123456/pkg, task/123456, task/123456/pkg
is_taskarg() {
    local arg
    for arg in "$@"; do
        [[ "$arg" =~ ^[[:space:]]*#?[0-9]+$ ]] && return 0
        [[ "$arg" =~ ^[0-9]+/[^/]+$ ]] && return 0
        [[ "$arg" =~ ^task/[0-9]+(/[^/]+)?$ ]] && return 0
    done
    return 1
}


is_taskurl()
{
    local pkg_urls="$1"
    [ -n "$pkg_urls" ] || return

    echo "$pkg_urls" | grep -q -E "https://packages.altlinux.org/ru/tasks/[0-9]+/*$" || \
    echo "$pkg_urls" | grep -q -E "https://git.altlinux.org/tasks/[0-9]+/*$" || \
    echo "$pkg_urls" | grep -q -E "https://git.altlinux.org/tasks/archive/done/_[0-9]+/[0-9]+/*$"
}

# Extract task number from various formats: 123456, #123456, 123456/pkg, task/123456, task/123456/pkg
get_tasknumber_from_arg()
{
    local arg="$1"
    local task=""
    # strip leading spaces and #
    arg="$(echo "$arg" | sed -e 's|^ *#*||')"
    case "$arg" in
        task/*/*)
            task=$(printf "%s" "$arg" | cut -d/ -f2)
            ;;
        task/*)
            task=$(printf "%s" "$arg" | cut -d/ -f2)
            ;;
        */*)
            task=$(printf "%s" "$arg" | cut -d/ -f1)
            ;;
        *)
            task="$arg"
            ;;
    esac
    isnumber "$task" && echo "$task"
}

# Extract package name from task arg formats: 123456/pkg, task/123456/pkg
get_pkgname_from_taskarg()
{
    local arg="$1"
    case "$arg" in
        task/*/*)
            printf "%s" "$arg" | cut -d/ -f3
            ;;
        task/[0-9]*)
            # task/123456 - no package name
            ;;
        [0-9]*/*)
            # 123456/pkg - first part is task number
            printf "%s" "$arg" | cut -d/ -f2
            ;;
    esac
}

ALTTASKURL="http://git.altlinux.org/tasks"

get_task_state()
{
    local tn="$1"
    fetch_url "$ALTTASKURL/$tn/task/state" 2>/dev/null
}

get_task_status()
{
    local tn="$1"
    docmd eget --check-url $ALTTASKURL/$tn/plan/add-bin
}

# print the branch of the task (sisyphus, p11, c10f2, ...)
get_task_repo()
{
    local tn="$1"
    fetch_url "$ALTTASKURL/$tn/task/repo" 2>/dev/null
}

# check if apt vendor (the key for [vendor] in sources.list) is defined in vendors.list
__alt_has_vendor()
{
    grep -qs "^[[:space:]]*simple-key[[:space:]]*\"$1\"" /etc/apt/vendors.list /etc/apt/vendors.list.d/*.list
}

# print [vendor] for the task repo: girar signs it by the key of the task branch
get_task_sign()
{
    local tn="$1"
    local branch vendor
    branch="$(get_task_repo "$tn")"
    case "$branch" in
        sisyphus)
            vendor="alt"
            ;;
        p[0-9]*)
            vendor="$branch"
            ;;
        c[0-9]*)
            vendor="updates"
            ;;
        *)
            return
            ;;
    esac
    if ! __alt_has_vendor "$vendor" ; then
        warning 'Vendor $vendor is missed in vendors.list, the signature of task $tn repo will not be checked'
        return
    fi
    echo "[$vendor]"
}

get_task_arepo_status()
{
    local tn="$1"
    docmd eget --check-url $ALTTASKURL/$tn/plan/arepo-add-x86_64-i586
}

get_task_packages_list()
{
    local tn="$1"
    local res

    res="$(fetch_url $ALTTASKURL/$tn/plan/add-bin)" || return
    echo "$res" | cut -f1-3 | grep -E "(noarch|$DISTRARCH)$" | cut -f1
}

get_task_arepo_packages_list()
{
    local tn="$1"
    local res

    res="$(fetch_url $ALTTASKURL/$tn/plan/arepo-add-x86_64-i586)" || return
    echo "$res" | cut -f1
}


get_task_packages()
{
    local arg tn
    for arg in "$@" ; do
        is_taskarg "$arg" || continue
        tn=$(get_tasknumber_from_arg "$arg")
        if ! get_task_status "$tn" ; then
            local state
            state="$(get_task_state "$tn")"
            if [ -n "$state" ] ; then
                warning 'Task $tn state is $state, packages are not yet available.'
            else
                warning 'Task $tn not found.'
            fi
            continue
        fi
        get_task_packages_list "$tn"
        [ "$DISTRARCH" = "x86_64" ] || continue
        get_task_arepo_status "$tn" || continue
        get_task_arepo_packages_list "$tn"
    done
}

# check if dnf5 takes repos from /etc/apt/sources.list* (libdnf5-plugin-apt)
__alt_dnf_uses_apt_sources()
{
    [ "$PMTYPE" = "dnf5-rpm" ] || return
    local conf=/etc/dnf/libdnf5-plugins/apt.conf
    grep -qsE '^[[:space:]]*enabled[[:space:]]*=[[:space:]]*(1|yes|true|on)[[:space:]]*$' $conf || return
    ! grep -qsE '^[[:space:]]*sources[[:space:]]*=[[:space:]]*(0|no|false|off)[[:space:]]*$' $conf
}

# rpm-md metadata for dnf on ALT is generated only on Etersoft mirror
ALT_DNF_MIRROR="http://download.etersoft.ru/pub"
# the key of repomd.xml.asc signatures on the mirror
ALT_DNF_MIRROR_KEYURL="$ALT_DNF_MIRROR/Etersoft/RPM-GPG-KEY-etersoft-mirror-metadata"
ALT_DNF_MIRROR_KEYFPR="24F2AD07095B62CC48D5AC7C81C29C26E0056291"
ALT_DNF_MIRROR_KEYFILE="/etc/pki/rpm-gpg/RPM-GPG-KEY-etersoft-mirror-metadata"

# print base url (without arch) of rpm-md repo for dnf on ALT
# args: sisyphus|p11|...|deferred|deferred.org|deferred-devel|deferred-beta
__alt_dnf_baseurl()
{
    case "$1" in
        sisyphus|Sisyphus)
            echo "$ALT_DNF_MIRROR/ALTLinux/Sisyphus"
            ;;
        deferred)
            echo "$ALT_DNF_MIRROR/Etersoft/Sisyphus/Deferred"
            ;;
        deferred.org)
            echo "http://mirror.eterfund.org/pub/Etersoft/Sisyphus/Deferred"
            ;;
        deferred-devel)
            echo "$ALT_DNF_MIRROR/Etersoft/Sisyphus/Deferred_DEVEL"
            ;;
        deferred-beta)
            echo "$ALT_DNF_MIRROR/Etersoft/Sisyphus/Deferred_BETA"
            ;;
        p[0-9]*|c[0-9]*)
            echo "$ALT_DNF_MIRROR/ALTLinux/$1/branch"
            ;;
        *)
            return 1
            ;;
    esac
}

# print arch subdirs of ALT repo
__alt_dnf_archlist()
{
    echo "noarch"
    echo "$DISTRARCH"
    [ "$DISTRARCH" = "x86_64" ] && echo "x86_64-i586"
    return 0
}

# print dnf option to install kernel modules alongside (like kernel-image), as apt does with Allow-Duplicated
# args: [module package names] (installed kernel-modules-* are added)
__alt_dnf_installonly_opt()
{
    local cur
    cur="$(a='' $DNFCMD --dump-main-config 2>/dev/null | sed -n 's/^installonlypkgs = //p')"
    [ -n "$cur" ] || cur="kernel"
    local modules
    modules="$(estrlist union "$* $(a='' rpm -qa --qf '%{NAME}\n' 'kernel-modules-*' 2>/dev/null)")"
    [ -n "$modules" ] || return 0
    echo "--setopt=installonlypkgs=$cur,$(echo $modules | tr ' ' ',')"
}
