#!/bin/sh
#
# Copyright (C) 2013, 2016, 2017, 2019, 2020, 2021  Etersoft
# Copyright (C) 2013, 2016, 2017, 2019, 2020, 2021  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/>.
#

load_helper epm-query
load_helper epm-repofix
load_helper epm-reposave

assure_safe_run()
{
    if [ "$TERM" = "linux" ] ; then
        message "You have the best choise to run the '# epm release-upgrade' from text console."
        return
    fi
    if [ "$TERM" != "screen" ] ; then
        if [ -n "$force" ] ; then
            message 'You force me running not under screen (TERM=$TERM now)! You can lost your system!'
            return
        else
            warning 'It is very dangerous to upgrade to next release from a GUI (your TERM=$TERM).'
            if is_installed screen ; then
                warning "You have 'screen' already installed, just run upgrade via screen (check https://losst.ru/komanda-screen-linux if needed)."
            else
                warning "It is recommended install 'screen' and run upgrade via screen (check https://losst.ru/komanda-screen-linux if needed)."
            fi
            fatal "or run me with --force if you understand the risk."
        fi
    fi

    # run under screen, check if systemd will not kill our processes
    local res
    if ! is_active_systemd ; then
        return
    fi

    res="$(a= busctl get-property org.freedesktop.login1 /org/freedesktop/login1 org.freedesktop.login1.Manager KillUserProcesses)"
    if [ "$res" = "b false" ] ; then
        message "Good news: systemd-logind will not kill your screen processes (KillUserProcesses=false)"
        return
    else
        if [ -n "$force" ] ; then
            warning "You force runnning even if systemd-logind kills screen on disconnect"
        else
            if ! epm installed systemd-settings-disable-kill-user-processes ; then
                docmd epm install systemd-settings-disable-kill-user-processes || fatal "Can't install the package above. Fix it or run with --force."
            fi
            # commented, will kick off the user from the system (ALT issue 50580)
            #docmd serv systemd-logind restart || fatal "Can't restart systemd-logind service. Fix it or run with --force."
            fatal "Now you need relogin to the system. In this session your screen still will be killed."
        fi
    fi

    # check too: KillExcludeUsers

    # can continue
    return 0
}

__wcount()
{
    echo "$*" | wc -w
}

__p11_upgrade_fix()
{
    if [[ ! $(docmd epm installed apt-conf-branch) ]]; then 
        info "Need to install default apt-conf package to avoid missing $TO repo"
        docmd epm install apt-conf-branch || fatal
    fi
    # libcrypto1.1 fix
    docmd epm repo save
    docmd epm repo rm all
    docmd apt-repo add branch sisyphus 2024/05/22
    docmd epm update
    docmd epm install libcrypto1.1
    docmd epm repo rm all
    docmd epm repo restore
}

__sisyphus_downgrade_fix()
{
    if [[ ! $(docmd epm installed apt-conf-branch) ]]; then 
        info "Need to install default apt-conf package to avoid missing $TO repo"
        docmd epm install apt-conf-branch || fatal
    fi
}

