#!/bin/sh
#(c) Copyright Barry Kauler, 31 January 2017. Licence: GPL v3 (/usr/share/doc/legal).
#called from /init, passed params are $WKG_DRV, $WKG_DEV
#./rollback.flg has params <version>,<date> which is version to roll back to 
#(default is keep current version), and date of rw snapshot (default is keep 
#current rw session). Both fields are optional. Special case "*,erase" means
#wipe the rw layer (.session folder).
#Special case ",last" means go back to last saved session (or rw-<current-version>.sfs).

WKG_DRV=$1 #ex: sda
WKG_DEV=$2 #ex: sda2
. /BOOT_SPECS #has BOOT_DISKID, BOOT_PARTNUM, BOOT_FS, BOOT_DIR, WKG_DISKID, WKG_PARTNUM, WKG_FS, WKG_DIR
. /mnt/${WKG_DEV}/${WKG_DIR}.session/etc/DISTRO_SPECS #note, 'init' always copies this up. 170521 fix path.

err_exit() {
 echo -e "\\033[1;31mERROR: ${1}\\033[0;39m" #red
 exit 1
}

backVER="$(cat /mnt/${WKG_DEV}/${WKG_DIR}.session/.rollback.flg | cut -f 1 -d ',')"
backDATE="$(cat /mnt/${WKG_DEV}/${WKG_DIR}.session/.rollback.flg | cut -f 2 -d ',')"
rm -f /mnt/${WKG_DEV}/${WKG_DIR}.session/.rollback.flg

case "$backDATE" in
 erase)
  echo -e "\\033[1;35m$(LANG=${wkgLANG} gettext 'Erasing current working session')\\033[0;39m" #purple
  echo "  $(LANG=${wkgLANG} gettext '(erasing the read-write layer)')"
 ;;
 last)
  echo -e "\\033[1;35m$(LANG=${wkgLANG} gettext 'Rolling read-write layer back to last saved session')\\033[0;39m" #purple
 ;;
 *)
  echo -e "\\033[1;35m$(LANG=${wkgLANG} gettext 'Rolling back to an earlier version or snapshot')\\033[0;39m" #purple
  echo "  $(LANG=${wkgLANG} gettext 'Current version:') ${DISTRO_VERSION}. $(LANG=${wkgLANG} gettext 'Back to:') ${backVER}, $(LANG=${wkgLANG} gettext 'snapshot:') ${backDATE}"
 ;;
esac

#want to read the saved versions in 'repository' folder, and sort them by version-number.
#busybox sort does not have that option (sort in coreutils has '-V'), so improvise...
VERS="$(ls -l /mnt/${WKG_DEV}/${WKG_DIR}repository/easy-* | rev | cut -f 1 -d '-' | rev)"
#refer: http://stackoverflow.com/questions/4493205/unix-sort-of-version-numbers
#sortedVERS="$(echo "$VERS" | sort -t. -k 1,1n -k 2,2n -k 3,3n -k 4,4n)" #lowest to highest.
#revsortedVERS="$(echo "$VERS" | sort -t. -k 1,1nr -k 2,2nr -k 3,3nr -k 4,4nr)" #highest to lowest.
#...turns out, don't need this, but leave it here, it is so cool.

#also read snapshots, if any...
SNAPS="$(ls -l /mnt/${WKG_DEV}/${WKG_DIR}repository/easy-${DISTRO_VERSION}/rw-* | rev | cut -f 1 -d '-' | rev)"
sortedSNAPS="$(echo "$SNAPS" | sort -t. -k 1,1n -k 2,2n -k 3,3n -k 4,4n)" #lowest to highest.
#revsortedSNAPS="$(echo "$SNAPS" | sort -t. -k 1,1nr -k 2,2nr -k 3,3nr -k 4,4nr)" #highest to lowest.

if [ "$backDATE" == "last" ];then
 #note, entire prev-version session is saved as rw-<current-version>.sfs
 backDATE="$(echo "$sortedSNAPS" | grep -v "^${DISTRO_VERSION}$" | tail -n 1)"
 if [ ! "$backDATE" ];then
  backDATE="${DISTRO_VERSION}"
  if [ ! -f /mnt/${WKG_DEV}/${WKG_DIR}repository/easy-${DISTRO_VERSION}/rw-${backDATE}.sfs ];then
   echo -e "  \\033[1;31m$(LANG=${wkgLANG} gettext 'Cannot rollback, no saved session')\\033[0;39m" #red
   backDATE=""
  fi
 fi
