#!/bin/sh
#
BASEDIR=`dirname $0`
. ${BASEDIR}/package-build.inc.sh

NANOBSD="$NANO_SRC/tools/tools/nanobsd/nanobsd.sh"

usage() {
cat <<EOF
# Usage $0 <arguments>
#
# Wrapper around nanobsd.sh with autodetection of already processed steps to
# provide some failsafe net, which avoids building world and/or kernel by
# default.
#
# Rick van der Zwet <rick@wirelessleiden.nl>
#
# Arguments:
# build                         - Build NanoBSD parts which are not build yet
# build force kernel            - Build NanoBSD and force rebuilding the kernel
# build force world             - Build NanoBSD and force rebuilding world
# edit				- Manually edit the image
# config [for <node>]           - Configure image to be used for <node>
# rebuild                       - Rebuild NanoBSD (aka force rebuilding all)
# deploy on <node> [and reboot] - Deploy the image on node and reboot if needed
# ports update 			- Update the packages from ports 
# ports force rebuild		- Forcefully rebuilding all required packages
EOF
}


deploy_image() {
  # Find object directory 
  img=${OBJDIR}/_.disk.image

  if [ ! -r "$img" ]; then
    p_err Source $img does not exists
    exit 1
  fi

  prompt_timeout=5
  p_warn "Going to DEPLOY $img to $host: (8.X-RELEASE and 9.X-RELEASE) to 9.X RELEASE"
  $do_reboot && p_warn "AND will REBOOT the $host"
  p_warn "Please do mind to use your ssh key else you be required to type the root"
  p_warn "password AT MOST 5 times"


  p_warn "Press CTRL+C in $prompt_timeout seconds to CANCEL"
  sleep $prompt_timeout

  # Details and alive checkings
  release=`ssh $host mount | grep 'ada0' && echo "9.0-RELEASE" || echo "PRE-9.0-RELEASE"` || exit 1
  if [ $release = "9.0-RELEASE" ]; then
    cat $img | ssh $host sh -x /tools/update || exit 1
  else
    # Hack to make sure we update the fstab the right way when converting from
    # 8.X-RELEASE to 9.X-RELEASE. ad0 naming changed to ada0.
    P=`ssh $HOST df / | grep '1a ' && echo "p2" || echo "p1"` || exit 1
    echo "# Updating partition $P"

    cat $img | ssh $host sh -x /tools/update$P || exit 1

    if [ "$P" = "p2" ]; then
      cat <<EOF | ssh $HOST sh -x || exit 1
mount -uwo noatime /dev/ad0s2a
sed -i "" "s/ada0s1/ada0s2/" /mnt/conf/base/etc/fstab /mnt/etc/fstab
umount 
EOF
    fi
  fi

  if $do_reboot; then
    ssh $host reboot
  fi
}

config_image() {
  node_name=${1:+"-b -c $1"}

  img=$OBJDIR/_.disk.full

  mnt=`mktemp -d -t $(basename $0)`
  md=`mdconfig -a -t vnode -f $img`
  
  # Clean up when done
  trap "umount $mnt/dev; umount $mnt/cfg; umount $mnt; mdconfig -d -u $md; rm -d $mnt" 0
  trap "exit 1" 1 2 3 15

  # Root filesystem
  mount /dev/${md}s1a $mnt || exit 1

  # /dev/null in chroot
  mount -t devfs devfs ${mnt}/dev || exit 1
  
  # Config files lives at /cfg  location
  mount /dev/${md}s3 $mnt/cfg || exit 1
  
  # Try to fetch and store config
  chroot $mnt /tools/wl-config -d -n -m startup $node_name || exit 1
}

edit_image() {
  img=$OBJDIR/_.disk.full

  mnt=`mktemp -d -t $(basename $0)`
  md=`mdconfig -a -t vnode -f $img`
  
  # Clean up when done
  trap "umount $mnt/dev; umount $mnt/cfg; umount $mnt; mdconfig -d -u $md; rm -d $mnt" 0
  trap "exit 1" 1 2 3 15

  # Root filesystem
  mount /dev/${md}s1a $mnt || exit 1

  # /dev/null in chroot
  mount -t devfs devfs ${mnt}/dev || exit 1
  
  # Config files lives at /cfg  location
  mount /dev/${md}s3 $mnt/cfg || exit 1

  # Nasty hack to set custom prompt
  prompt='set prompt = "image# "'
  echo $prompt >> $mnt/root/.cshrc
  
  p_info "Type exit when done"
  chroot $mnt
  p_info "Any changes are made permanent on image $img"
  
  # Unset prompt again
  sed -I '' "/^$prompt$/d" $mnt/root/.cshrc
}


