#!/bin/sh -e
# rkpkg: a KerGIS tools script to create the archive package holding
# the result
#
# $Id: rkpkg,v 1.16 2007/03/22 16:51:33 tlaronde Exp $
#
#  Copyright 2004 Thierry LARONDE <tlaronde@polynum.com>
#  All rights reserved. 
#  
#  This work is under the KerGIS Public Licence v1.0
# 
#  See the COPYRIGHT file at the root of the source directory or see
#  http://www.kergis.org/licence.txt for complete information.
# 
# !!!THIS SOFTWARE IS PROVIDED ``AS IS'' WITHOUT ANY WARRANTIES!!! 
#                      USE IT AT YOUR OWN RISK 

#========== EXTERNS SETTABLE

#================== NOTHING TO CHANGE BELOW! =====================

#========== GLOBALS

prog_version='$Id: rkpkg,v 1.16 2007/03/22 16:51:33 tlaronde Exp $'

usage="
	$program [-d] [-h] [-V] [-s] 
Package the files as showed in a PROJECT.map.
This program must be run from the top OBJDIR.

Options:
 -s	Save space: move obj files in archive, don't copy
 -d	set Debug on
 -h	display this Help and exit
 -V	display Version information and exit
"

version="$prog_version
Written by Thierry Laronde.

Copyright (c) 2004 Thierry Laronde <tlaronde@polynum.org>

All rights reserved. KerGIS Public Licence v1.0. NO WARRANTIES!."

#========== INITIALIZATIONS

# Name by which this script was invoked.
#
program=`basename $0`


TMPDIR=${TMPDIR:-/tmp}
tmpdir=$TMPDIR/$$
! [ -d $tmpdir ] && mkdir $tmpdir
# remove temporary files on HUP, INT, QUIT, PIPE, TERM
trap " debug F 'Unexpected event. Try -d to debug'; clean_tmp; exit 1;"  HUP INT QUIT PIPE TERM

#========== SUBFUNCTIONS

clean_tmp()
{
	rm -fr $tmpdir
}

# debug writes info (L for LOG), warning (W for WARNING), error
# (E for ERROR) or fatal (F for FATAL) for a programming unrecoverable
# error followed by the message on stderr
#
debug ()
{
	case $1 in
	  A) echo "  ->" | tr -d '\n' 1>&2;;
	  E) echo "$program ERROR: " | tr -d '\n' 1>&2;;
	  F) echo "$program FATAL: " | tr -d '\n' 1>&2;;
	  L) echo "  - " | tr -d '\n' 1>&2;;
	  W) echo "$program WARNING: " | tr -d '\n' 1>&2;;
	  *) echo "$1: " | tr -d '\n' 1>&2;;
	esac
    echo "$2" 1>&2
    return
}

error ()
{
	case $1 in
	  cannot_mkdir) debug E "I can't even make the dir! Uh?!";;
	  not_in_objdir) debug E "I must be run from OBJDIR!";;
	  not_configured) debug E "The pkg tarball does not exist!";;
	  option) debug E "This option is unknown!";
		debug USAGE "$usage";;
	esac

	clean_tmp
	exit 1
}

#=========== PROCESSING

debug_mode=NO
save_space=YES

while [ $# -gt 0 ]; do
	case "$1" in
	  -d) set -x; debug_mode=YES;;
	  -h|--help) echo "$usage"; exit 0;;
	  -V|--version) echo "$version"; exit 0;;
	  -s) save_space=YES;;
	  *) error option ;;
	esac
shift	
done

#========== INITIAL CHECKS

[ -f ".rkcomp/rkpkg.cf" ] || error not_in_objdir
. .rkcomp/rkpkg.cf

#========== PROCESSING

# split the sources between OBJDIR and others
moved=$tmpdir/moved
kept=$tmpdir/kept
present=.rkcomp/installed.list
missing=.rkcomp/missing.list
preserved=.rkcomp/preserved.list
verified=.rkcomp/verified.list
touch $present $missing $preserved $verified

regexp=$(echo $OBJDIR | sed -e 's!/!\\/!g' -e 's/\./\\./g')
sed -n "
/^.\{4\}$regexp/ {
w $moved
=
}
w $kept
" .rkcomp/map 2>/dev/null 1>&2

# Directories (created) are best treated first
# We need to keep track of the action performed before for "continuing"
# that is conditional inclusion.
# NOTE: the real permissions will be handled by rkinstall. Here we set
# permissions so that we can write or overwrite our package.
#
preact=drop
while read action type src dest owner mod; do
	# Don't treat what shall not be treated.
	#
	[ "$preact" != "drop" -o "$action" != '=' ] || { preact=drop; continue; }
	[ "$dest" != '*' ] || { preact=drop; continue; }

	# Skip if already created or installed.
	# We do not support update.
	#
	if grep -qF "$type $dest "  $present \
	    || grep -qF "$type $dest " $preserved \
		|| grep -qF "$type $dest " $verified; then
	    debug L "$dest already packaged";
	    continue;
	fi

	case $action in
	  '?') echo "$type $dest $owner $mod" >>$verified;
		continue;; # let preact untouched
	  ':') to=.rkcomp/preserved$dest;;
	  *) to=.rkcomp/installed$dest;;
	esac

	case $src in
	  '*') # pure creation (no source)
	  case $type in
		f) [ -d $(dirname $to) ] || { mkdir -p $(dirname $to); chmod 755 $(dirname $to); };
		  touch $to; chmod 644 $to;;
		d) mkdir -p $to; chmod 755 $to;;
		*) debug E "Action $action can not be used with a null source!";
		  preact=drop;
		  continue;;
	  esac;;
	  *) # shall exist
	    case $type in

		# Symbolic links are special since they refer to an existing
		# file in the target.
		#
		l) [ -d $(dirname $to) ] || { mkdir -p $(dirname $to); chmod 755 $(dirname $to); };
		  ln -sf $src $to;;
	      *) if [ ! -f "$src" ]; then
			   if ! grep -qF "$src" $missing; then
		        debug W "$src doesn't exist..."; 
			    echo $src >>$missing; preact=drop; 
			   fi
			   continue
			fi

		    # Create intermediary dir if needed.
			#
		    [ -d $(dirname $to) ] || { mkdir -p $(dirname $to); chmod 755 $(dirname $to); }

	        # If file is a compiled one, move or copy depending on
			# save_space. If not a compiled one (source), copy.
			#
	        if ! grep -Fq "$src" $moved || [ $save_space != "YES" ]; then
	          cp  $src $to
	        else
			  mv $src $to
	        fi;
		    chmod 644 $to;;
	     esac;;
	  esac
	  if [ "$action" = ':' ]; then
	    echo "$type $dest $owner $mod" >>$preserved
	  else
	    echo "$type $dest $owner $mod" >>$present
	  fi
	  preact=done 

	  # If pkg is done in several distinct passes, what is now present
	  # may have been missing previously.
	  #
	  if [ "$src" != "*" ] && grep -qF "$src" $missing; then
	    regexp=$(echo $src | sed -e 's!/!\\/!g' -e 's/\./\\./g')
		ed -s $missing<<EOT
g/$regexp/d
w
q
EOT
	  fi
done < .rkcomp/map

# Add new stuf and then suppress in local.
#
if [ -s $PKG.tar ]; then
	tar_action=r
else
	tar_action=c
fi
tar -$tar_action -f $PKG.tar -C .rkcomp rkinstall installed preserved install_bin install_data installed.list missing.list preserved.list verified.list
rm -fr .rkcomp/installed/* .rkcomp/verified/* 

#------------------POST PROCESSING

clean_tmp

exit 0
