#!/bin/bash
#
# vim: ts=4 sw=4 et
#
# 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=11.01
BETA_RELEASE=11.07

# 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"
    q='"'
    if test -d "$this_file"
    then
        echo "$prefix <a href=$q$this_file$q>$this_file_descr</a>" >> $INDEX
    else
        this_file_size=`ls -Ll "$this_file" | awk '{ print $5; }'`
        this_file_sizekb=`expr "$this_file_size" / 1024`
        echo "$prefix <a href=$q$this_file$q>$this_file_descr</a> ($this_file_sizekb kilobytes)" >> $INDEX 
    fi
    handled_files="$this_file $handled_files"
}

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

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 test -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*|$LOCKDIR)
            ;;
        
        *)
            if test -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 test -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; }
