#!/bih/sh

#
# Qt4 distribution ZIP archive creator.
#
# NOTE: This script requires the basic set of unix tools such as cp, mkdir,
# pwd, readlink, find etc.
#

#
# Defaults
#

out_dir="tmp-zip"

cp="cp -Rdp"

#
# Functions
#

die() { echo "ERROR: $@"; cd "$start_dir"; exit 1; }

run()
{
    echo "$@"
    "$@" || die \
"Last command failed (exit status $?)."
}

cp_files()
{
    local src_base="$1" # source directory base
    local out_base="$2" # output directory base
    local path="$3"     # file path relative to $src_base, may be glob
    local exclude="$4"  # exclude pattern (relative to $src_base),
                        # case syntax [optional]
    local ext="$5"      # additional extension of $path base to copy (e.g. .sym)
                        # [optional

    [ -z "$src_base" -o -z "$out_base" -o -z "$path" ] && \
        die "cp_files: invalid arguments."

    local path_dir="${path%/*}/"
    [ "$path_dir" = "$path/" ] && path_dir=

    [ -d "$out_base/$path_dir" ] || run mkdir -p "$out_base/$path_dir"

    # simple case?
    if [ -z "$exclude" -a -z "$ext" ]; then
        run $cp "$src_base/$path" "$out_base/$path_dir"
        return
    fi

    # complex case with exclude pattern or with additional extension
    for f in $src_base/$path; do
        [ -z "$exclude" ] || \
            eval "case ${f#$src_base/} in $exclude) continue;; esac"
        run $cp "$f" "$out_base/$path_dir"
        [ -z "$ext" ] || run $cp "${f%.*}.$ext" "$out_base/$path_dir"
    done
}

cp_files_inst_out() cp_files "$inst_base" "$out_base" "$1" "$2" "$3"

cp_exe_files_inst_out() cp_files "$inst_base" "$out_base" "$1" "$2" "sym"

cmd_cleanup()
{
    [ -d "$out_dir" ] && \
        run rm -rf "$out_dir"
}

split_out_sym()
{
    local out_base="$1"
    local out_base_sym="$2"

    [ -z "$out_base" -o -z "$out_base_sym" ] && \
        die "create_zips: invalid arguments."

    run mkdir -p "$out_base_sym/"

    for f in $(cd "$out_base" && find -type f -name "*.sym"); do
        local fd="${f%/*}"/
        [ "$fp" = "$f/" ] && fd=
        [ -d "$out_base_sym/$fd" ] || run mkdir -p "$out_base_sym/$fd"
        run mv "$out_base/$f" "$out_base_sym/$fd"
    done

    run $cp "$script_dir/INSTALL.OS2.debuginfo" "$out_base_sym/"
}

create_zips()
{
    [ -z "$start_dir" -o -z "$out_dir" -o \
      -z "$pkg_name" -o -z "$full_pkg_name" -o -z "$out_base" ] && \
        die "create_zips: invalid arguments."

    local out_base_sym="$out_dir/$full_pkg_name-debuginfo/$pkg_name-$ver_dots"

    # .SYM files
    split_out_sym "$out_base" "$out_base_sym"

    local cwd=$(pwd)

    run cd "$out_base/.."
    run zip -SrX9 "$full_pkg_name-$ver_dots.zip" "$pkg_name-$ver_dots"
    run mv "$full_pkg_name-$ver_dots.zip" "$start_dir/"

    run cd "$out_base_sym/.."
    run zip -SrX9 "$full_pkg_name-debuginfo-$ver_dots.zip" "$pkg_name-$ver_dots"
    run mv "$full_pkg_name-debuginfo-$ver_dots.zip" "$start_dir/"

    run cd "$cwd"
}

