#!/bin/bash

#Preupgrade Assistant performs system upgradability assessment
#and gathers information required for successful operating system upgrade.
#Copyright (C) 2013 Red Hat Inc.
#Ondrej Vasik <ovasik@redhat.com>, Petr Stodulka <pstodulk@redhat.com>
#
#This program is free software: you can redistribute it and/or modify
#it under the terms of the GNU 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 General Public License for more details.
#
#You should have received a copy of the GNU General Public License
#along with this program.  If not, see <http://www.gnu.org/licenses/>.
. /usr/share/preupgrade/common.sh
check_rpm_to "" ""
#END GENERATED SECTION

# is created/copied by ReplacedPackages
_DST_NOAUTO_POSTSCRIPT="$NOAUTO_POSTUPGRADE_D/install_rpmlist.sh"
FILENAME_BASIS="RHRHEL7rpmlist_obsoleted"

get_repo_id() {
  grep -E "^[^-]*-$1;" "$COMMON_DIR/default_nreponames" | cut -d ";" -f3
}

[ ! -f "$VALUE_RPM_RHSIGNED" ] || [ ! -r "$COMMON_DIR" ] && {
  log_error "Signed RPM list or common file directory missing. Contact the support."
  exit $RESULT_ERROR
}

ObsoletedPkgs=$(mktemp .obsoletedpkgsXXX --tmpdir=/tmp)
MoveObsoletedPkgs=$(mktemp .mvreplacedpkgsXXX --tmpdir=/tmp)
NotBasePkgs=$(mktemp .notbasepkgsXXX --tmpdir=/tmp)
cat $COMMON_DIR/default*_*obsoleted* | cut -f1,3 -d' ' | tr ' ' '|' | sort | uniq >"$ObsoletedPkgs"
grep -Hr "..*" $COMMON_DIR/default*_moved-obsoleted_?* | sed -r "s|^$COMMON_DIR/([^:]+):([^[:space:]]*).*$|\2 \1|" | sort | uniq >"$MoveObsoletedPkgs"
grep -Hr "..*" $COMMON_DIR/default-*_obsoleted | sed -r "s|^$COMMON_DIR/([^:]+):([^[:space:]]*).*$|\2 \1|" | sort | uniq >"$NotBasePkgs"



[ ! -r "$ObsoletedPkgs" ] \
      || [ ! -r "$MoveObsoletedPkgs" ] \
      || [ ! -r "$NotBasePkgs" ] && {
  log_error "Package content lists missing.  Contact the support."
  rm -f "$ObsoletedPkgs" "$MoveObsoletedPkgs" "$NotBasePkgs"
  exit $RESULT_ERROR
}

found=0
other_repositories=""
rm -f solution.txt "$KICKSTART_DIR/${FILENAME_BASIS}"*

echo \
"Some packages became obsolete between Red Hat Enterprise Linux 6 and Red Hat Enterprise Linux 7.
Red Hat provides alternatives for them, but these
alternatives may not be 100% compatible. For this reason,
the packages are not replaced automatically.

For some of the obsolete packages you will get the
incompatibilities list from separate preupgrade
modules and you can adjust your migration or upgrade
as required.

Sometimes, the functionality of a package requires
more than one new package to achieve the same
functionality.

Note: All packages from the debug repositories
are skipped and Red Hat recommends that you remove
them before upgrade.

The following packages are obsolete and replaced by
new ones:" >solution.txt

