#!/bin/sh

# Author   : Benoit PAPILLAULT <benoit.papillault@sourcemage.org>
# Creation : 2004-11-25

# Design document:
# http://benoit.papillault.free.fr/sourcemage/cast-binary.php

# usage: get_cache_list
# output the list of files available, the output name should not include
# any URL or path.

get_cache_list()
{
  case "${BASE}" in
    http://* | https://* | ftp://*)
      if ! wget -O - "${BASE}/ls"; then
	    return 1
      fi
	  ;;
	*)
	  # cut removes the leading "./"
      (cd "${BASE}" ; find . -maxdepth 1 -type f| cut -c3-)
	  ;;
  esac
}

# usage: get_cache spell
# return the full path to spell-....tar.bz2

get_cache()
{
  local spell="$1"
  local CACHE=`get_cache_list | grep "^${spell}_" | head -n 1` &&
  if [ -n "${CACHE}" ]; then
    if [ -f "${BASE}/${CACHE}" ]; then
	  echo "${BASE}/${CACHE}"
    else
	  # it's a remote file, we need to download it first in /tmp
	  rm -rf "/tmp/${CACHE}" &&
	  if wget -O "/tmp/${CACHE}" "${BASE}/${CACHE}"; then
		echo "/tmp/${CACHE}"
	  fi
	fi
  fi
}

# usage: update_sorcery_packages
# add stdin to sorcery packages on the destination system

update_sorcery_packages()
{
  mkdir -p "${INSTALL_ROOT}/var/state/sorcery" &&
  cat >> "${INSTALL_ROOT}/var/state/sorcery/packages"
}

# usage: update_sorcery_depends
# add stdin to sorcery depends on the destination system

update_sorcery_depends()
{
  mkdir -p "${INSTALL_ROOT}/var/state/sorcery" &&
  cat >> "${INSTALL_ROOT}/var/state/sorcery/depends"
}

# usage: install_from_cache spell cache.tar.bz2
# SPELL is the spell name given on the command line
# C_SPELL is the canonical spell name

install_from_cache()
{
  local SPELL="$1"
  local CACHE="$2"
  local VERSION=`basename "${CACHE}" | cut -d_ -f2`

  echo "spell ${SPELL} version ${VERSION} is being investigated"

# create a temporary directory
  local tmpdir="/tmp/spell-binary-$$"
  rm -rf "${tmpdir}" && mkdir -p "${tmpdir}" &&
  (

# extract and install dependencies
	tar jxf "${CACHE}" -C "${tmpdir}" ./install &&
	grep ".*:.*:on:.*" "${tmpdir}/install/depends" |
	cut -d: -f2 | cut -d'(' -f1 |
	while read dep_spell;
	do
	  spell-binary-install "${dep_spell}"
	done

# extract binary files

    echo "spell ${SPELL} version ${VERSION} is being installed"

	tar jxf "${CACHE}" -C "${INSTALL_ROOT}" --exclude ./install 2>/dev/null

# update sorcery files:
# - /var/state/sorcery/packages
# - /var/state/sorcery/depends

    if [ -f "${tmpdir}/install/packages" ]; then
	  cat "${tmpdir}/install/packages"
	else
	  echo "${SPELL}:`date +%Y%m%d`:installed:${VERSION}"
    fi | update_sorcery_packages
	cat "${tmpdir}/install/depends"  | update_sorcery_depends

# run post installation script
	(
	  cd "${INSTALL_ROOT}" &&
	  if [ -x "${tmpdir}/install/postinst" ]; then
		"${tmpdir}/install/postinst"
	  fi
	)

  ) &&
  echo "spell ${SPELL} version ${VERSION} is installed"

  rm -rf "${tmpdir}"
}

# usage: install_from_system spell

install_from_system()
{
  local SPELL="$1"

# we check if the spell is in the source system
  local packages="/var/state/sorcery/packages"
  if [ ! -f "${packages}" ]; then
    echo "spell ${SPELL} is missing"
	exit 1
  fi

  if ! grep -q "^${SPELL}:" "${packages}"; then
    echo "spell ${SPELL} is missing"
    exit 1
  fi

  local VERSION=`grep "^${SPELL}:" "${packages}" | cut -d: -f4 | head -n 1`

  echo "spell ${SPELL} version ${VERSION} is being investigated"

# find the install log
  local FILES="/var/log/sorcery/install/${SPELL}-${VERSION}"
  if [ ! -f "${FILES}" ]; then
    echo "spell ${SPELL} is missing an install log"
    exit 1
  fi

# install dependencies

  local depends="/var/state/sorcery/depends"
  if [ -f "${depends}" ]; then
    grep "^${SPELL}:.*:on:.*" "${depends}" | cut -d: -f2 | cut -d'(' -f1|
	while read dep_spell;
	do
	  spell-binary-install "${dep_spell}"
	done
  fi

# create a temporary dir
  local tmpdir="/tmp/spell-binary-$$"
  rm -rf "${tmpdir}" && mkdir -p "${tmpdir}"

# extract binary files

  echo "spell ${SPELL} version ${VERSION} is being installed"

  sed 's:^\(/*\)::' "${FILES}" > "${tmpdir}/ls"

  (cd / && tar cf - --no-recursion -T "${tmpdir}/ls" )|
  (tar xfp - -C "${INSTALL_ROOT}") || exit 1

# update sorcery files

  grep "^${SPELL}:" "${packages}" | update_sorcery_packages
  grep "^${SPELL}:" "${depends}"  | update_sorcery_depends 

# run post installation scripts: how?

  rm -rf "${tmpdir}"

  echo "spell ${SPELL} version ${VERSION} is installed"
}

main()
{
  if [ $# -ne 1 ]; then
    echo "usage: $0 spell"
    exit 1
  fi

  local SPELL="$1"
  local C_SPELL=`echo "${SPELL}" | sed s/_/-/g`

# default values
  if [ -z "${BASE}" ]; then
    BASE=.
  fi

  if [ -z "${INSTALL_ROOT}" ]; then
    INSTALL_ROOT=/
  fi

# check if the spell is already installed first!
  if [ -f "${INSTALL_ROOT}/var/state/sorcery/packages" ]; then
    if grep -q "^${SPELL}:" "${INSTALL_ROOT}/var/state/sorcery/packages"; then
      echo "spell ${SPELL} is already installed"
      exit 0
    fi
  fi

# find the cache file
  local CACHE=`get_cache "${C_SPELL}"`
  if [ -z "${CACHE}" ]; then
	install_from_system "${SPELL}"
  else
    install_from_cache "${SPELL}" "${CACHE}"
  fi
}

main "$@"
