#!/bin/bash
# vim: sw=3:ts=3:et
set -e

FEDORA_VERSION=$(rpm -q --qf '%{version}' fedora-release)
TARGET_VERSION=$((FEDORA_VERSION + 1))
UPGRADE_FINISHED=0

function check_installation() {
  [[ -e /usr/sbin/fedora-upgrade ]]
}

function pause() {
   # clear the stdin buffer and pause with question
   read -t 1 -n 10000 discard || [ $? -gt 128 ]
   read -p "Hit Enter to continue or Ctrl + C to cancel."
}

function continue_or_skip() {
   read -t 1 -n 10000 discard || [ $? -gt 128 ]
   echo -e $1
   echo "This step is highly recommended, but can be safely skipped."
   ANSWER='XXX'
   while [ "$ANSWER" != "" -a "$ANSWER" != "S" ] ; do
     read -p "Hit Enter to continue, Ctrl + C to cancel or S + Enter to skip. " ANSWER
     ANSWER=$(echo $ANSWER | tr "[:lower:]" "[:upper:]")
   done
}

function install_deps() {
  # TODO add -q to all yum and create some kind of progress meter
  # but now be verbose
  rpm -q rpmconf >/dev/null || yum install -y rpmconf
  rpm -q yum-utils >/dev/null || yum install -y yum-utils
}

function dnf_install_deps() {
  # TODO add -q to all dnf and create some kind of progress meter
  # but now be verbose
  rpm -q rpmconf >/dev/null || dnf install -y rpmconf
  rpm -q dnf-plugins-core >/dev/null || dnf install -y dnf-plugins-core
}

function upgrade_before_upgrade() {
  continue_or_skip "\nGoing to run 'yum upgrade' before upgrading."
  if [ "$ANSWER" != "S" ] ; then
    yum upgrade
  fi
}

function dnf_upgrade_before_upgrade() {
  continue_or_skip "\nGoing to run 'dnf upgrade' before upgrading."
  if [ "$ANSWER" != "S" ] ; then
    dnf upgrade
  fi
}

function rpmconf_before_upgrade() {
  continue_or_skip "\nGoing to resolve old .rpmsave and .rpmnew files before upgrading."
  if [ "$ANSWER" != "S" ] ; then
    rpmconf -fvimdiff -a
  fi
}

function import_keys() {
  rpm --import /usr/share/fedora-upgrade/keys/RPM-GPG-KEY-fedora-$TARGET_VERSION-primary
  if [ -f /etc/yum.repos.d/rpmfusion-free.repo -a -e /usr/share/fedora-upgrade/keys/RPM-GPG-KEY-rpmfusion-free-fedora-$TARGET_VERSION ]; then
    rpm --import /usr/share/fedora-upgrade/keys/RPM-GPG-KEY-rpmfusion-free-fedora-$TARGET_VERSION
  fi
  if [ -f /etc/yum.repos.d/rpmfusion-nonfree.repo -a -e /usr/share/fedora-upgrade/keys/RPM-GPG-KEY-rpmfusion-nonfree-fedora-$TARGET_VERSION ]; then
    rpm --import /usr/share/fedora-upgrade/keys/RPM-GPG-KEY-rpmfusion-nonfree-fedora-$TARGET_VERSION
  fi
}

function install_base() {
  continue_or_skip "\nGoing to install missing packages from group 'Minimal Install'"
  if [ "$ANSWER" != "S" ] ; then
    yum groupupdate 'Minimal Install'
  fi
}

function dnf_install_base() {
  continue_or_skip "\nGoing to install missing packages from group 'Minimal Install'"
  if [ "$ANSWER" != "S" ] ; then
    dnf groupupdate 'Minimal Install'
  fi
}

function rpmconf_after_upgrade() {
  continue_or_skip "\nGoing to resolve .rpmsave and .rpmnew files after upgrade."
  if [ "$ANSWER" != "S" ] ; then
    rpmconf -fvimdiff -a
    rpmconf --clean
  fi
}

function reset_service_priorities() {
  continue_or_skip "\nGoing to reset priorities of services."
  if [ "$ANSWER" != "S" ] ; then
    ( cd /etc/rc.d/init.d;
      for f in *; do
        [ -x $f ] && /sbin/chkconfig $f resetpriorities || :
      done # TODO - the same for systemd unit files
    )
  fi
}