#Check for package obsolete type replacements in packages
# - packages from *debug repositories aren't important - ignore them (at least for now)
while read line
do
  orig_pkg=$(echo "$line" | cut -d'|' -f1)
  new_pkgs=$(echo "$line" | cut -d'|' -f2)
  #skip non-rh and unavailable packages
  is_pkg_installed "$orig_pkg" && is_dist_native $orig_pkg || continue

  is_moved=0
  is_not_base=0
  filename_suffix=""
  msg_channel=""
  req_pkgs=""
  msg_req=""
  func_log_risk=log_medium_risk

  for k in $(rpm -q --whatrequires $orig_pkg | grep -v "^no package requires" \
    | rev | cut -d'-' -f3- | rev | sort | uniq)
  do
    is_pkg_installed "$k" || continue
    is_dist_native "$k" || req_pkgs="$req_pkgs$k "
  done
  [ -n "$req_pkgs" ] && {
    req_pkgs="${req_pkgs% }"
    msg_req=" (required by Non Red Hat signed package(s):$req_pkgs)"
    func_log_risk=log_high_risk
  }
  channel="$(grep "^$orig_pkg[[:space:]]" "$MoveObsoletedPkgs" | rev | cut -d "_" -f 1 | rev)"

  if [ -n "$channel" ]; then
    [[ "$channel" =~ debug$ ]] && continue
    is_moved=1
  else
    channel=$(grep "^$orig_pkg[[:space:]]" "$NotBasePkgs" | sed -r "s/^.*default-(.*)_obsoleted$/\1/" )
    [[ "$channel" =~ debug$ ]] && continue
    [ -n "$channel" ] && is_not_base=1
  fi


  if [ $is_moved -eq 1 ] || [ $is_not_base -eq 1 ]; then
    # [ "$channel" == "optional" ] && optional=1 # unused variable
    other_repositories="${other_repositories}$channel "
    msg_channel=" ($channel channel in RHEL 7)"
  fi

  # logs / prints
  [ -n "$msg_req" ] && $func_log_risk "The package ${orig_pkg}$msg_req was removed between Red Hat Enterprise Linux 6 and Red Hat Enterprise Linux 7"
  [ $is_moved -eq 1 ] && $func_log_risk "The partial replacement for $orig_pkg moved to the $channel channel between Red Hat Enterprise Linux 6 and Red Hat Enterprise Linux 7."
  [ $is_not_base -eq 1 ] && $func_log_risk "The partial replacement for $orig_pkg is available in the $channel channel on Red Hat Enterprise Linux 7."
  echo "${orig_pkg}$msg_req was replaced by ${new_pkgs}$msg_channel" >>solution.txt
  {
    # store data to kickstart files
    [ -n "$msg_req" ] && filename_suffix="${filename_suffix}-required"
    [ -n "$channel" ] && filename_suffix="${filename_suffix}-notbase"
    echo "${orig_pkg}|$req_pkgs|$(echo $new_pkgs | tr ',' ' ')|$(get_repo_id $channel)" >> "$KICKSTART_DIR/${FILENAME_BASIS}${filename_suffix}"
  }
  found=1
done < "$ObsoletedPkgs"
rm -f "$ObsoletedPkgs" "$MoveObsoletedPkgs" "$NotBasePkgs"

# transform my-repo-names to known names
[ -n "$other_repositories" ] && [ $MIGRATE -eq 1 ] && {
  regexp_part="$(echo "${other_repositories}" | tr ' ' '|' | sed -e "s/^|*//" -e "s/|*$//" | sort | uniq )"
  migrate_repos="$(grep -E "^[^-]*(-($regexp_part))?;" < "$COMMON_DIR/default_nreponames")"
  repos_texts="$(echo "$migrate_repos" | cut -d ";" -f4)"

  echo "
One or more replacement packages are available only in other repositories.
If you want to install them later, you will need to attach subscriptions that provide:
$repos_texts

Then enable any equivalent repositories (if they are disabled) and install any needed packages.
For this purpose, run a prepared script:
$_DST_NOAUTO_POSTSCRIPT <path/to/pkglist-file>

which will install the available packages listed in the file.
See ${KICKSTART_README} for details on 'pkglist' files.
" >>solution.txt
}

# it looks better sorted
for file in $(ls $KICKSTART_DIR/${FILENAME_BASIS}*); do
  # add header line
  echo "# old-package|required-by-pkgs|obsoleted-by-pkgs|repo-id" > ${file}.bak
  cat "$file" | sort | uniq >> ${file}.bak
  mv ${file}.bak $file
done


  echo -n "
 * ${FILENAME_BASIS} - This file contains all Red Hat Enterprise Linux 6 packages which were replaced in Red Hat Enterprise Linux 7 by a not 100% compatible alternative and are a part of the base channel. Direct dependency from the packages not signed by Red Hat was not discovered.
 * ${FILENAME_BASIS}-required - Similar to ${FILENAME_BASIS}, but in addition are required by the packages not signed by Red Hat. As some of your packages depend on it, check the changes in detail.
 * ${FILENAME_BASIS}-notbase - Similar to ${FILENAME_BASIS}, but these packages are not a part of the base channel on Red Hat Enterprise Linux 7. Register the new machine and attach subscriptions with the correct repositories if you want to install them.
 * ${FILENAME_BASIS}-required-notbase - Similar to ${FILENAME_BASIS}-required and ${FILENAME_BASIS}-notbase - packages are required by the packages not signed by Red Hat and are not a part of the base channel.
" >> "$KICKSTART_README"

echo \
"
If a package not signed by Red Hat requires these packages, you may need to check if the alternative solution provided by Red Hat works for you. You may need to get the missing package from a source other than the Red Hat Enterprise Linux repositories.

You will need to install these new packages yourself after the assessment, as Red Hat cannot assess the suitablility of the replacements for your workload." >>solution.txt

[ $found -eq 1 ] && log_medium_risk "\
Some packages installed on the system were removed between Red Hat Enterprise Linux 6 and Red Hat Enterprise Linux 7. This may break the functionality of the packages depending on them." && exit $RESULT_FAIL

rm -f solution.txt && touch solution.txt

exit $RESULT_PASS
