#!/usr/local/bin/bash
#
# generate_index_html
#
# Generates index.html files with a link to each file in the directory, and
# recursively for its sub-directories.
#
# Note: This script recursively calls itself, so if invoked without
# an absolute path name, it had better be in its own path!
#

CURRENT_RELEASE=0.11.0
BETA_RELEASE=0.11.1

# We need bash's extended globbing for the case patterns
# matching the release numbers.
shopt -s extglob

INDEX=index.html.$HOST.$$
LOCKDIR=generate_index_html.lock
handled_files=

# Lock the directory (this script may be invoked by test_mercury
# on multiple machines at once).
timeout=20
retries=0
until mkdir $LOCKDIR; do
	case $retries in
	    $timeout) 
	    	echo "** $0: creating lock directory `pwd`/$LOCKDIR failed" 1>&2
		echo "** $0: remove it manually if it is stale" 1>&2
		exit 1
		;;
	esac
	sleep 5
	retries=`expr $retries + 1`
done

trap 'rm -rf $INDEX $LOCKDIR; exit 1' 1 2 3 13 15

    #
    # These are the standard locations for apache's icons
    #
img_txt="<img src=/icons/text.gif>"
img_dir="<img src=/icons/folder.gif>"
img_bak="<img src=/icons/back.gif>"

echo "<!-- This page was automatically generated by generate_index_html -->" \
	> $INDEX
echo "<HTML>" >> $INDEX
echo "<HEAD>" >> $INDEX
echo "<TITLE>The Mercury Project: Directory Listing</TITLE>" >> $INDEX
echo "</HEAD>" >> $INDEX
echo "<BODY>" >> $INDEX
echo "<H1>Directory listing</H1>" >> $INDEX
echo "<hr>" >> $INDEX

#-----------------------------------------------------------------------------#

# link_to_file prefix filename description.
#
# Generate a line with the prefix followed by a link to the given file.
# Record that the file has been handled.
link_to_file () {
	prefix="$1"
	this_file="$2"
	this_file_descr="$3"
	this_file_size=`ls -Ll "$this_file" | awk '{ print $5; }'`
	this_file_sizekb=`expr "$this_file_size" / 1024`
	handled_files="$this_file $handled_files"
	q='"'
	echo "$prefix <a href=$q$this_file$q>$this_file_descr</a> ($this_file_sizekb kilobytes)" >> $INDEX 
}

#-----------------------------------------------------------------------------#

skip_file () {
	stable_file="$1"
	unstable_file="$2"
	if [ -f "$stable_file" ]; then
		handled_files="$unstable_file $handled_files"
	fi
}

#-----------------------------------------------------------------------------#

# link_to_file filename description
#
# Generate a link to a file if it exists.
# This should be called within a `<ul>' element.
link_to_existing_file () {
	#echo link_to_existing_file "$@"
	if [ -f "$1" ]; then
		#echo YES
		link_to_file "<li> " "$1" "$2"
	fi
}

#-----------------------------------------------------------------------------#

# handle_release release_file
#
# Given the name of a source or binary distribution file in a release,
# generate an entry describing all the files in the release.
handle_release () {
	file="$1"
	if [ -f "$file" ]
	then
		case "$handled_files" in
		*$file*)	;;
		*)		do_handle_release "$file" ;;
		esac
	fi
}

#-----------------------------------------------------------------------------#

