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

__replace_text_in_alt_repo()
{
	local i
	for i in /etc/apt/sources.list /etc/apt/sources.list.d/*.list ; do
		[ -s "$i" ] || continue
		regexp_subst "$1" "$i"
	done
}

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

__detect_alt_release_by_repo()
{
	local BRD=$(cat /etc/apt/sources.list /etc/apt/sources.list.d/*.list \
		| grep -v "^#" \
		| grep "p[5-9]/branch/" \
		| sed -e "s|.*\(p[5-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
}

__replace_alt_version_in_repo()
{
	local i
	assure_exists apt-repo
	#echo "Upgrading $DISTRNAME from $1 to $2 ..."
	docmd apt-repo list | sed -e "s|\($1\)|{\1}->{$2}|g" | egrep --color -- "$1"
	# ask and replace only we will have changes
	if a='' apt-repo list | egrep -q -- "$1" ; then
		confirm "Are these correct changes? [y/N]" || fatal "Exiting"
		__replace_text_in_alt_repo "/^ *#/! s!$1!$2!g"
	fi
	docmd apt-repo list
}

__alt_repofix()
{
	load_helper epm-repofix
	showcmd epm repofix
	quiet=1 pkg_filenames='' epm_repofix >/dev/null
	__replace_text_in_alt_repo "/^ *#/! s!\[p[6-9]\]![updates]!g"
}

get_fix_release_pkg()
{
	# TODO: check for version incompatibilities
	if epmqf /etc/altlinux-release | grep -q sisyphus ; then
		echo altlinux-release-$1
	fi
}

__update_to_the_distro()
{
	__alt_repofix
	case "$1" in
		p7)
			docmd epm update || fatal
			docmd epm install apt rpm apt-conf-branch $(get_fix_release_pkg p7) || fatal "Check an error and run epm release-upgrade again"
			__alt_repofix
			__replace_text_in_alt_repo "/^ *#/! s!\[updates\]![p7]!g"
			docmd epm update || fatal
			docmd epm upgrade || fatal "Check an error and run epm release-upgrade again"
			;;
		p8)
			docmd epm update || fatal
			if ! docmd epm install apt rpm apt-conf-branch $(get_fix_release_pkg p8) ; then
				# Hack for error: execution of %post scriptlet from glibc-core-2.23-alt1.eter1
				docmd rpm -ev glibc-core-2.17 || fatal "Check an error and run epm release-upgrade again"
				docmd epm install apt rpm apt-conf-branch $(get_fix_release_pkg p8) || fatal "Check an error and run epm release-upgrade again"
			fi
			__alt_repofix
			__replace_text_in_alt_repo "/^ *#/! s!\[updates\]![p8]!g"
			docmd epm update || fatal
			if is_installed systemd && is_active_systemd systemd ; then
				docmd epm install systemd || fatal
			fi
			docmd epm upgrade || fatal "Check an error and run epm release-upgrade again"
			;;
		Sisyphus)
			docmd epm update || fatal
			docmd epm install apt rpm librpm7 librpm apt-conf-sisyphus altlinux-release-sisyphus || fatal "Check an error and run again"
			docmd epm upgrade || fatal "Check an error and run epm release-upgrade again"
			;;
		*)
	esac
}

__update_alt_to_next_distro()
{
	local FROMTO=$(echo "$*" | sed -e "s| | to |")
	info
 	case "$*" in
		"p6"|"p6 p7")
			info "Upgrade $DISTRNAME from p6 to p7 ..."
			docmd epm install apt-conf-branch || fatal
			__replace_alt_version_in_repo p6/branch/ p7/branch/
			__update_to_the_distro p7
			docmd epm update-kernel
			info "Done."
			info "Run epm release-upgrade again for update to p8"
			;;
		"p7"|"p7 p8")
			info "Upgrade $DISTRNAME from p7 to p8 ..."
			docmd epm install apt-conf-branch $(get_fix_release_pkg p7) || fatal
			__replace_alt_version_in_repo p7/branch/ p8/branch/
			__update_to_the_distro p8
			docmd epm update-kernel || fatal
			info "Done."
			;;
		"Sisyphus p8")
			info "Downgrade $DISTRNAME from Sisyphus to p8 ..."
			docmd epm install apt-conf-branch || fatal
			__replace_alt_version_in_repo Sisyphus/ p8/branch/
			__replace_text_in_alt_repo "/^ *#/! s!\[alt\]![p8]!g"
			__update_to_the_distro p8
			docmd epm downgrade || fatal
			info "Done."
			;;
		"p8 Sisyphus")
			info "Upgrade $DISTRNAME from p8 to Sisyphus ..."
			docmd epm install apt-conf-branch || fatal
			docmd epm upgrade || fatal
			__replace_alt_version_in_repo p8/branch/ Sisyphus/
			__alt_repofix
			__replace_text_in_alt_repo "/^ *#/! s!\[updates\]![alt]!g"
			__update_to_the_distro Sisyphus
			docmd epm update-kernel || fatal
			info "Done."
			;;
		*)
			warning "Have no idea how to update from $DISTRNAME $DISTRVERSION."
			info "Try run f.i. # epm release-upgrade p8 or # epm release-upgrade Sisyphus"
			info "Also possible you need install altlinux-release-p? package for correct distro version detecting"
			return 1
	esac
}

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

	case $DISTRNAME in
	ALTLinux)
		docmd epm update
		docmd epm install apt rpm

		# 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

		__alt_repofix

		# check forced target
		if [ -n "$pkg_filenames" ] ; then
			[ "$(__wcount $pkg_filenames)" = "1" ] || fatal "Too many args: $pkg_filenames"
		fi

		__update_alt_to_next_distro $DISTRVERSION $pkg_filenames
		return
		;;
	*)
		;;
	esac

	case $PMTYPE in
	apt-rpm)
		#docmd epm update
		info "Have no idea how to upgrade $DISTRNAME"
		;;
	*-dpkg)
		assure_exists do-release-upgrade update-manager-core
		sudocmd do-release-upgrade -d
		;;
	yum-rpm)
		docmd epm install rpm yum
		sudocmd yum clean all
		# TODO
		showcmd rpm -Uvh http://mirror.yandex.ru/fedora/linux/releases/16/Fedora/x86_64/os/Packages/fedora-release-16-1.noarch.rpm
		docmd epm Upgrade
		;;
	dnf-rpm)
		info "Check https://fedoraproject.org/wiki/DNF_system_upgrade for an additional info"
		docmd epm install dnf
		sudocmd dnf clean all
		assure_exists dnf-plugin-system-upgrade
		sudocmd dnf system-upgrade
		local RELEASEVER="$pkg_filenames"
		[ -n "$RELEASEVER" ] || RELEASEVER=$(($DISTRVERSION + 1))
		#[ -n "$RELEASEVER" ] || fatal "Run me with new version"
		info "Upgrate to $DISTRNAME/$RELEASEVER"
		sudocmd dnf system-upgrade download --refresh --releasever=$RELEASEVER
		sudocmd dnf distro-sync --releasever=$RELEASEVER
		info "Run epm autoorphans to remove orphaned packages"
		;;
	urpm-rpm)
		sudocmd urpmi.removemedia -av
		# TODO
		showcmd urpmi.addmedia --distrib http://mirror.yandex.ru/mandriva/devel/2010.2/i586/
		sudocmd urpmi --auto-update --replacefiles
		;;
	zypper-rpm)
		docmd epm repolist
		# TODO
		# 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)
		epm Upgrade
		;;
	conary)
		epm Upgrade
		;;
	emerge)
		epm Upgrade
		;;
	guix)
		sudocmd guix pull --verbose
		;;
	*)
		fatal "Have no suitable command for $PMTYPE"
		;;
	esac

}