#!/bin/bash
# $Id$

# inital version
# Copyright 2004 Jeroen van Wolffelaar <jeroen@wolffelaar.nl>
#
# Generalized for components (dpkg source format 3.0 (quilt))
# - get language packs as component archives
# - also repackage according to several parameters when told so
# Copyright 2010 J.M. Roth <jmroth@iip.lu>
#
# This script may be distributed under the conditions of the GPL v2

set -e

if [ "$#" -lt 2 ] ; then
	echo "How to call: $0 <VERSION> ( <PACKAGE> [<PACKAGE> ...] | _all )"
	exit 1
fi

if [ ! -d debian ] ; then
    echo "No debian/ directory here. You should use 'debian/rules get-orig-source' instead of calling this script directly. Aborting."
    exit 1
fi

cexit () {
    rm -Rf $@
    exit 100
}

format_supported() {
    # Argument(s): filename

    local f=$(file -b $1 | cut -d' ' -f1 | tr \[:upper:\] \[:lower:\])
    #local ext=$(echo ${1##*.})
    case "$f" in
        gzip | bzip2 | lzma | zip )
            echo $f
            return 0
            ;;
        * )
            return 1
            ;;
    esac
}
format_repackaging_required () {
    # Argument(s): format

    local needs_repackaging="zip" # make sure this is a subset of the formats from format_supported()!
    for i in "$needs_repackaging" ; do
        [ "$1" = "$i" ] && return 0
    done
    return 1
}
repackage () {
    local app=$1
    local comp=$2
    local file=$3
    local fromformat=$4
    local toformat=$5
    local cds=${6:-0}

    local TMPDIR=$(mktemp -d -t repack.XXXXXX)
    # need a second temp dir inside first one, in case we need to change directory structure
    local TMP2=$(mktemp -p $TMPDIR -d)

    # extract the stuff
    case $fromformat in
        zip )
            unzip -q $file -d $TMP2
            ;;
        * )
            if [ "$fromformat" = "$toformat" ] ; then
                # keep format but change directory structure
                tar -C $TMP2 -xf $file
            else
                echo Source format not supported for repackaging: $fromformat
                cexit $TMPDIR $file
            fi
            ;;
    esac

    # change directory structure, if so requested
    local ORIGDIR=$(pwd)
    cd $TMPDIR
    if [ "$cds" -gt 0 ] ; then
        # need to use TMP2 since 'mv * xxx' cannot move xxx to xxx
        dirs=${app}_${comp}.orig
        [ "$cds" -gt 1 ] && dirs=$dirs/$(seq -s/ 2 $cds)/
        mkdir -p $dirs
        mv -t $dirs $TMP2/*
        rmdir $TMP2
        dir=$(ls -1)
    elif [ "$cds" -lt 0 ] ; then
      while [ "$cds" -lt 0 ] ; do
        if [ "$(find . -maxdepth 1 -type f | wc -l)" -gt 0 ] ; then
            echo "Warning: The extraction point contains files, cannot change directory structure"
        elif [ "$(find . -maxdepth 1 -type d ! -iname '.' | wc -l)" -gt 1 ] ; then
            echo "Warning: The extraction point contains more than one directory, cannot change directory structure"
        else
	    # need to use a new directory since 'mv $dir/* .' cannot work if * == $dir or $TMP2
            dir=$(ls -1) # ls minus one
	    mv $dir $TMP2$dir
            mv $TMP2$dir/* .
            rmdir $TMP2$dir
        fi
        cds=$((++cds))
      done
    else
        mv $TMP2/* .
        rmdir $TMP2
    fi
    cd $ORIGDIR

    # repack the stuff
    case $toformat in
        gzip | bzip2 | lzma | xz )
            tar --$toformat -C $TMPDIR -cf $file $(ls $TMPDIR)
            rm -rf $TMPDIR
            return 0
            ;;
        * )
            echo Destination format not supported for repackaging: $toformat
            cexit $TMPDIR $file
            ;;
    esac
}
fetch_rename_go () {
    # Argument(s): app comp

    # component name in .orig.tar must not contain anything else than alphanumeric and dash
    local comp=${2:+-$(echo $2 | tr '_' '-' | tr -dc \[\[:alnum:\]-\])}
    local stor=$1_$DVERSION.orig$comp.tar

    # get the checksum of a potentially existing download
    local md5=
    local sha256=
    for d in . .. ; do
        if [ -f $d/$stor* ] ; then
            md5=$(md5sum $d/$stor* | cut -f1 -d' ')
            sha256=$(sha256sum $d/$stor* | cut -f1 -d' ')
        fi
    done

    # download the file if it's supposed to be repackaged or the checksum didn't match
    if [[ "$RepackDirectoryStructure" != 0 \
	    || ( "$Md5" != "" && "$md5" != "$Md5" ) \
	    || ( "$SHA256" != "" && "$sha256" != "$SHA256" ) ]] ; then
        echo "***>" Going to get ${app}${comp}
        local tmp=$(mktemp -t pget.XXXXXX)
        if ! wget -nv -O$tmp $Url ; then
            echo "failed"
            cexit $tmp
        fi
    else
        echo "Skipping ${app}${comp}..."
        return 0
    fi

    # check downloaded file checksum
    md5=$(md5sum $tmp | cut -f1 -d' ')
    sha256=$(sha256sum $tmp | cut -f1 -d' ')
    if [ -n "$Md5" -a "$md5" != "$Md5" ] ; then
        echo "Warning: MD5 mismatch"
        echo "[MD5] Url  $md5"
        echo "[MD5] info $Md5"
    elif [ -n "$SHA256" -a "$sha256" != "$SHA256" ] ; then
        echo "Warning: SHA256 mismatch"
        echo "[SHA256] Url  $sha256"
        echo "[SHA256] info $SHA256"
    fi

    # check format of downloaded file
    local fmt=$(format_supported $tmp)
    if [ $? -ne 0 ] ; then
        echo This file format is not supported at all by this script, neither for packaging, nor for repackaging. "($fmt)"
        cexit $tmp
    fi

    # repackage if necessary
    if format_repackaging_required $fmt || [ "$RepackDirectoryStructure" -ne 0 ] ; then
        local toformat=xz
        echo "***> Repackaging $1_$2: $fmt >> $toformat ($RepackDirectoryStructure)"
        ##! $2 can be empty, script will break when main app needs repackaging
        repackage $1 $2 $tmp $fmt $toformat $RepackDirectoryStructure # overwrites $tmp
        fmt=$toformat
    else 
        # check if tar actually likes the downloaded file
        if [ "$fmt" != "lzma" ] && ! tar tf $tmp >/dev/null 2>&1; then
            echo $tmp does not seem to be a valid .tar.$fmt file
            cexit $tmp
        fi
    fi

    local gzip=gz
    local bzip2=bz2
    local lzma=lzma
    local xz=xz
    case $fmt in
        gzip )
            stor=$stor.gz
            ;;
        bzip2 )
            stor=$stor.bz2
            ;;
        * )
            stor=$stor.$fmt
            ;;
    esac
    mv $tmp $stor
}

DVERSION=$1
shift

if [ "$1" = "_all" ] ; then
    for i in debian/upstream/*.info ; do
        i=${i#debian/upstream/}
        i=${i%.info}
        el="$el $i"
    done
else 
    el="$@"
fi
for i in $el ; do
    # source the metadata
    if [ ! -f debian/upstream/$i.info ] ; then
        echo Warning: debian/upstream/$i.info does not exist.
        continue
    fi
    . debian/upstream/$i.info
    [ "${Include:-yes}" = "no" ] && continue
    : ${RepackDirectoryStructure:=0}
    
    # check versions
    # - run only if it's the main app (not a component)
    # - check if the info file has same version than argument provided to this script (from changelog)
    if [ -z "$(echo $i | grep _)" -a "$Version" != "$DVERSION" ] ; then
        echo "Notice:" Changelog/rules/.info versions seem to disagree: $i: $UPSTREAM/$DVERSION/$Version
        echo "Enter to continue [Ctrl-C to abort]"
        read x
    fi
    
    app=$(echo $i | cut -d_ -f1)
    comp=$(echo $i | cut -d_ -f2-)${Update:+-u}${Update}
    [ "$comp" = "$app" ] && comp=
    fetch_rename_go $app $comp
    
    unset RepackDirectoryStructure
    unset Include
    unset Version
    unset Update
done

echo "***>" Done
exit 0
