#!/bin/sh

# ensure PATH contains what we use
export PATH=/sbin:/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin

errmsg()   { printf "\033[1;31mFailed:\033[0m  $1\n"; exit; }
usagemsg() { printf '\033[1;31mUsage:\033[0m  upgrade [-r release] [configuration]
  -r 0 | unstable  -- upgrade to development head
  -r 1 | stable    -- latest release
  -r n             -- a prior release
  -r branch        -- such as DragonFly_RELEASE_5_6
  -r commit        -- such as 3f628449363f40a
  configuration is an optional kernconf file.  See `man kernconf`\n'; exit; }

# simply get usage arguments
KERNCONF='X86_64_GENERIC'
case $# in
  0) ;;
  1) KERNCONF="$1" ;;
  2) RELEASE="$2"
     test "$1" = '-r' || usagemsg ;;
  3) test "$1" = '-r' && RELEASE="$2" && KERNCONF="$3"
     test "$2" = '-r' && RELEASE="$3" && KERNCONF="$1"
     test "$RELEASE"  || usagemsg ;;
  *) usagemsg ;;
esac
test "$KERNCONF" = '-r'  -o "$KERNCONF" = '-h'  -o "$KERNCONF" = '--help' && usagemsg
echo "Configuration is \"$KERNCONF\""

# create the base repository
test -d /usr/src || {
  su -m root -c "mkdir /usr/src && chown `id -u` /usr/src" \
  && cd /usr/src \
  && git init >/dev/null \
  && git remote add origin git://git.dragonflybsd.org/dragonfly.git; }
cd /usr/src

# warn if root, or enable non-root usage
test `id -u` -eq 0 \
&& echo 'It is possible to run this script without root privileges' \
|| test `stat -f '%u' /usr/src` -eq 0  -o  `stat -f '%u' /usr/obj` -eq 0 \
&& su -m root -c "chown -R `id -u` /usr/src; chown -R `id -u` /usr/obj" 2>/dev/null

# get branches and tags
LIST=`git ls-remote -q --refs --sort='v:refname' 2>/dev/null` \
|| errmsg 'Could not reach git://git.dragonflybsd.org'
# get only tags ending in '.0' -- so filtering 'rc' release-candidates
TAGS=`echo "$LIST" | grep -E 'refs/tags/v[0-9.]+\.0$'`
# convert it to a regex to match branches
TAGSREGEX=`echo "$TAGS" | sed -E 's/.*\/tags\/v(.*)\.0/\1/' | tr '.' '_' | tr '\n' '|'`
# now filter DragonFly_RELEASE, to those with '.0' released tags
LISTRELEASED=`echo "$LIST" | grep -E "refs/heads/DragonFly_RELEASE_(${TAGSREGEX}blah)"`
test "$RELEASE" || {
  # list possible releases to choose from
  echo   'Release is:'
  echo   '  [0]  Unstable head'
  echo   echo "$LISTRELEASED" | tail -3 -r | cat -n | sed -E 's/^ *([0-9]+).*\/heads\//  [\1]  /'
  printf "  [_]  Enter a specific commit like 'abcdef123'\n\nChoose: "
  read RELEASE; }

# allow RELEASE to be 'stable' or 'unstable'
test "$RELEASE" = 'unstable' && RELEASE=0
test "$RELEASE" = 'stable'   && RELEASE=1

# try to convert RELEASE 0-n to a branch
LIST=`echo "$LISTRELEASED" | tail -r | sed -E 's/.*\/heads\///'`
LIST="master
$LIST"
test "$RELEASE" -ge 0                         2>/dev/null \
&& echo "$LIST" | head -$(( 1 + "$RELEASE"))  2>/dev/null >&2 \
&& BRANCH=`echo "$LIST" | head -$(( 1 + "$RELEASE")) | tail -1`

# RELEASE is a branch or a commit
test "$BRANCH" && {
	echo "Upgrading to $BRANCH"
  git fetch --depth=1 -k origin "$BRANCH" \
  || errmsg 'git fetch'
  git checkout -B "$BRANCH" origin/"$BRANCH" \
  || errmsg 'git checkout  (you may need to delete /usr/src and try again)'; } \
|| {
	echo "Upgrading to $RELEASE"
  git fetch $(test `git rev-parse --is-shallow-repository` = 'true' && echo '--unshallow') origin \
  || errmsg 'git fetch'
  git checkout "$RELEASE" \
  || errmsg 'git checkout  (you may need to delete /usr/src and try again)'; }

# test configuration
test -f "/usr/src/sys/config/$KERNCONF" \
|| errmsg "Configuration \"$KERNCONF\" not in /usr/src/sys/config" \

# install
make -j`sysctl -n hw.ncpu` buildworld \
|| errmsg     'make buildworld'
make -j`sysctl -n hw.ncpu` buildkernel KERNCONF="$KERNCONF" \
|| errmsg     'make buildkernel'
su -m root -c "make installkernel KERNCONF='$KERNCONF'" \
|| errmsg     'make installkernel'
su -m root -c 'make installworld' \
|| errmsg     'make installworld'
su -m root -c 'make upgrade' \
|| errmsg     'make upgrade'
