#!/bin/sh
set -e

# Copyright (C) 2006,2007,2008,2009,2010  Free Software Foundation, Inc.
#
# GRUB 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.
#
# GRUB 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 GRUB.  If not, see <http://www.gnu.org/licenses/>.

grub_mkconfig="/usr/sbin/grub2-mkconfig"
grub_mkrelpath="/usr/bin/grub2-mkrelpath"
grub_script_check="/usr/bin/grub2-script-check"
grub_setting="/etc/default/grub"
grub_cfg="/boot/grub2/grub.cfg"
grub_snapshot_cfg="/boot/grub2/snapshot_submenu.cfg"

snapper_snapshot_path="/.snapshots"
snapshot_submenu_name="grub-snapshot.cfg"
snapper_snapshots_cfg="${snapper_snapshot_path}/${snapshot_submenu_name}"

# add hotkeys for s390.  (bnc#885668)
hotkey=
incr_hotkey()
{
  [ -n "$hotkey" ] || return
  expr $hotkey + 1
}
print_hotkey()
{
  keys="123456789abdfgijklmnoprstuvwyz"
  if [ -z "$hotkey" ]||[ $hotkey -eq 0 ]||[ $hotkey -gt 30 ]; then
    return
  fi
  echo "--hotkey=$(expr substr $keys $hotkey 1)"
}


snapshot_submenu () {

  s_dir="$1"

  snapshot="${s_dir}/snapshot"
  num="`basename $s_dir`"
  
  # bnc#864842 Important snapshots are not marked as such in grub2 menu
  # the format is "important distribution version (kernel_version, timestamp, pre/post)"
  date=`xmllint --xpath '/snapshot/date/text()' "${s_dir}/info.xml" || echo ""`
  date=`echo $date | sed 's/\(.*\) \(.*\):.*/\1T\2/'`
  important=`xmllint --xpath "/snapshot/userdata[key='important']/value/text()" "${s_dir}/info.xml" 2>/dev/null || echo ""`
  stype=`xmllint --xpath '/snapshot/type/text()' "${s_dir}/info.xml" || echo ""`
  kernel_ver=`readlink ${snapshot}/boot/vmlinuz | sed -e 's/^vmlinuz-//' -e 's/-default$//'` 
  if [ -z "$kernel_ver" -a -L ${snapshot}/boot/image ]; then
    kernel_ver=`readlink ${snapshot}/boot/image | sed -e 's/^image-//' -e 's/-default$//'`
  fi
  eval `cat ${snapshot}/etc/os-release` 
  test "$important" = "yes" && important="*" || important=" "
  test "$stype" = "single" && stype=""

  test -z "$stype" || stype=",$stype"
  desc=`xmllint --xpath '/snapshot/description/text()' "${s_dir}/info.xml" 2>/dev/null || echo ""`
  #test "$desc" = "timeline" && return 1
  test -z "$desc" || desc=",$desc"
  title="${important}${NAME} $VERSION ($kernel_ver,$date$stype$desc)"

  cat <<EOF

  if [ -f "${snapper_snapshot_path}/$num/snapshot/boot/grub2/grub.cfg" ]; then
    snapshot_found=true
    saved_subvol=\$btrfs_subvol
    menuentry `print_hotkey` "$title" "${snapper_snapshot_path}/$num/snapshot" "`$grub_mkrelpath ${snapper_snapshot_path}/${num}/snapshot`" {
        btrfs_subvol="\$2"
        extra_cmdline="rootflags=subvol=\$3"
        export extra_cmdline
        snapshot_num=$num
        export snapshot_num
        configfile "\$btrfs_subvol/boot/grub2/grub.cfg"
        btrfs_subvol=\$saved_subvol
      }
  fi

EOF
  hotkey=`incr_hotkey`
  return 0
}

