#!/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_intallation() {
  [[ -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 recomended, 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 metter
  # 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 upgrade_before_upgrade() {
  continue_or_skip "\nGoing to run 'yum upgrade' before upgrading."
  if [ "$ANSWER" != "S" ] ; then
    yum 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 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/*
}

function unwanted_packages() {
  LAST=$1
  continue_or_skip "\nThere can be some packages which are now orphan, 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 orphan. 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 sucessfullly 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. Official tool is 'fedup'."
  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_intallation; then
  echo "Please install fedora-upgrade package using yum first"
  exit 2
fi

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

if [ 0$FEDORA_VERSION -eq 19 ]; then
  welcome_banner 20

  install_deps
  upgrade_before_upgrade
  rpmconf_before_upgrade
  import_keys

  yum update -q yum
  yum clean -q dbcache rpmdb plugins metadata
  yum --releasever=20 --disableplugin=presto distro-sync
  UPGRADE_FINISHED=2

  install_base

  rpmconf_after_upgrade
  reset_service_priorities
  cleanup_cache
  unwanted_packages 19
  UPGRADE_FINISHED=1
elif [ 0$FEDORA_VERSION -eq 20 ]; then
  welcome_banner 21

  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 21)
  yum --releasever=21 --disableplugin=presto $enable_updates distro-sync
  UPGRADE_FINISHED=2

  choose_fedora_next
  #install_base

  echo "Relabel system"
  restorecon -Rpv / 

  rpmconf_after_upgrade
  #reset_service_priorities
  cleanup_cache
  unwanted_packages 20
  UPGRADE_FINISHED=1
elif [ 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

  choose_fedora_next
  #install_base

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

  install_deps
  rpmconf_before_upgrade

  yum install fedora-repos-rawhide yum-utils
  yum-config-manager --disable fedora updates updates-testing
  yum-config-manager --enable rawhide
  yum update -q yum
  yum clean -q dbcache rpmdb plugins metadata
  yum --releasever=rawhide --disableplugin=presto distro-sync --nogpgcheck
  UPGRADE_FINISHED=2

  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