fi

if [ "$backDATE" ];then
 case "$backDATE" in
  erase)
   echo "  $(LANG=${wkgLANG} gettext 'Erasing working session...')"
   rm -rf /mnt/${WKG_DEV}/${WKG_DIR}.session/*
   sync
  ;;
  *)
   echo "  $(LANG=${wkgLANG} gettext 'Rolling working session back...')"
   #170529 do not flag error if no rw-${backDATE}.sfs, just erase...
   #[ ! -f /mnt/${WKG_DEV}/${WKG_DIR}repository/easy-${backVER}/rw-${backDATE}.sfs ] && err_exit "$(LANG=${wkgLANG} gettext 'Missing snapshot:') /mnt/${WKG_DEV}/${WKG_DIR}repository/easy-${backVER}/rw-${backDATE}.sfs"
   rm -rf /mnt/${WKG_DEV}/${WKG_DIR}.session/*
   if [ -f /mnt/${WKG_DEV}/${WKG_DIR}repository/easy-${backVER}/rw-${backDATE}.sfs ];then #170529
    mkdir snapmnt
    mount -t squashfs -o loop,noatime /mnt/${WKG_DEV}/${WKG_DIR}repository/easy-${backVER}/rw-${backDATE}.sfs snapmnt
    [ $? -ne 0 ] && err_exit "$(LANG=${wkgLANG} gettext 'Failed to mount snapshot:') rw-${backDATE}.sfs"
    cp -a snapmnt/* /mnt/${WKG_DEV}/${WKG_DIR}.session/
    sync
    umount snapmnt
   fi
  ;;
 esac
 echo "  $(LANG=${wkgLANG} gettext '...done')"
fi

[ "$backVER" == "$DISTRO_VERSION" -o "$backVER" == "" ] && exit 0

#rolling back to earlier version, need to replace files in boot partition...
#note, BOOT_DIR, WKG_DIR already have a trailing slash
#note, 'version-control' script has already copied vmlinuz, checking here as precaution.
echo -n "  $(LANG=${wkgLANG} gettext 'Rolling back:')"
LINUZ=0
cmp -s /mnt/${WKG_DEV}/${WKG_DIR}repository/easy-${DISTRO_VERSION}/vmlinuz /mnt/${BOOT_DEV}/${BOOT_DIR}vmlinuz
[ $? -ne 0 ] && LINUZ=1
if [ $LINUZ -eq 1 ];then
 echo -n " vmlinuz"
 cp -a -f /mnt/${WKG_DEV}/${WKG_DIR}repository/easy-${DISTRO_VERSION}/vmlinuz /mnt/${BOOT_DEV}/${BOOT_DIR}
fi
echo -n " initrd.q"
cp -a -f /mnt/${WKG_DEV}/${WKG_DIR}repository/easy-${DISTRO_VERSION}/initrd.q /mnt/${BOOT_DEV}/${BOOT_DIR}
echo " q.sfs"
cp -a -f /mnt/${WKG_DEV}/${WKG_DIR}repository/easy-${DISTRO_VERSION}/q.sfs /mnt/${BOOT_DEV}/${BOOT_DIR}
#170524 also roll back .session folder...
rm -rf /mnt/${WKG_DEV}/${WKG_DIR}.session/*
if [ -f /mnt/${WKG_DEV}/${WKG_DIR}repository/easy-${backVER}/rw-${backVER}.sfs ];then #this will exist.
 mkdir -p snapmnt
 mount -t squashfs -o loop,noatime /mnt/${WKG_DEV}/${WKG_DIR}repository/easy-${backVER}/rw-${backVER}.sfs snapmnt
 [ $? -ne 0 ] && err_exit "$(LANG=${wkgLANG} gettext 'Failed to mount snapshot:') rw-${backVER}.sfs"
 cp -a snapmnt/* /mnt/${WKG_DEV}/${WKG_DIR}.session/
 sync
 umount snapmnt
fi
sync
#if vmlinuz has changed, will need to reboot...
if [ $LINUZ -eq 1 ];then
 echo -n "  $(LANG=${wkgLANG} gettext 'The kernel has changed, a reboot will occur in 10 seconds...')"
 sync
 umount /mnt/$BOOT_DEV
 umount /mnt/$WKG_DEV 2>/dev/null #boot and wkg could be the same.
 sleep 10
 reboot
fi
echo "  $(LANG=${wkgLANG} gettext '...done')"

exit 0
###end###