do_handle_release () {
	file="$1"
	date=`expr "$file" : '.*\([0-9]\{4\}[-_][0-9][0-9][-_][0-9][0-9]\).*'`
	date_underscores=`echo $date | tr '-' '_'`
	date=`echo $date | tr '_' '-'`

	#echo "file=$file, date=$date"
	case "$file" in
	    *-rotd*[-_]unstable*)
		release_name="Unstable snapshot $date"
		release_id="rotd-$date-unstable"
		release_id_underscores="rotd_${date_underscores}_unstable"
		;;
	    *-rotd*)
		release_name="Stable snapshot $date"
		release_id="rotd-$date"
		release_id_underscores="rotd_$date_underscores"
		;;
	    *-*([0-9.])[-_]beta*[-_]unstable*)
		version=`expr "$file" : ".*-\([0-9.]*\)[-_]beta.*[-_]unstable.*"`
		release_name="Unstable $version beta $date"
		release_id="$version-beta-$date-unstable"
		release_id_underscores="${version}_beta_${date_underscores}_unstable"
		;;
	    *-*([0-9.])[-_]beta*)
		version=`expr "$file" : ".*-\([0-9.]*\)[-_]beta.*"`
		release_name="Stable $version beta $date"
		release_id="$version-beta-$date"
		release_id_underscores="${version}_beta_$date_underscores"
		;;
	    *-*([0-9.])*[-_]unstable*)
		version=`expr "$file" : ".*-\([0-9.]*[0-9]\).*[-_]unstable.*"`
		release_name="Unstable release $version"
		release_id="$version-unstable"
		release_id_underscores="${version}_unstable"
		;;
	    *-*([0-9.])*)
		#echo "XXX [release_id=$release_id	file=$file]" 1>&2
		version=`expr "$file" : ".*-\([0-9.]*[0-9]\).*"`
		release_name="Release $version"
		release_id="$version"
		release_id_underscores="$version"
		;;
	    *)
		# Unknown release, this will be put in the list of
		# other files after all known releases.
		#echo "unknown file name: $file"
		return 0
		;;
	esac
	#echo "[release_id=$release_id	file=$file]" 1>&2

	echo "<li> $release_name" >> $INDEX
	echo '<ul>' >> $INDEX
	source_dist_news="mercury-NEWS-$release_id.txt"
	link_to_existing_file "$source_dist_news" "News"
	link_to_existing_file mercury-INSTALL-$release_id.txt \
		"Installation instructions"
	link_to_existing_file mercury-compiler-$release_id.tar.gz \
		"Source distribution"
	link_to_existing_file \
		mercury-compiler-$release_id_underscores-1.src.rpm \
		"Source RPM"
	link_to_existing_file \
		mercury-compiler-$release_id_underscores-1.i386.rpm \
		"RPM (x86)"
	link_to_existing_file mercury_$release_id-1_i386.deb "Debian (x86)"
	bindists1=`echo mercury-$release_id.[a-z]*.tar.gz`
	bindists2=`echo mercury-compiler-$release_id.[a-z]*.zip`
	case "$bindists1" in
	    *'*'.tar.gz)
		bindists=""
		;;
	    *)
	    	bindists="$bindists1"
		;;
	esac
	case "$bindists2" in
	    *'*'.zip)
	    	;;
	    *)
	    	bindists="$bindists $bindists2"
		;;
	esac
	case "$bindists" in
	    "")
	    	;;
	    *)
		echo "<li> Binary distributions" >> $INDEX
		echo "<ul>" >> $INDEX
		for bindist in $bindists
		do
		    case $bindist in
		        *.tar.gz)
			    bindist_name=`expr \
		    	      "$bindist" : "mercury-$release_id.\(.*\).tar.gz"`
			    ;;
		        *.zip)
			    bindist_name=`expr \
		    	      "$bindist" : "mercury-compiler-$release_id.\(.*\).zip"`
			    ;;
		    esac
		    link_to_file "<li> " $bindist $bindist_name
		    echo "<ul>" >> $INDEX
		    bindist_news="mercury-NEWS-$release_id.$bindist_name.txt"

		    # If the news file for the source distribution
		    # doesn't exist, or doesn't match the news file for
		    # the binary distribution, generate a link to the
		    # news file for the binary distribution.
		    # XXX We should probably generate a separate release
		    # entry if the news files for the source and binary
		    # distributions don't match, but that should be rare.
		    if cmp $bindist_news $source_dist_news >& /dev/null
		    then
		    	handled_files="$bindist_news $handled_files"
		    else
			link_to_existing_file $bindist_news "News"
		    fi

		    link_to_existing_file \
			mercury-INSTALL-$release_id.$bindist_name.txt \
			"Installation instructions"
		    link_to_existing_file \
			mercury-test-failures-$release_id.$bindist_name.txt \
			"Test failures"
		    echo "</ul>" >> $INDEX
		done
		echo "</ul>" >> $INDEX
		;;
	esac
	link_to_existing_file mercury-extras-$release_id.tar.gz "Extras"
	link_to_existing_file mercury-gcc-$release_id.tar.gz "GCC native-code interface source"
	link_to_existing_file mercury-tests-$release_id.tar.gz "Test suite"
	link_to_existing_file mercury-test-failures-$release_id.txt \
		"Test failures"
	echo '</ul><p>' >> $INDEX

	# If the same release occurs as both stable and unstable,
	# only include the stable version in the index.
	case $release_id in
		*-unstable*)
			;;
		*)	
			skip_file mercury-NEWS-$release_id.txt \
				  mercury-NEWS-$release_id-unstable.txt
			skip_file mercury-INSTALL-$release_id.txt \
				  mercury-INSTALL-$release_id-unstable.txt
			skip_file mercury-compiler-$release_id.tar.gz \
				  mercury-compiler-$release_id-unstable.tar.gz
			skip_file mercury-extras-$release_id.tar.gz \
				  mercury-extras-$release_id-unstable.tar.gz
			skip_file mercury-tests-$release_id.tar.gz \
				  mercury-tests-$release_id-unstable.tar.gz
			skip_file mercury-gcc-$release_id.tar.gz \
				  mercury-gcc-$release_id-unstable.tar.gz
			;;
	esac
}

