#!/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>
#
#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 "" ""
COMPONENT="distribution"
#END GENERATED SECTION

ReplacedPkgs=$(mktemp .replacedpkgsXXX --tmpdir=/tmp)
cat /root/preupgrade/RHEL6_7/common/default*_replaced* | grep -v "\.so" | cut -f1,3 -d' ' | tr ' ' '|' | sort | uniq >"$ReplacedPkgs"

[ ! -f "$VALUE_RPM_RHSIGNED" ] && \
  log_error generic Common content part is missing! &&
  exit $RESULT_ERROR

[ ! -r "$ReplacedPkgs" ] && \
  log_error generic Part of the content is missing! && \
  exit $RESULT_ERROR

#Following two are more packaging troubles and should
#be empty once everything is resolved.
[ ! -r BothMissing ] && \
  log_error generic Part of the content is missing! && \
  exit $RESULT_ERROR

[ ! -r ProvidesonlyMissing ] && \
  log_error generic Part of the content is missing! && \
  exit $RESULT_ERROR

found=0
notprovided=0
rm -f solution.txt
echo \
"Some of the packages were replaced between RHEL 6 and RHEL 7. This means
package with different name provides 100% compatible functionality, so we
can replace them automatically in the package set.
For some of the replacements provides were not handled by the packages,
therefore preupgrade asistant migrates them after the upgrade if necessary.

Following packages were replaced:" >solution.txt

#Check for package replacements in the packages
while read i
do
  l=$(echo $i | cut -d'|' -f1 )
  m=$(echo $i | cut -d'|' -f2 )
  #skip non-rh and unavailable packages
  grep -e "^$l[[:space:]]" "$VALUE_RPM_RHSIGNED" >/dev/null || continue
  j=" (required by NonRH signed package(s):"
  for k in $(rpm -q --whatrequires $l | grep -v "^no package requires" | \
   rev | cut -d'-' -f3- | rev )
  do
    grep -e "^$k[[:space:]]" "$VALUE_RPM_RHSIGNED" >/dev/null || j="$j$k "
  done
  j="$j)"
  [ "$j" == " (required by NonRH signed package(s):)" ] && j=""
  [ -n "$j" ] && log_slight_risk "Package $l $j replaced between RHEL 6 and RHEL 7"
  echo "$l$j was replaced by $m" >>solution.txt
  found=1
done < "$ReplacedPkgs"

echo \
"
If some NonRH signed package requires these packages, you still may want
to monitor them closely. Although the replacement should be compatible,
it can have some minor differences expectable even in the case of common
application lifecycle." >>solution.txt

rm -f "$VALUE_TMP_PREUPGRADE/kickstart/RHRHEL7rpmlist" >/dev/null
removeme=""
for i in $(cat "$VALUE_RPM_RHSIGNED" | cut -f1)
do
  #Was the package obsoleted/removed? Skip it...
  grep " $i " Removed >/dev/null && continue
  echo $i >>"$VALUE_TMP_PREUPGRADE/kickstart/RHRHEL7rpmlist"
done
while read i
do
  l=$(echo $i | cut -d'|' -f1)
  m=$(echo $i | cut -d'|' -f2)
  sed -i -e "s/^$l$/$m/g" "$VALUE_TMP_PREUPGRADE/kickstart/RHRHEL7rpmlist" 2>/dev/null
  grep "^$l[[:space:]]" "$VALUE_RPM_RHSIGNED" && removeme="$removeme $l"
done < "$ReplacedPkgs"
rm -f "$ReplacedPkgs"

#Packages not handled properly according to http://fedoraproject.org/wiki/Packaging:Guidelines#Renaming.2FReplacing_Existing_Packages ... Package should have both obsoletes and provides, otherwise it can cause troubles during the update.
l=""
for i in $(cat "$VALUE_RPM_RHSIGNED" | cut -f1)
do
  #For now, handle them same way, we want them installed...
  m=$(grep "^$i|" ProvidesonlyMissing)
  [ -n $m ] || m=$(grep "^$i|" BothMissing)
  [ -z $m ] && continue
  replacement=$(echo $m | cut -d'|' -f2)
  notprovided=1
  log_medium_risk "Package $i not provided by its replacement $replacement. In-place upgrade might not work properly, will be finished by postupgrade script!"
  l="$l $m"