build_image() {
  p_info Forcefully building kernel: $FORCE_KERNEL
  p_info Forcefully building world : $FORCE_WORLD
  
  NANOBSD_EXTRA=${NANOBSD_EXTRA:-''}
  
  if [ ! -r "${NANOBSD}" ]; then
    p_err ${NANOBSD} does not exists
    exit 1
  fi
  
  if [ ! -x "${NANOBSD}" ]; then
    NANOBSD="sh ${NANOBSD}"
  fi
  
  # Find object directory 
  OBJDIR="/usr/obj/nanobsd.${NANO_NAME}"
  
  if [ -d "${OBJDIR}" ]; then
    NANOBSD_FLAGS=""
    
    # Detect succesfull buildworld
    tail -10 ${OBJDIR}/_.bw | grep 'World build completed'
    if [ $? -eq 0 -a ${FORCE_WORLD} = "no" ]; then
       p_info NO building of world
       NANOBSD_FLAGS="${NANOBSD_FLAGS} -w"
    fi  
  
    # Detect succesfull buildkernel
    tail -10 ${OBJDIR}/_.bk | grep 'Kernel build for .* completed'
    if [ $? -eq 0 -a ${FORCE_KERNEL} = "no" ]; then
       p_info NO building of kernel
       NANOBSD_FLAGS="${NANOBSD_FLAGS} -k"
    fi  
  
  else
    p_warn Nothing yet, starting fresh
    NANOBSD_FLAGS=""
  fi
  
  # Provide verbose output by default
  COMMAND="${NANOBSD} ${NANOBSD_FLAGS} -c ${NANO_CFG_FILE} -v ${NANOBSD_EXTRA}"
  f_time ${COMMAND}
  RETVAL=$?
  
  # Verify on build failures
  tail -10 ${OBJDIR}/_.bw | grep 'World build completed'
  if [ $? -eq 1 ]; then
    p_err Building world FAILED, check ${OBJDIR}/_.bw
  fi
  tail -10 ${OBJDIR}/_.bk | grep 'Kernel build for .* completed'
  if [ $? -eq 1 ]; then
    p_err Building kernel FAILED, check ${OBJDIR}/_.bk
  fi  
  if [ $RETVAL -ne 0 ]; then
    p_err "Errors in building NanoBSD Image ($RETVAL)"
  fi
  p_info End time: `date`
  exit ${RETVAL}
}

#
# Argument parsing
#
FORCE_KERNEL=${FORCE_KERNEL:-"no"}
FORCE_WORLD=${FORCE_WORLD:-"no"}
if [ -z "$1" ]; then
  usage; exit 1
elif [ "$1" = "build" ]; then
  if [ -z "$2" ]; then
  elif [ "$2" = "force" ]; then
    if [ "$3" = "kernel" ]; then
      FORCE_KERNEL="yes"
    elif [ "$3" = "world" ]; then
      FORCE_WORLD="yes"
    else
      echo "Argument Error - '$3'"; exit 128
    fi
  else
    echo "Argument Error - '$2'"; exit 128
  fi
  build_image
elif [ "$1" = "rebuild" ]; then
  FORCE_KERNEL="yes"
  FORCE_WORLD="yes"
  build_image
elif [ "$1" = "deploy" -a "$2" = "on" ]; then
  if [ -z "$3" ]; then
      echo "Argument Error - '$3'"; exit 128
  fi
  host=$3
  do_reboot=false
  if [ -n "$4" -o -n "$5" ]; then
    if [ "$4" = "and" -a "$5" = "reboot" ]; then
      do_reboot=true
    else
      echo "Argument Error - '$4 $5'"; exit 128
    fi
  fi
  deploy_image
elif [ "$1" = "ports" ]; then
  if [ "$2" = "update" ]; then
    # Fetch the latest details and provide listing of packages to be updated
    portsnap fetch update || exit 1

    # HACK: install our own ports _inside_ the normal ports dir
    cp -fR $WL_PORTSDIR/* $PORTSDIR || exit 1

    # Make sure portmaster is present to update all ports
    portmaster --version 1>/dev/null 2>/dev/null || make -C /usr/ports/ports-mgmt/portmaster BATCH=yes install clean || exit 1

    # Update via portmaster
    CMD="env `echo $PKG_MAKE_ARGS` portmaster --no-confirm --update-if-newer -y -d -G  `echo $PACKAGE_LIST`"
    echo "# Going to run port upgrade cycle: $CMD"; $CMD || exit 1

    . ${BASEDIR}/package-build.sh
  elif [ "$2" = "force" -a "$3" = "rebuild" ]; then
    export FORCE_REBUILD=1
    . ${BASEDIR}/package-build.sh
  else
    shift 1
    echo "Arguments Error - '$*'"; exit 128
  fi
elif [ "$1" = "config" ]; then
  if [ "$2" = "for" ]; then
    if [ -n "$3" ]; then
      node_name=$3
    else
      echo "Arguments Error - '$*'"; exit 128
    fi
  else
    echo "Arguments Error - '$*'"; exit 128
  fi
  config_image $node_name
elif [ "$1" = "edit" ]; then
  edit_image
else
  echo "Argument Error - '$1'"; exit 128
fi

