#!/bin/sh

# No Time To Explain Get In The Car!

. shell-getopt

Die() { # message [errorcode]
  echo "$1" >&2
  exit "${2:-1}"
}

# imported from m-i-propagator, since the respective libshell tool can not print
# the queried argument and therefore is lame.
#
# get /proc/cmdline parameter
# if key is specified, parse key1:value1,key2:value2... parameter argument
# and select the corresponding key value
# returns:
#       0 if there is a parameter (also print it's value if "-p" is used)
#       1 if there is no such parameter
get_cmdline() { # [-p] parameter [key]
  local SEDFLAG=""
  local SEARCH=""
  local REPLACE=""
  local CMDLINE="${PROC_CMDLINE:-/proc/cmdline}"

  case "$1" in
    -p) SEDFLAG="p"; shift ;;
  esac

  case "$#" in
    1) SEARCH="$1(=([^ ]*)|()( |$))"; REPLACE="\3";;
    *) SEARCH="$1=(.*,|)$2(:([^, ]+)|()(,.*| |\$))"; REPLACE="\4";;
  esac

  sed -nr "
  s/(^|.* )$SEARCH.*/$REPLACE/$SEDFLAG
  t
  q 1
  " < "$CMDLINE"
}

# check if get_cmdline -p $2 [$3] is equal to $1 pattern
equal_cmdline() {  # value <get_cmdline parameter> [<get_cmdline parameter2>]
  local V="$1"; shift
  case $(get_cmdline -p "$@") in
      $V) return 0;;
      *) return 1;;
  esac
}

RW="/.rw/rw"
STATIC="/opt /root /usr/local"
PRIVATE="/home"
KEEPDIR=""
ISOPARAMS="-input-charset UTF-8 -R -o-"
SQPARAMS="-noappend -comp lzo -Xcompression-level 3" # -quiet"
DST="user@ns"
VARSKIP="/var/log /var/cache /var/lib/apt /tmp /var/tmp /run /var/run"
ADDSKIP="/dev /proc /sys /mnt"
ALLSKIP="gvfs"
MANAGER=overlays-manage
MANAGEFLAGS=""
SKIP=""
HOMESKIP=".cache Cache .apt"
PKGSTORE="/var/db/livecd-packages"
PROFILE="$(get_cmdline -p profile)"

if test -r "$HOME/.config/netinst-overlays/overlays-create"; then
	. "$HOME/.config/netinst-overlays/overlays-create"
elif test -r "$HOME/.overlays-create"; then
	. "$HOME/.overlays-create"
fi

argv=$(getopt \
	-n "overlays-create" \
	-o H:,P:, -l destination:,profile:,manager: \
	-- "$@")
eval set -- $argv
while : ; do case "$1" in
	--) shift; break; ;;
	-H|--destination) shift; DST="$1" ;;
	-P|--profile) shift; PROFILE="$1" ;;
	--manager) shift; MANAGER="$1" ;;
esac; shift
done

STACK=""
CLASS="$1"
CMD="${2:-create}"
MNT="${MNT:-/mnt}"
MNTDIR="${MNTDIR:-overlays}"
MTARGET="$MNT/$MNTDIR"

case "$CLASS" in
	diskcache)	# temporary loopmount varskip on hdd
		HDD="$( (fdisk -l || sfdisk -l) 2>/dev/null | sed -n '/Linux$/s/[ 	].*//p' | tail -1)"
		test -n "$HDD" || Die "No Linux partition found"
		umount "$MNT" 2>/dev/null || :
		mount "$HDD" "$MNT" || Die "Mount $HDD to $MNT failed"
		rm -rf "$MTARGET" 
		mkdir -p "$MTARGET" || Die "Cannot make $MTARGET directory"
		find $VARSKIP | grep -v "$ALLSKIP" | cpio -pdm "$MTARGET" || 
			Die "Copying of $VARSKIP failed"
		for D in $VARSKIP; do
			mount -o bind "$MTARGET$D" "$D" ||
				Die "Bind mount of $D failed"
		done
		exit
		;;
	initial)	# create initial full overlay (without $PRIVATE)
		ROOT="$RW/"
		SKIP="$VARSKIP $ADDSKIP $PRIVATE"
		CMD="start"
		rpm -qa > "$PKGSTORE.initial"
		;;
	packages)	# ask server for packages that were installed and/or deleted
		ssh -qt "$DST" "PROFILE='$PROFILE' $MANAGER $MANAGEFLAGS diff" | sed '
		/^1 /s/^1/remove -y/
		/^2 /s/^2/install -y/
		$a\
			commit -y
		'
		exit 0
		;;
	static)		# create static system paths overlay
		ROOT="$STATIC";;
	home)		# create $HOME overlay
		ROOT="$PRIVATE"
		KEEPDIR="-keep-as-directory"
		SKIP="$HOMESKIP"
		;;
	etc)		# create cumulative /etc overlay
		ROOT="$RW/etc"
		STACK=1
		;;
	system)		# create cumulative system-only overlay (includes /etc)
		ROOT="$RW/"
		STACK=1
		SKIP="$PRIVATE $STATIC $VARSKIP $ADDSKIP"
		rpm -qa > "$PKGSTORE"
		;;
	*)
		echo "Usage: $0 <command> [start]" >&2
		grep "^[^(]*).*#" "$0" >&2
		exit 1
		;;
esac

GRAFT="-graft-points"
for D in $ROOT; do GRAFT="$GRAFT ${D#$RW}=$D"; done

SKIPLIST=""
for F in $SKIP; do 
	case "$F" in
		/*) for D in $ROOT; do SKIPLIST="$SKIPLIST -m ${D%/}$F"; done;;
		*) SKIPLIST="$SKIPLIST -m $F";;
	esac
done

SQIPLIST=""
for F in $SKIP; do 
	case "$F" in
		/*) for D in $ROOT; do SQIPLIST="$SQIPLIST -e ${D%/}$F"; done;;
		*) SQIPLIST="$SQIPLIST $F" ;; # SQIPLIST="$SQIPLIST ${F#/}";;
	esac
done
test -z "$SQIPLIST" || SQIPLIST="-e $SQIPLIST"

echo "	Creating '$CLASS': $ROOT" >&2

#echo genisoimage -q $SKIPLIST $ISOPARAMS $GRAFT # | ssh "$DST" "PROFILE='$PROFILE' $MANAGER $MANAGEFLAGS $CMD $CLASS $STACK"
OSIZE="`df --output=used -k "$RW" | tail -1`"
mkdir -p "$MTARGET"
ASIZE="`df --output=avail -k "$MTARGET" | tail -1`"
SQIMAGE="$MTARGET/image.squash"
if [ "$OSIZE" -ge "$ASIZE" ]; then 
	Die "There's no $OSIZE space at $MTARGET, use `basename $0` diskcache" 1
else
{
	cd "$RW"
	set -x
	mksquashfs $ROOT $SQIMAGE $SQPARAMS $KEEPDIR $SQIPLIST
	ssh "$DST" "PROFILE='$PROFILE' $MANAGER $MANAGEFLAGS $CMD $CLASS $STACK" < $SQIMAGE
	set +x
}
fi
