#!/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_sorcery_host

get_sorcery_host()
{
  local config="${INSTALL_ROOT}/etc/sorcery/config"
  if [ -f "${config}" ]; then
# we start a subshell to avoid polluting our variables
# warning : if INSTALL_ROOT is not / and since "config" will try to
# source other files, we might get into problems.
    ( . "${config}"; echo "${HOST}")
  fi
}

# usage: get_spell_version $spell

get_spell_version()
{
  local spell="$1"

# check if we have a "packages" file, otherwise, we return a empty string

  if [ -f "${INSTALL_ROOT}/var/state/sorcery/packages" ]; then
    grep "^${spell}:" "${INSTALL_ROOT}/var/state/sorcery/packages"|
	cut -d: -f4|head -n 1
  fi
}

# usage: copy_local_depends $SPELL
# copy $INSTALL_ROOT/etc/sorcey/local/depends/$SPELL{.p} if any
# to the current directory

copy_local_depends()
{
  local SPELL="$1"

  # copy /etc/sorcery/local/depends files
  local DEPENDS_DIR=/etc/sorcery/local/depends
  local DEPENDS="${DEPENDS_DIR}/${SPELL}"
  if [ -f "${INSTALL_ROOT}/${DEPENDS}" ]; then
    mkdir -p "./${DEPENDS_DIR}" &&
	cp -a "${INSTALL_ROOT}/${DEPENDS}" "./${DEPENDS_DIR}"
  fi

  local DEPENDS="${DEPENDS_DIR}/${SPELL}.p"
  if [ -f "${INSTALL_ROOT}/${DEPENDS}" ]; then
    mkdir -p "./${DEPENDS_DIR}" &&
	cp -a "${INSTALL_ROOT}/${DEPENDS}" "./${DEPENDS_DIR}"
  fi
}

# usage: get_depends $spell
# output one line for each dependency. each dependency is a spell name

get_depends()
{
  local spell="$1"

# check if we have a "depends" file
# warning, some spells depends on generic provider and the spell name field
# is for instance : util-linux(UTIL-LINUX)
# we remove the () part.

  local depends="${INSTALL_ROOT}/var/state/sorcery/depends"
  if [ -f "${depends}" ]; then
    grep "^${spell}:" "${depends}"
	true
  fi
}

# usage: get_spell_dir $spell
# returns the directory containing spell files
# something like /var/lib/sorcery/codex/stable/libs/glibc for the glibc spell

get_spell_dir()
{
  local spell="$1"

  find "${INSTALL_ROOT}/var/lib/sorcery/codex" -mindepth 3 -maxdepth 3 \
    -type d -name "${spell}" | head -n 1
}

# usage: get_build_api $spell_dir
# this returns the BUILD_API specified in the first spell found in
# /var/lib/sorcery/codex

get_build_api()
{
  local spell_dir="$1"

  if [ -z "${spell_dir}" ]; then
    echo "cannot find spell ${spell} in grimoires"
    exit 1
  fi

  local build_api

# spell level
  local spell_config="${spell_dir}/DETAILS"
  if [ -f "${spell_config}" ]; then
    build_api=`. "${spell_config}"; echo "${BUILD_API}"`
  fi

# section level (if not defined at the spell level)
  if [ -z "${build_api}" ]; then
    local section_config="${spell_dir}/../API_VERSION"
    if [ -f "${section_config}" ]; then
	  build_api=`. "${section_config}"; echo "${BUILD_API}"`
    fi
  fi

# grimoire level (if not already defined)
  if [ -z "${build_api}" ]; then
    local grimoire_config="${spell_dir}/../../API_VERSION"
    if [ -f "${grimoire_config}" ]; then
      build_api=`. "${grimoire_config}"; echo "${BUILD_API}"`
    fi
  fi

# default value if not already defined
  if [ -z "${build_api}" ]; then
    build_api=1
  fi

  echo "${build_api}"
}

# usage: get_postinst $spell
# output the postinst file from either POST_INSTALL (BUILD_API=1)
# or FINAL (BUILD_API=2)