done

#Create a postupgrade script which ensures that the replacement packages are installed
mkdir $VALUE_TMP_PREUPGRADE/postupgrade.d/replacedpkg 2>/dev/null
cat <<\EOF >$VALUE_TMP_PREUPGRADE/postupgrade.d/replacedpkg/fixreplaced.sh
#!/bin/bash
#Generated file, part of preupgrade-assistant content, should not be used
#separately, see preupgrade-assistant license for licensing details
#Do the upgrade for the packages with potentially broken obsoletes/provides
for i in $(echo "SEDMEHERE")
do
  old="$(echo $i | cut -d'|' -f1)"
  new="$(echo $i | cut -d'|' -f2 | tr ',' ' ')"
  #we want to remove the old package if still present
  rpm -q $old 2>/dev/null >/dev/null && {
  #Store the modified files as .preupsave
  for j in $(rpm -V $old | rev | cut -d' ' -f1 | rev | grep -v "(replaced)")
  do
    cp $j $j.preupsave
    echo "Storing modified file $j from $old as $j.preupsave"
  done
  #deinstall the old package
  rpm -e $old --nodeps
  echo "Package $old uninstalled"
  }
  #do we already have all new installed? Skip it...
  rpm -q $new >/dev/null && continue
  yum install -y $new
  rpm -q $new 2>/dev/null >/dev/null && echo "Package(s) $new installed" && continue
  #when we are here, installation got wrong and we should warn the user.
  echo  "Installation of package(s) $new failed, you need to install it manually!"
done
for old in $(echo "SEDME2HERE")
do
  #we want to remove the old package if still present
  rpm -q $old 2>/dev/null >/dev/null && {
  #Store the modified files as .preupsave
  for j in $(rpm -V $old | rev | cut -d' ' -f1 | rev | grep -v "(replaced)")
  do
    cp $j $j.preupsave
    echo "Storing modified file $j from $old as $j.preupsave"
  done
  #deinstall the old package
  rpm -e $old --nodeps
  echo "Package $old uninstalled"
  }
done
EOF
sed -i -e "s/SEDMEHERE/$l/" $VALUE_TMP_PREUPGRADE/postupgrade.d/replacedpkg/fixreplaced.sh
sed -i -e "s/SEDME2HERE/$removeme/" $VALUE_TMP_PREUPGRADE/postupgrade.d/replacedpkg/fixreplaced.sh
chmod +x $VALUE_TMP_PREUPGRADE/postupgrade.d/replacedpkg/fixreplaced.sh

#TBD Do the comps groups replacements (when someone had full yum group on RHEL 6, assume he wants it on RHEL 7 as well, rather than having only limited set of packages)

#remove the duplicates from rhel7rpmlist caused by replacements
cat "$VALUE_TMP_PREUPGRADE/kickstart/RHRHEL7rpmlist" | sort | uniq > "$VALUE_TMP_PREUPGRADE/kickstart/RHRHEL7rpmlist.bak"
mv "$VALUE_TMP_PREUPGRADE/kickstart/RHRHEL7rpmlist.bak"  "$VALUE_TMP_PREUPGRADE/kickstart/RHRHEL7rpmlist"

statuscode=$RESULT_INFORMATIONAL

[ $notprovided -eq 1 ] && statuscode=$RESULT_FIXED

[ $found -eq 1 ] && log_slight_risk "\
We detected some packages installed on the system changed their name between RHEL 6 and RHEL 7. Although they should be compatible, monitoring after the update is recommended." && exit $statuscode

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

exit $RESULT_PASS