cmd_create()
{
    local inst_base="$1"
    local build_num="$2"

    [ -d "$inst_base" ] || die "'$inst_base' is not a directory."

    local qconfig_pri="$inst_base/mkspecs/qconfig.pri"

    [ -f "$qconfig_pri" ] || \
        die "Could not find file '$qconfig_pri'."

    local ver_major=$(sed -nre \
        "s/^[[:space:]]*QT_MAJOR_VERSION[[:space:]]+=[[:space:]]+([0-9]+)[[:space:]]*$/\1/p" < "$qconfig_pri")
    local ver_minor=$(sed -nre \
        "s/^[[:space:]]*QT_MINOR_VERSION[[:space:]]+=[[:space:]]+([0-9]+)[[:space:]]*$/\1/p" < "$qconfig_pri")
    local ver_patch=$(sed -nre \
        "s/^[[:space:]]*QT_PATCH_VERSION[[:space:]]+=[[:space:]]+([0-9]+)[[:space:]]*$/\1/p" < "$qconfig_pri")

    [ -z "$ver_major" -o -z "$ver_minor" -o -z "$ver_patch" ] && \
        die "Could not determine Qt version number in '$qconfig_pri'."

    local ver_dots="$ver_major.$ver_minor.$ver_patch"

    echo "Found Qt version: $ver_dots"

    [ -n "$build_num" ] && ver_dots="$ver_dots-$build_num"

    echo "Full version ID:  $ver_dots"

    cmd_cleanup

    #--------------------------------------------------------------------------
    # commons
    #--------------------------------------------------------------------------

    local pkg_name="qt"

    local designer_dlls="bin/QtDsg*.dll"
    local designer_plugin_dirs="designer|qmltooling"

    #--------------------------------------------------------------------------
    # runtime package
    #--------------------------------------------------------------------------

    local full_pkg_name="qt"
    local out_base="$out_dir/$full_pkg_name/$pkg_name-$ver_dots"

    # Readmes
    cp_files_inst_out "LGPL_EXCEPTION.txt"
    cp_files_inst_out "LICENSE.*"
    cp_files_inst_out "README"
    cp_files_inst_out "changes-$ver_major.$ver_minor.$ver_patch"
    cp_files_inst_out "README.OS2"
    cp_files_inst_out "CHANGES.OS2"
    run $cp "$script_dir/INSTALL.OS2" "$out_base/"

    # DLLs
    cp_exe_files_inst_out "bin/Qt*.dll" "$designer_dlls"

    # Imports
    cp_files_inst_out "imports"

    # Plugins
    for d in $inst_base/plugins/*; do
        local dn=${d##*/}
        eval "case $dn in $designer_plugin_dirs) continue;; esac"
        cp_exe_files_inst_out "plugins/$dn/*.dll"
    done

    # Translations
    cp_files_inst_out "translations/qt_*"
    cp_files_inst_out "translations/qt_help_*"
    cp_files_inst_out "translations/qtconfig_*"

    # qt.conf
    echo \
"[Paths]
Prefix = ..
Settings = \$(ETC)/xdg
Examples = examples
Demos = demos" \
    > "$out_base/bin/qt.conf"

    create_zips

    #--------------------------------------------------------------------------
    # development package
    #--------------------------------------------------------------------------

    local full_pkg_name="qt-develop"
    local out_base="$out_dir/$full_pkg_name/$pkg_name-$ver_dots"

    # Readmes
    cp_files_inst_out "LGPL_EXCEPTION.txt"
    cp_files_inst_out "LICENSE.*"
    cp_files_inst_out "README"
    cp_files_inst_out "changes-$ver_major.$ver_minor.$ver_patch"
    cp_files_inst_out "README.OS2"
    cp_files_inst_out "CHANGES.OS2"
    run $cp "$script_dir/INSTALL.OS2.develop" "$out_base/"

    # EXEs & DLLs
    cp_exe_files_inst_out "bin/*.exe"
    cp_exe_files_inst_out "$designer_dlls"

    # Demos
    cp_files_inst_out "demos"

    # Doc (no html, qch only)
    cp_files_inst_out "doc/qch"
    cp_files_inst_out "q3porting.xml"

    # Examples
    cp_files_inst_out "examples"

    # Includes
    cp_files_inst_out "include"

    # Libraries
    cp_files_inst_out "lib/*.prl"
    cp_files_inst_out "lib/*.lib"

    # Mkspecs
    cp_files_inst_out "mkspecs"

    # Phrasebooks
    cp_files_inst_out "phrasebooks"

    # Plugins
    for d in $inst_base/plugins/*; do
        local dn=${d##*/}
        eval "case $dn in $designer_plugin_dirs) ;; *) continue;; esac"
        cp_exe_files_inst_out "plugins/$dn/*.dll"
    done

    # Translations
    cp_files_inst_out "translations/assistant_*"
    cp_files_inst_out "translations/designer_*"
    cp_files_inst_out "translations/linguist_*"

    create_zips

    cmd_cleanup

    echo "ALL DONE."
}

#
# Main
#

script_path=$(readlink -e $0)
script_dir=${script_path%/*}
script_name=$(basename $0)

start_dir=$(pwd)

[ -z "$out_dir" ] && out_dir="."
out_dir=$(readlink -m "$out_dir")

# Parse arguments

cmd_help()
{
    echo \
"
Usage:
  $script_name all [options]    Create ZIPs.
  $script_name cleanup          Remove what this script creates (except ZIPs).

Options:
  <instdir>     (*) Qt installation tree location
  <bldnum>          Build number [none]
"
}

case "$1" in
    cleanup) cmd_cleanup;;
    all)
        if [ -n "$2" ]; then
            cmd_create $(echo "$2" | tr '\\' '/') "$3"
        else
            cmd_help
        fi;;
    -h|-?|--help|*) cmd_help;;
esac

# end of story

exit 0