# TODO: remove it or move to distro_info
__detect_alt_release_by_repo()
{
    local BRD=$(cat /etc/apt/sources.list /etc/apt/sources.list.d/*.list \
        | grep -v "^#" \
        | grep -E "[tpc][1-3]?[5-9][f.]?[0-9]?/branch/" \
        | sed -e "s|.*\([tpc][1-3]\?[5-9][f.]\?[0-9]\?\)/branch.*|\1|g" \
        | sort -u )
    if [ "$(__wcount $BRD)" = "1" ] ; then
        echo "$BRD"
        return
    fi

    local BRD=$(cat /etc/apt/sources.list /etc/apt/sources.list.d/*.list \
        | grep -v "^#" \
        | grep "Sisyphus/" \
        | sed -e "s|.*\(Sisyphus\).*|\1|g" \
        | sort -u )
    if [ "$(__wcount $BRD)" = "1" ] ; then
        echo "$BRD"
        return
    fi

    return 1
}


__get_conflict_release_pkg()
{
    epm qf --quiet --short /etc/fedora-release | head -n1
}

get_fix_release_pkg()
{
    local TOINSTALL=''

    local FORCE=''
    if [ "$1" = "--force" ] ; then
        FORCE="$1"
        shift
    fi

    local TO="$1"

    if [ "$TO" = "Sisyphus" ] ; then
        TO="sisyphus"
        echo "apt-conf-$TO"
        # apt-conf-sisyphus and apt-conf-branch conflicts
        epm installed apt-conf-branch && echo "apt-conf-branch-"
        #for i in apt apt-rsync libapt libpackagekit-glib librpm7 packagekit rpm synaptic realmd libldap2 ; do
        #    epm installed $i && echo "$i"
        #done

    else
        epm installed apt-conf-branch && echo "apt-conf-branch" && epm installed apt-conf-sisyphus && echo "apt-conf-sisyphus-"
    fi

    if [ "$FORCE" = "--force" ] ; then
        # assure we have set needed release
        TOINSTALL="altlinux-release-$TO"
    else
        # just assure we have /etc/altlinux-release and switched from sisyphus
        if [ ! -s /etc/altlinux-release ] || epm qf /etc/altlinux-release | grep -q sisyphus ; then
            TOINSTALL="altlinux-release-$TO"
        fi
    fi

    #local AR="$(epm --short qf /etc/altlinux-release)"
    #if [ -n "$AR" ] && [ "$AR" != "$TOINSTALL" ] ; then
    #    echo "$AR-"
    #fi

    # TODO: add bug?
    # workaround against obsoleted altlinux-release-sisyphus package from 2008 year
    [ "$TOINSTALL" = "altlinux-release-sisyphus" ] && TOINSTALL="branding-alt-sisyphus-release"

    if epm installed etersoft-gpgkeys ; then
        # TODO: we don't support LINUX@Etersoft for now
        # leave etersoft-gpgkeys only if we have LINUX@Etersoft repo
        #epm repo list | grep -q "LINUX@Etersoft" && echo "etersoft-gpgkeys" || echo "alt-gpgkeys"
        epm --quiet repo comment "LINUX@Etersoft"
        echo "alt-gpgkeys"
    else
        # update if installed (just print package name here to include in the install list)
        epm query --short alt-gpgkeys 2>/dev/null
    fi

    if [ -n "$TOINSTALL" ] ; then
        echo "$TOINSTALL"

        # workaround against
        #    file /etc/fedora-release from install of altlinux-release-p8-20160414-alt1 conflicts with file from package branding-simply-linux-release-8.2.0-alt1
        # problem
        local AR="$(__get_conflict_release_pkg)"
        if [ -n "$AR" ] && [ "$TOINSTALL" != "$AR" ] ; then
            #echo $AR-
            # remove conflicts package right here to workaround against asking 'Yes, do as I say!' later
            epm remove --nodeps $AR >/dev/null
        fi
    fi
}

__check_system()
{
    local TO="$1"
    shift

    # sure we have systemd if systemd is running
    if is_active_systemd ; then
        docmd epm --skip-installed install systemd || fatal
    fi

    if [ "$TO" != "Sisyphus" ] ; then
        # note: we get --base-version directy to get new version
        if [ "$($DISTRVENDOR --base-version)" != "$TO" ] || epm installed altlinux-release-sisyphus >/dev/null ; then
            warning 'Current distro still is not $TO, or altlinux-release-sisyphus package is installed.'
            warning 'Trying to fix with altlinux-release-$TO'
            docmd epm install altlinux-release-$TO
        fi
    fi

    # switch from prefdm: https://bugzilla.altlinux.org/show_bug.cgi?id=26405#c47
    if is_active_systemd ; then
        if serv display-manager exists || serv prefdm exists ; then
            # don't stop running X server!
            # docmd serv dm off
            docmd serv disable prefdm
            docmd serv disable display-manager
            docmd serv enable display-manager

# $ epm sf dm.service
# xinitrc: /lib/systemd/system/dm.service
# gdm: /lib/systemd/system/gdm.service
# lightdm: /lib/systemd/system/lightdm.service
# lxde-lxdm: /lib/systemd/system/lxdm.service
# xinitrc: /lib/systemd/system/prefdm.service
# sddm: /lib/systemd/system/sddm.service
            # enable first available DM
            for i in lightdm sddm lxde-lxdm gdm ; do
                serv $i exists && docmd serv enable $i && break
            done
        fi
    fi

}

__epm_ru_update()
{
    docmd epm update && return
    # TODO: there can be errors due obsoleted alt-gpgkeys
    epm update 2>&1 | grep "E: Unknown vendor ID" || return
    info "Drop vendor signs"
    __alt_replace_sign_name ""
    docmd epm update
}

__switch_repo_to()
{
    epm_reposwitch "$@"
    __epm_ru_update || fatal
}

get_next_release()
{
    local FROM="$1"
    case "$FROM" in
    "p6")
        echo "p7" ;;
    "p7")
        echo "p8" ;;
    "p8")
        echo "p9" ;;
    "p9")
        echo "p10" ;;
    "p10")
        echo "p11" ;;
    "c6")
        echo "c7" ;;
    "c7")
        echo "c8" ;;
#    "c8")
#        echo "c8.1" ;;
    "c8.1")
        echo "c8.2" ;;
    "c8")
        echo "c9f2" ;;
    "c9f1")
        echo "c9f2" ;;
    "c10f1")
        echo "c10f2" ;;
    *)
        echo "$FROM" ;;
    esac
}

__do_upgrade()
{
    docmd epm $non_interactive $force_yes upgrade || fatal "Check the errors and run '# $0' again"
}

# TODO: install new conf without signs?
__switch_alt_to_distro()
{
    local TO="$2"
    local FROM="$1"
    info

    try_change_alt_repo

    case "$*" in
        "p6"|"p6 p7"|"t6 p7"|"c6 c7")
            confirm_info "Upgrade $DISTRNAME from $FROM to $TO ..."
            docmd epm install rpm apt $(get_fix_release_pkg "$FROM") || fatal
            __switch_repo_to $TO
            docmd epm install rpm apt $(get_fix_release_pkg --force "$TO") || fatal "Check the errors and run '# epm release-upgrade' again"
            end_change_alt_repo
            __do_upgrade
            docmd epm update-kernel
            info "Run epm release-upgrade again for update to p8"
            ;;
        "p7"|"p7 p8"|"t7 p8"|"c7 c8")
            confirm_info "Upgrade $DISTRNAME from $FROM to $TO ..."
            docmd epm install rpm apt $(get_fix_release_pkg "$FROM") || fatal
            __switch_repo_to $TO
            docmd epm install rpm apt $(get_fix_release_pkg --force "$TO") || fatal "Check the errors and run '# epm release-upgrade' again"
            end_change_alt_repo
            __do_upgrade
            __check_system "$TO"
            docmd epm update-kernel || fatal
            info "Run epm release-upgrade again for update to p9"
            ;;
        "c8"|"c8.1"|"c8.2"|"c8 c8.1"|"c8.1 c8.2"|"c8 c8.2")
            confirm_info "Upgrade $DISTRNAME from $FROM to $TO ..."
            docmd epm install rpm apt $(get_fix_release_pkg "$FROM") || fatal
            __switch_repo_to $TO
            docmd epm install rpm apt $(get_fix_release_pkg --force "$TO") || fatal "Check the errors and run '# epm release-upgrade' again"
            end_change_alt_repo
            __do_upgrade
            __check_system "$TO"
            docmd epm update-kernel || fatal
            ;;
        "p8 c8"|"p8 c8.1"|"p8 c8.2")
            confirm_info "Upgrade $DISTRNAME from $FROM to $TO ..."
            docmd epm install rpm apt $(get_fix_release_pkg "$FROM") || fatal
            __switch_repo_to $TO
            docmd epm install rpm apt $(get_fix_release_pkg --force "$TO") || fatal "Check the errors and run '# epm release-upgrade' again"
            if epm installed libcrypt ; then
                # glibc-core coflicts libcrypt
                docmd epm downgrade apt pam pam0_passwdqc glibc-core libcrypt- || fatal
            fi
            docmd epm $non_interactive $force_yes downgrade || fatal
            end_change_alt_repo
            __do_upgrade
            __check_system "$TO"
            docmd epm update-kernel || fatal
            ;;
        "p8"|"p8 p9"|"t8 p9"|"c8 c9"|"c8 p9"|"c8.1 p9"|"c8.2 p9"|"p9 p9"|"p9 c9f2")
            confirm_info "Upgrade $DISTRNAME from $FROM to $TO ..."
            docmd epm install rpm apt $(get_fix_release_pkg "$FROM") || fatal
            info "Workaround for https://bugzilla.altlinux.org/show_bug.cgi?id=35492 ..."
            if epm installed gdb >/dev/null ; then
                docmd epm remove gdb || fatal
            fi
            __switch_repo_to $TO
            end_change_alt_repo
            __do_upgrade
            docmd epm install rpm apt $(get_fix_release_pkg --force "$TO") || fatal "Check the errors and run '# epm release-upgrade' again"
            __check_system "$TO"
            docmd epm update-kernel || fatal
            info "Run epm release-upgrade again for update to p10"
            ;;
        "p9"|"p9 p10"|"p10 p10"|"p10 p11")
            info "Upgrade all packages to current $FROM repository"
            __do_upgrade
            confirm_info "Upgrade $DISTRNAME from $FROM to $TO ..."
            docmd epm install rpm apt $(get_fix_release_pkg "$FROM") || fatal
            if [ $TO = "p11" ]; then __p11_upgrade_fix; fi
            __switch_repo_to $TO
            end_change_alt_repo
            __do_upgrade
            docmd epm install rpm apt $(get_fix_release_pkg "$TO") || fatal "Check the errors and run '# epm release-upgrade' again"
            __check_system "$TO"
            docmd epm update-kernel -t std-def || fatal
            ;;
        "p9 p8"|"c8.1 c8"|"c8.1 p8"|"p8 p8")
            confirm_info "Downgrade $DISTRNAME from $FROM to $TO ..."
            docmd epm install $(get_fix_release_pkg "$FROM")
            __switch_repo_to $TO
            docmd epm downgrade rpm apt $(get_fix_release_pkg --force "$TO") || fatal "Check the errors and run '# epm release-upgrade' again"
            if epm installed libcrypt >/dev/null ; then
                # glibc-core coflicts libcrypt
                docmd epm downgrade apt rpm pam pam0_passwdqc glibc-core libcrypt- || fatal
            fi
            docmd epm $force_yes $non_interactive downgrade || fatal "Check the error and run '# epm downgrade'"
            end_change_alt_repo
            __check_system "$TO"
            docmd epm upgrade || fatal
            ;;
        "p9 c8"|"p9 c8.1"|"p9 c8.2")
            confirm_info "Downgrade $DISTRNAME from $FROM to $TO ..."
            docmd epm install $(get_fix_release_pkg "$FROM")
            __switch_repo_to $TO
            docmd epm downgrade rpm apt $(get_fix_release_pkg --force "$TO") || fatal "Check the errors and run '# epm release-upgrade' again"
            #if epm installed libcrypt >/dev/null ; then
            #    # glibc-core coflicts libcrypt
            #    docmd epm downgrade apt rpm pam pam0_passwdqc glibc-core libcrypt- || fatal
            #fi
            docmd epm $force_yes $non_interactive downgrade || fatal "Check the error and run '# epm downgrade'"
            end_change_alt_repo
            __check_system "$TO"
            docmd epm upgrade || fatal
            ;;
        "p10 p9"|"p11 p9")
            confirm_info "Downgrade $DISTRNAME from $FROM to $TO ..."
            docmd epm install $(get_fix_release_pkg "$FROM")
            __switch_repo_to $TO
            docmd epm downgrade rpm apt $(get_fix_release_pkg --force "$TO") || fatal "Check the errors and run '# epm release-upgrade' again"
            docmd epm $force_yes $non_interactive downgrade || fatal "Check the error and run '# epm downgrade'"
            end_change_alt_repo
            __check_system "$TO"
            docmd epm upgrade || fatal
            ;;
        "Sisyphus p8"|"Sisyphus p9"|"Sisyphus p10"|"Sisyphus p11"|"Sisyphus c8"|"Sisyphus c8.1"|"Sisyphus c9f2"|"Sisyphus c10f1"|"Sisyphus c10f2")
            confirm_info "Downgrade $DISTRNAME from $FROM to $TO ..."
            docmd epm install $(get_fix_release_pkg "$FROM")
            if [ $TO = "p11" ]; then __sisyphus_downgrade_fix; fi
            __switch_repo_to $TO
            docmd epm downgrade rpm apt $(get_fix_release_pkg --force "$TO") || fatal "Check the errors and run '# epm release-upgrade' again"
            docmd epm $force_yes $non_interactive downgrade || fatal "Check the error and run '# epm downgrade'"
            end_change_alt_repo
            __check_system "$TO"
            docmd epm upgrade || fatal
            ;;
        "p8 Sisyphus"|"p9 Sisyphus"|"p10 Sisyphus"|"p11 Sisyphus"|"10 Sisyphus"|"Sisyphus Sisyphus")
            confirm_info "Upgrade $DISTRNAME from $FROM to $TO ..."
            docmd epm install rpm apt $(get_fix_release_pkg "$FROM") || fatal
            docmd epm upgrade || fatal
            # TODO: epm_reposwitch??
            __replace_alt_version_in_repo "$FROM/branch/" "$TO/"
            __switch_repo_to $TO
            [ -s /etc/rpm/macros.d/p10 ] && rm -fv /etc/rpm/macros.d/p10
            [ -s /etc/rpm/macros.d/p11 ] && rm -fv /etc/rpm/macros.d/p11
            __epm_ru_update || fatal
            docmd epm fix || fatal
            docmd epm install $(get_fix_release_pkg --force "$TO") || fatal "Check the errors and run '# epm release-upgrade' again"
            #local ADDPKG
            #ADDPKG=$(epm -q --short make-initrd sssd-ad 2>/dev/null)
            #docmd epm install librpm7 librpm rpm apt $ADDPKG $(get_fix_release_pkg --force "$TO") ConsoleKit2- || fatal "Check an error and run again"
            end_change_alt_repo
            docmd epm $force_yes $non_interactive upgrade || fatal "Check the error and run '# epm release-upgrade' again or just '# epm upgrade'"
            docmd epm $force_yes $non_interactive downgrade || fatal "Check the error and run '# epm downgrade'"
            __check_system "$TO"
            docmd epm update-kernel || fatal
            ;;
        *)
            if [ "$FROM" = "$TO" ] ; then
                info 'It seems your system is already $DISTRNAME $TO'
            else
                warning 'Unknown distro version. Have no idea how to switch from $DISTRNAME $FROM to $DISTRNAME $TO.'
            fi
            end_change_alt_repo
            info "Try run f.i. '# epm release-upgrade p10' or '# epm release-downgrade p9' or '# epm release-upgrade Sisyphus'"
            info "Also possible you need install altlinux-release-p? package for correct distro version detecting"
            return 1
    esac
    docmd epm clean
    docmd epm update
}

epm_release_upgrade()
{
    assure_root
    assure_safe_run
    info "Starting upgrade/switch whole system to other release"
    info "Check also http://wiki.etersoft.ru/Admin/UpdateLinux"

    cd / || fatal
    # TODO: it is possible eatmydata does not do his work
    export EPMNOEATMYDATA=1

    case $BASEDISTRNAME in
    "alt")
        __epm_ru_update || fatal

        # TODO: remove this hack (or move it to distro_info)
        # try to detect current release by repo
        if [ "$DISTRVERSION" = "Sisyphus" ] || [ -z "$DISTRVERSION" ] ; then
            local dv
            dv="$(__detect_alt_release_by_repo)"
            if [ -n "$dv" ] && [ "$dv" != "$DISTRVERSION" ] ; then
                DISTRVERSION="$dv"
                info 'Detected running $DISTRNAME $DISTRVERSION (according to using repos)'
            fi
        fi

        TARGET=""
        [ -n "$3" ] && fatal 'Too many args: $*'
        if [ -n "$2" ] ; then
            DISTRVERSION="$1"
            info 'Force current distro version as $DISTRVERSION'
            TARGET="$2"
        elif [ -n "$1" ] ; then
            TARGET="$1"
        fi

        [ "$TARGET" = "Sisyphus" ] && info "Check also https://www.altlinux.org/Update/Sisyphus"

        [ -n "$TARGET" ] || TARGET="$(get_next_release $DISTRVERSION)"

        __alt_repofix

        __switch_alt_to_distro $DISTRVERSION $TARGET && info 'Done. The system has been successfully upgraded to the next release $TO.'

        return 0
        ;;
    *)
        ;;
    esac

    case $DISTRNAME in
    "Mageia")
        epm repo remove all
        sudocmd urpmi.addmedia --distrib --mirrorlist 'http://mirrors.mageia.org/api/mageia.8.$DISTRARCH.list'
        sudocmd urpmi --auto-update $non_interactive $force
        return
        ;;
     "OpenMandrivaLx")
        sudocmd dnf clean all
        sudocmd dnf distro-sync --allowerasing
        return
        ;;
    "ROSA")
        # TODO: move to distro related upgrade
        #epm repo remove all
        # FIXME: don't work:
        #epm repo add "http://mirror.rosalinux.ru/rosa/rosa2021.1/repository/$DISTRARCH"
        #showcmd urpmi.addmedia --distrib http://mirror.yandex.ru/mandriva/devel/2010.2/i586/
        #sudocmd urpmi --auto-update --replacefiles
        return
        ;;
    *)
        ;;
    esac

    case $PMTYPE in
    apt-rpm)
        #docmd epm update
        info 'Have no idea how to upgrade $DISTRNAME. It is possible you need use release-downgrade'
        ;;
    *-dpkg)
        assure_exists do-release-upgrade update-manager-core
        sudocmd do-release-upgrade
        ;;
    packagekit)
        docmd pkcon upgrade-system "$@"
        ;;
    yum-rpm)
        docmd epm install rpm yum
        sudocmd yum clean all
        info "Try do manually:"
        showcmd rpm -Uvh http://mirror.yandex.ru/fedora/linux/releases/16/Fedora/x86_64/os/Packages/fedora-release-16-1.noarch.rpm
        showcmd epm Upgrade
        ;;
    dnf-rpm)
        if [ "$DISTRNAME/$DISTRVERSION" = "CentOS/8" ] ; then
            if [ "$1" = "RockyLinux" ] ; then
                info "https://github.com/rocky-linux/rocky-tools/tree/main/migrate2rocky/"
                confirm_info "Switch to Rocky Linux 8.x"
                cd /tmp
                docmd epm install git
                sudocmd git clone https://github.com/rocky-linux/rocky-tools.git || fatal
                sudocmd bash rocky-tools/migrate2rocky/migrate2rocky.sh -r
                exit
            fi

            if [ "$1" = "OracleLinux" ] ; then
                info "Check https://t.me/srv_admin/1630"
                confirm_info "Switch to Oracle Linux 8.x"
                cd /tmp
                docmd epm install git
                sudocmd sed -i -r \
                    -e 's!^mirrorlist=!#mirrorlist=!' \
                    -e 's!^#?baseurl=http://(mirror|vault).centos.org/\$contentdir/\$releasever/!baseurl=https://dl.rockylinux.org/vault/centos/8.5.2111/!i' \
                        /etc/yum.repos.d/CentOS-*.repo
                sudocmd git clone https://github.com/oracle/centos2ol.git || fatal
                a= bash centos2ol/centos2ol.sh
                exit
            fi

            info "Check https://www.cyberciti.biz/howto/upgrade-migrate-from-centos-8-to-centos-stream-conversion/"
            confirm_info "Switch to CentOS Stream?"
            sudocmd sed -i -r \
                    -e 's!^mirrorlist=!#mirrorlist=!' \
                    -e 's!^#?baseurl=http://(mirror|vault).centos.org/\$contentdir/\$releasever/!baseurl=https://dl.rockylinux.org/vault/centos/8.5.2111/!i' \
                        /etc/yum.repos.d/CentOS-*.repo
            docmd epm install centos-release-stream
            sudocmd dnf swap centos-{linux,stream}-repos
            sudocmd dnf distro-sync
            info "You can run '# epm autoorphans' to remove orphaned packages"
            exit
        fi

        if [ "$DISTRNAME" = "RockyLinux" ] ; then
            sudocmd dnf --refresh upgrade || fatal
            sudocmd dnf clean all
            info "Check https://www.centlinux.com/2022/07/upgrade-your-servers-from-rocky-linux-8-to-9.html"
            info "For upgrading your yum repositories from Rocky Linux 8 to 9 ..."
            epm install "https://download.rockylinux.org/pub/rocky/9/BaseOS/x86_64/os/Packages/r/rocky-gpg-keys*.rpm" || fatal
            epm install "https://download.rockylinux.org/pub/rocky/9/BaseOS/x86_64/os/Packages/r/rocky-repos*.rpm" "https://download.rockylinux.org/pub/rocky/9/BaseOS/x86_64/os/Packages/r/rocky-release*.rpm" || fatal

            # hack (TODO)
            DV=$(echo "$DISTRVERSION" | sed -e "s|\..*||")
            local RELEASEVER="$1"
            [ -n "$RELEASEVER" ] || RELEASEVER=$(($DV + 1))
            confirm_info 'Upgrade to $DISTRNAME/$RELEASEVER'

            sudocmd dnf distro-sync -y --releasever=$RELEASEVER --allowerasing --setopt=deltarpm=false
            sudocmd rpm --rebuilddb
            epm upgrade
            info "You can run '# epm autoorphans' to remove orphaned packages"
            info "Use # dnf module reset <module> to resolve 'nothing provides module' error"
            exit
        fi

        info "Check https://fedoraproject.org/wiki/DNF_system_upgrade for an additional info"
        #docmd epm install epel-release yum-utils
        sudocmd dnf --refresh upgrade || fatal
        sudocmd dnf clean all
        assure_exists dnf-plugin-system-upgrade
        sudocmd dnf upgrade --refresh
        local RELEASEVER="$1"
        [ -n "$RELEASEVER" ] || RELEASEVER=$(($DISTRVERSION + 1))
        #[ -n "$RELEASEVER" ] || fatal "Run me with new version"
        confirm_info 'Upgrade to $DISTRNAME/$RELEASEVER'
        sudocmd dnf system-upgrade download --refresh --releasever=$RELEASEVER
        # TODO: from docs:
        # dnf system-upgrade reboot
        # FIXME: download all packages again
        sudocmd dnf distro-sync --releasever=$RELEASEVER
        info "You can run '# epm autoorphans' to remove orphaned packages"
        ;;
    zypper-rpm)
        docmd epm repolist
        # TODO: move to distro related upgrade
        # sudocmd zypper rr <номер_репозитория>
        showcmd rr N
        showcmd epm ar http://mirror.yandex.ru/opensuse/distribution/11.1/repo/oss 11.1oss
        showcmd zypper ref
        docmd epm update
        docmd epm install rpm zypper
        docmd epm upgrade
        ;;
    pacman)
        docmd epm Upgrade
        ;;
    conary)
        docmd epm Upgrade
        ;;
    emerge)
        docmd epm Upgrade
        ;;
    guix)
        sudocmd guix pull --verbose
        ;;
    *)
        fatal 'Have no suitable command for $PMTYPE'
        ;;
    esac

}