function cleanup_cache() {
  rm -rf /var/cache/yum/* /var/cache/dnf/*
}

function unwanted_packages() {
  LAST=$1
  continue_or_skip "\nThere may be some packages which are now orphaned, do you want to see them?"
  RESULT=0
  for i in $(seq 10 $LAST); do
    rpm -qa | grep fc$i && RESULT=1
  done
  if [ 0$RESULT -eq 1 ]; then
    echo "These packages are very probably orphaned. You may want to remove them."
  fi
}

function is_prerelease() {
  # will print string "--enablerepo=updates-testing" if this is prerelease, "" otherwise
  local RELEASE=$1
  if yumdownloader --disablerepo=* --enablerepo=fedora --releasever=$RELEASE fedora-release --urls | tail -n 1 | wget -q -i - -O - | rpm2cpio | cpio -i --quiet --to-stdout - ./etc/yum.repos.d/fedora-updates-testing.repo | grep 'enabled=1' >/dev/null; then
    echo "--enablerepo=updates-testing"
  else
    echo ""
  fi
}

function print_exit_banner() {
  if [ $UPGRADE_FINISHED -eq 1 ]; then
    echo
    echo You successfully upgraded to Fedora $TARGET_VERSION
    echo Reboot is strongly suggested.
    exit 0
  elif [ $UPGRADE_FINISHED -eq 0 ]; then
    echo
    echo Upgrade to Fedora $TARGET_VERSION was not finished!
    echo You can safely re-run fedora-upgrade again to start over.
    exit 1
  else
    echo
    echo Upgrade to Fedora $TARGET_VERSION was not finished!
    echo Finish steps manually according to documentation on the wiki:
    echo 'http://fedoraproject.org/wiki/Upgrading_Fedora_using_yum#5._Make_sure_Fedora_is_upgraded'
    exit 2
  fi
}

function welcome_banner() {
  echo "Going to upgrade your Fedora to version $1."
  echo "You may want to read Release Notes:"
  echo "  http://docs.fedoraproject.org/release-notes/"
  echo "Warning: This is unofficial upgrade tool. For official tool see:"
  echo "         https://fedoraproject.org/wiki/Upgrading"
  echo "         While author of fedora-upgrade thinks fedora-upgrade is better, it is"
  echo "         not officially tested by FedoraQA."
  pause
}

function choose_fedora_next() {
  echo "Fedora now split into several products:"
  echo "  * Cloud"
  echo "  * Server"
  echo "  * Workstation"
  echo "And there is choice to stay non-productized:"
  echo "  * Nonproduct"

  read -t 1 -n 10000 discard || [ $? -gt 128 ]
  echo -e $1
  ANSWER='XXX'
  while [ "$ANSWER" != "cloud" -a "$ANSWER" != "server" -a "$ANSWER" != "workstation" -a "$ANSWER" != "nonproduct" ] ; do
    read -p "What is your option? (cloud/server/workstation/nonproduct)  " ANSWER
    ANSWER=$(echo $ANSWER | tr "[:upper:]" "[:lower:]")
  done
  if [ "$ANSWER" != "nonproduct" ] ; then
    # would be nice to use:
    # yum swap -- remove fedora-release-workstation -- install fedora-release-server
    # but it does not work BZ 1167194
    if [ "$ANSWER" != "cloud" ] ; then
      rpm -e --nodeps firewalld-config-standard >/dev/null || :
    fi
    rpm -q fedora-release-nonproduct >/dev/null && rpm -e fedora-release-nonproduct
    if [ "$ANSWER" != "cloud" ] ; then
      yum install -y firewalld-config-$ANSWER firewalld-config-$ANSWER
    fi
  fi
  yum install -y fedora-release-$ANSWER
}

if ! check_installation; then
  echo "Please install fedora-upgrade package using yum first"
  exit 2
fi

# make obvious ending for inexperienced users
trap "print_exit_banner" SIGHUP SIGINT SIGTERM

if [ 0$FEDORA_VERSION -eq 21 ]; then
  welcome_banner 22

  install_deps
  upgrade_before_upgrade
  rpmconf_before_upgrade
  import_keys

  yum update -q yum
  yum clean -q dbcache rpmdb plugins metadata
  enable_updates=$(is_prerelease 22)
  yum --releasever=22 --disableplugin=presto $enable_updates distro-sync
  UPGRADE_FINISHED=2

  dnf_install_base

  rpmconf_after_upgrade
  #reset_service_priorities
  cleanup_cache
  unwanted_packages 21
  UPGRADE_FINISHED=1
elif [ 0$FEDORA_VERSION -eq 22 ]; then
  welcome_banner 23

  dnf_install_deps
  dnf_upgrade_before_upgrade
  rpmconf_before_upgrade
  import_keys

  dnf install -y -q dnf-plugins-core
  dnf clean -q dbcache plugins metadata
  enable_updates=$(is_prerelease 23)
  dnf --releasever=23 --setopt=deltarpm=false $enable_updates distro-sync
  UPGRADE_FINISHED=2

  dnf_install_base

  rpmconf_after_upgrade
  reset_service_priorities
  cleanup_cache
  UPGRADE_FINISHED=1
elif [ 0$FEDORA_VERSION -eq 23 ]; then
  echo "Going to upgrade your Fedora to rawhide."
  echo "Fedora $TARGET_VERSION is currently under development."
  echo "Are you sure?"
  pause

  dnf_install_deps
  rpmconf_before_upgrade

  dnf install fedora-repos-rawhide dnf-plugins-core
  dnf config-manager --set-disabled fedora updates updates-testing
  dnf config-manager --set-enabled rawhide
  dnf upgrade -q dnf
  dnf clean -q dbcache plugins metadata
  dnf --releasever=rawhide --setopt=deltarpm=false distro-sync --nogpgcheck
  UPGRADE_FINISHED=2

  dnf_install_base

  rpmconf_after_upgrade
  reset_service_priorities
  cleanup_cache
  UPGRADE_FINISHED=1
else
  echo Upgrading from version $FEDORA_VERSION is not supported.
  exit 1
fi
print_exit_banner