get_postinst()
{
  local spell="$1"

  local spell_dir=`get_spell_dir "${spell}"`
  local build_api=`get_build_api "${spell_dir}"`

  case "${build_api}" in
    1)
      if [ -f "${spell_dir}/POST_INSTALL" ]; then
		cat "${spell_dir}/POST_INSTALL"
      fi
	  ;;
    2)
      if [ -f "${spell_dir}/FINAL" ]; then
        cat "${spell_dir}/FINAL"
      fi
	  ;;
  esac
}

# usage: package_depends spell
# stdin is read for dependencies information
# lines have the same format as /var/state/sorcery/depends
# call spell-binary-make for all dependencies

package_depends()
{
  local SPELL="$1"

  grep "^${SPELL}:.*:on:.*" | cut -d: -f2 | cut -d'(' -f1|
  while read dep_spell;
  do
	spell-binary-make "${dep_spell}"
  done
}

# usage: make_binary_cache spell version
# the resulting cache file name is written on stdout

make_binary_cache()
{
  local SPELL="$1"
  local VERSION="$2"

  local INSTALL="${INSTALL_ROOT}/var/log/sorcery/install/${SPELL}-${VERSION}"
  if [ ! -f "${INSTALL}" ]; then
    exit 1
  fi

  # remove all leading /

  rm -rf "/tmp/ls.${SPELL}" &&
  sed 's:^\(/*\)::' "${INSTALL}" > "/tmp/ls.${SPELL}"

  local CACHE="/tmp/${SPELL}-${VERSION}-iso.tar.bz2"

  (cd "${INSTALL_ROOT}" &&
	tar jcf "${CACHE}" --no-recursion -T "/tmp/ls.${SPELL}" &&
    echo "${CACHE}"
  )

  rm "/tmp/ls.${SPELL}"
}

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

  local SPELL="$1"

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

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

  local VERSION=`get_spell_version "${SPELL}"`
  if [ -z "${VERSION}" ]; then
    echo "${SPELL} is not installed in ${INSTALL_ROOT}"
    exit 1
  fi

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

  local HOST=`get_sorcery_host`
  if [ -z "${HOST}" ]; then
    echo "sorcery architecture is unknown, check your sorcery settings"
    exit 1
  fi

# compute canonic name (replace _ by -)

  local C_SPELL=`echo "${SPELL}" | sed s/_/-/g`
  local C_VERSION=`echo "${VERSION}" | sed s/_/-/g`
  local C_HOST=`echo "${HOST}" | sed s/_/-/g`
  local PKG="${C_SPELL}_${C_VERSION}_${C_HOST}.tar.bz2"

# check if the package already exist (it may already exist since we
# are checking dependencies recursively)

  if [ -f "${BASE}/${PKG}" ]; then
	 echo "spell ${SPELL} version ${VERSION} is already packaged"
     exit 0
  fi

# look for the precompiled binary cache

  CACHE="${INSTALL_ROOT}/var/cache/sorcery/${SPELL}-${VERSION}-${HOST}.tar.bz2"
  if [ ! -f "${CACHE}" ]; then
	# we need to make a cache ourselves (TO BE IMPLEMENTED)
	CACHE=`make_binary_cache "${SPELL}" "${VERSION}"`
	if [ -z "${CACHE}" ]; then
     echo "no binary cache found and cannot make one"
     exit 1
    fi
  fi

# package dependencies first
  get_depends "${SPELL}" | package_depends "${SPELL}"

# create a temporary directory

  local tmpdir="/tmp/spell-binary-$$"
  rm -rf "${tmpdir}" && mkdir -p "${tmpdir}" &&
  (
	cd "${tmpdir}" &&
	tar jxf "${CACHE}" &&
	mkdir -p install &&
	copy_local_depends "${SPELL}" &&
	get_depends  "${SPELL}" > install/depends &&
	get_postinst "${SPELL}" > install/postinst &&
	if [ -s install/postinst ]; then
	  chmod a+x install/postinst
    else
	  rm install/postinst
    fi
  ) &&
  (
    echo "spell ${SPELL} version ${VERSION} is being packaged" &&
	mkdir -p "${BASE}" &&
	tar jcf "${BASE}/${PKG}" -C "${tmpdir}" .
  ) &&
  echo "spell ${SPELL} version ${VERSION} is packaged"

  rm -rf "${tmpdir}"
}

main "$@"