#-----------------------------------------------------------------------------#

echo "$img_bak <a href=../>Parent Directory</a><br>" >> $INDEX

#
# Directories.
#
for file in *
do
	if [ -d "$file" -a "$file" != $LOCKDIR ]
	then
		(cd "$file" && $0)
		q='"'
		echo "$img_dir <a href=$q$file/index.html$q>$file/</a><br>" \
			>> $INDEX
	fi
done


echo "<p>" >> $INDEX
echo "<ul>" >> $INDEX

#
# Handle releases. Note that handle_release checks for files
# which have been handled before, so the cases below need not
# be mutually exclusive.
#

#
# Current release.
#
handle_release "mercury-compiler-${CURRENT_RELEASE}.tar.gz"

#
# Stable beta for current release + bug fixes.
# There may be an unstable beta, but there's no point using it.
# We list these in reverse alphabetical order,
# so that the most recently dated ones come first.
#
for file in `ls -1 mercury-compiler-${BETA_RELEASE}-beta*.{tar.gz,rpm} \
		mercury-${BETA_RELEASE}-beta*.tar.gz 2>/dev/null | sort -r`
do
	case "$file" in
		*-unstable*) ;;
		*)	handle_release "$file" ;;
	esac
done

#
# Stable release-of-the-day.
#
for file in `ls -1 mercury-compiler-rotd*.{tar.gz,rpm} mercury-rotd* 2>/dev/null \
		| sort -r`
do
	case "$file" in
		*-unstable*) ;;
		*)	handle_release "$file" ;;
	esac
done

#
# Unstable release-of-the-day
#
for file in `ls -1 mercury-compiler-rotd*-unstable.{tar.gz,rpm} 2>/dev/null \
		| sort -r`
do
	handle_release "$file"
done

#
# Other assorted releases.
#
for file in mercury-compiler-* mercury-rotd* mercury-gcc-*
do
	handle_release "$file"
done

#
# Other stuff.
#
for file in *
do
    case "$file" in
		#
		# Don't include the README or any of the index files
		#
	README|index.html*)
		;;
	*)
		if [ ! -d "$file" ]
		then
			case $handled_files in
				*$file*) ;;
				*)	link_to_file "<li> " "$file" "$file" ;;
			esac
		fi
    		;;
    esac
done

echo "</ul>" >> $INDEX

echo "<hr>" >> $INDEX

if [ -f README ]
then
    echo "<pre>" >> $INDEX
    cat README >> $INDEX
    echo "</pre>" >> $INDEX
fi
echo "</BODY>" >> $INDEX
echo "</HTML>" >> $INDEX

chmod a+r,g+w $INDEX
chgrp mercury $INDEX

mv $INDEX index.html

rmdir $LOCKDIR || { echo "** $0: error removing $LOCKDIR" 1>&2; exit 1; }