snapper_snapshots_cfg_refresh () {

  if [ ! -d "$snapper_snapshot_path" ]; then
    return
  fi

  cs=
  for s_dir in ${snapper_snapshot_path}/*; do

    snapshot="${s_dir}/snapshot"

    # list only read-only snapshot (bnc#878528)
    if [ ! -d ${s_dir} -o -w "$snapshot" ]; then
        continue
    fi
    if [ -r "${s_dir}/info.xml" -a -r "${s_dir}/snapshot/boot/grub2/grub.cfg" ]; then
      cs="${s_dir}
${cs}"
    else
      # cleanup any grub-snapshot.cfg without associated snapshot info
      snapper_cfg="${s_dir}/${snapshot_submenu_name}"
      if [ -f "$snapper_cfg" ]; then
	rm -f "$snapper_cfg"
	rmdir "$s_dir" 2>/dev/null || true
      fi
      continue
    fi

  done

  hk=""
  [ -z "$hotkey" ] || hk="--hotkey=s"

  for c in $(printf '%s' "${cs}" | sort -Vr); do
    if ! snapshot_submenu "$c" > "${c}/${snapshot_submenu_name}"; then
       rm -f "${c}/${snapshot_submenu_name}"
       continue
    fi
    snapshot_cfg="${snapshot_cfg}
    if [ -f \"$c/${snapshot_submenu_name}\"; then
      source \"$c/${snapshot_submenu_name}\"
    fi"
  done

  cat <<EOF >"${snapper_snapshots_cfg}.new"
if [ -z "\$extra_cmdline" ]; then
  submenu $hk "Start bootloader from a read-only snapshot" {${snapshot_cfg}
    if [ x\$snapshot_found != xtrue ]; then
      submenu "Not Found" { true; }
    fi
  }
fi
EOF

  if ${grub_script_check} "${snapper_snapshots_cfg}.new"; then
    mv -f "${snapper_snapshots_cfg}.new" "${snapper_snapshots_cfg}"
  fi

}


snapshot_submenu_clean () {

  for s_dir in ${snapper_snapshot_path}/*; do

    snapper_cfg="${s_dir}/${snapshot_submenu_name}"

    if [ -f "$snapper_cfg" ]; then
      rm -f "$snapper_cfg"
      rmdir "$s_dir" 2>/dev/null || true
    fi

  done

  if [ -f "${snapper_snapshot_path}/${snapshot_submenu_name}" ]; then
    rm -f "${snapper_snapshot_path}/${snapshot_submenu_name}"
  fi

}

set_grub_setting () {

  name=$1
  val=$2

  if grep -q "$name" "$grub_setting"; then
    sed -i -e "s!.*\($name\)=.*!\1=\"$val\"!" "$grub_setting"
  else
    echo "$name=\"$val\"" >> "$grub_setting"
  fi
}

enable_grub_settings () {
  set_grub_setting SUSE_BTRFS_SNAPSHOT_BOOTING "true"
}

disable_grub_settings () {
  set_grub_setting SUSE_BTRFS_SNAPSHOT_BOOTING "false"
}

update_grub () {
   "${grub_mkconfig}" -o "${grub_cfg}"
}

machine=`uname -m`
case "$machine" in
(s390|s390x)
  hotkey=1
  ;;
esac
cmdline="$0 $* hotkey='$hotkey'"

# Check the arguments.
while test $# -gt 0
do
  option=$1
  shift

  case "$option" in
  -e | --enable)
  opt_enable=true
  ;;
  -d | --disable)
  opt_enable=false
  ;;
  -r | --refresh)
  opt_refresh=true
  ;;
  -c | --clean)
  opt_clean=true
  ;;
  -*)
  ;;
  esac
done

if [ "x${opt_enable}" = "xtrue" ]; then
  #enable_grub_settings
  #update_grub
  snapper_snapshots_cfg_refresh
elif [ "x${opt_enable}" = "xfalse" ]; then
  #disable_grub_settings
  update_grub
  snapshot_submenu_clean
fi

if [ x${opt_refresh} = "xtrue" ]; then
  snapper_snapshots_cfg_refresh
fi

if [ x${opt_clean} = "xtrue" ]; then
  snapshot_submenu_clean
fi

