#!/bin/sh
#
# Copyright (C) 2017-2018, 2020  Etersoft
# Copyright (C) 2017-2018, 2020  Vitaly Lipatov <lav@etersoft.ru>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#


# args: pkgname/repackscript
get_repack_script()
{
    local repackcode="$1"
    is_abs_path "$repackcode" || repackcode="$EPM_REPACK_SCRIPTS_DIR/$1.sh"
    echo "$repackcode"
}

# args: pkgname/repackscript
has_repack_script()
{
    [ -s "$(get_repack_script "$1")" ]
}

# args: pkgname/repackscript buildroot spec
__apply_fix_code()
{
    local repackcode="$(get_repack_script "$1")"
    [ -s "$repackcode" ] || return 0
    [ -f "$repackcode.rpmnew" ] && warning 'There is .rpmnew file(s) in $EPM_REPACK_SCRIPTS_DIR dir. The pack script can be outdated.'

    shift
    [ "$PROGDIR" = "/usr/bin" ] && SCPATH="$PATH" || SCPATH="$PROGDIR:$PATH"
    local bashopt=''
    [ -n "$debug" ] && bashopt='-x'
    ( unset EPMCURDIR ; export PATH=$SCPATH ; docmd $CMDSHELL $bashopt $repackcode "$1" "$2" "$3" "$4" "$5" ) || fatal 'There is an error from $repackcode script'
}

__create_rpmmacros()
{
    cat <<EOF >$HOME/.rpmmacros
%_topdir    $HOME/RPM
%_tmppath    $TMPDIR

%packager    EPM <support@eepm.ru>
%_vendor    EEPM
%_gpg_name    support@etersoft.ru
# TODO: use special user for repack (instead of root of local user)
%_allow_root_build    1
EOF
    remove_on_exit "$HOME/.rpmmacros"
}

# will set RPMBUILD
__assure_exists_rpmbuild()
{
    # checking both if they already installed
    RPMBUILD=/usr/bin/eepm-rpmbuild
    if [ -x $RPMBUILD ] ; then
        info "will use eepm-rpmbuild for rpm packing"
        export EPM_RPMBUILD=$RPMBUILD
        return
    fi

    RPMBUILD=/usr/bin/rpmbuild
    [ -x "$RPMBUILD" ] && return


    # try install eepm-rpm-build
    RPMBUILD=/usr/bin/eepm-rpmbuild
    try_assure_exists $RPMBUILD eepm-rpm-build

    if [ -x $RPMBUILD ] ; then
        info "will use eepm-rpmbuild for rpm packing"
        export EPM_RPMBUILD=$RPMBUILD
        return
    fi


    # return to the default
    RPMBUILD=/usr/bin/rpmbuild

    # TODO: check for all systems
    case $PKGFORMAT in
        rpm)
            assure_exists $RPMBUILD rpm-build
            ;;
        deb)
            assure_exists $RPMBUILD rpm
            ;;
    esac
}


__epm_check_repacked_package_req()
{
    local name="$1"
    local grep_flag="$2"
    local alf="$CONFIGDIR/reqstoplist.list"
    [ -s "$alf" ] || return 0
    [ -n "$name" ] || return 0
    local tmpalf=$(__convert_pkgallowscripts_to_regexp "$alf")
    remove_on_exit $tmpalf
    [ -n "$verbose" ] && echo "reqstop rules: $(cat $tmpalf)"
    ! echo "$name" | grep $grep_flag -f $tmpalf
    local res=$?
    rm $tmpalf
    return $res
}


epm_check_repacked_rpm()
{
    local pkg="$1"
    [ -n "$force" ] && return

    [ -z "$quiet" ] && info 'Checking for forbidden requires of $pkg package ...'
    local req="$(epm --quiet requires "$pkg")"

    # don't check requires marked as epm-forced-req in Provides:
    local forcedreq="$(epm --quiet provides "$pkg" | sed -n 's/^epm-forced-req(\(.*\))$/\1/p')"
    req="$(estrlist exclude "$forcedreq" "$req" | xargs -n 1000 echo)"

    __epm_check_repacked_package_req "$req" -q && return
    warning 'There are forbidden requires in $pkg package:'
    __epm_check_repacked_package_req "$req"
    fatal "Unnecessary dependencies appear due to incorrect packaging. Check the repack rule."
}


# will fills repacked_pkg var
__epm_repack_to_rpm()
{
    local pkg="$1"
    local packversion="$2"
    local packrelease="$3"

    # Note: install epm-repack for static (package based) dependencies
    assure_exists cpio
    assure_exists alien
    assure_exists fakeroot

    # will set RPMBUILD
    __assure_exists_rpmbuild

    umask 022

    # TODO: improve
    if echo "$pkg" | grep -q "\.deb" ; then
        assure_exists dpkg
        # TODO: Для установки требует: /usr/share/debconf/confmodule но пакет не может быть установлен
        # assure_exists debconf
    fi

    local alpkg
    local abspkg
    local tmpbuilddir

    repacked_pkg=''

        # TODO: keep home?
        HOME="$(mktemp -d --tmpdir=$BIGTMPDIR)" || fatal
        unset BASH_ENV
        remove_on_exit $HOME
        export HOME
        __create_rpmmacros

        tmpbuilddir=$HOME/tmp-$(basename $pkg).tmpdir
        mkdir $tmpbuilddir
        abspkg="$(realpath $pkg)"
        info
        info 'Repacking $abspkg to local rpm format (inside $tmpbuilddir) ...'

        alpkg=$(basename $pkg)
        # don't use abs package path: copy package to temp dir and use there
        __epm_repack_copy $abspkg $tmpbuilddir/../$alpkg
        [ -r "$pkg.eepm.yaml" ] && cp $verbose $pkg.eepm.yaml $tmpbuilddir/../$alpkg.eepm.yaml

        cd $tmpbuilddir/../ || fatal
        # fill alpkg and SUBGENERIC
        __prepare_source_package "$(pwd)/$alpkg" "$packversion"
        # override abspkg
        abspkg="$(realpath $alpkg)"
        cd $tmpbuilddir/ || fatal

        local fakeroot
        fakeroot=''
        ! is_root && is_command fakeroot && fakeroot='fakeroot'

        if [ -n "$verbose" ] || [ -n "$debug" ] ; then
            verbose1="$verbose"
            [ -n "$debug" ] && verbose1="--veryverbose"
            docmd $fakeroot alien --generate --to-rpm $verbose1 $scripts "../$alpkg" || fatal
        else
            showcmd $fakeroot alien --generate --to-rpm $scripts "../$alpkg"
            a='' $fakeroot alien --generate --to-rpm $scripts "../$alpkg" >/dev/null || fatal
        fi

        # remove all empty dirs (hack against broken dpkg with LF in the end of line) (hack for linux_pantum.deb)
        rmdir * 2>/dev/null

        local subdir="$(echo *)"
        [ -d "$subdir" ] || fatal "can't find subdir in" $(pwd)

        local buildroot="$tmpbuilddir/$subdir"

        # for tarballs fix permissions (ideally fix in pack.d/generic-tar.sh, but there is tar repacking only)
        [ "$SUBGENERIC" = "tar" ] && chmod $verbose -R a+rX $buildroot/*

        # detect spec and move to prev dir
        local spec="$(echo $buildroot/*.spec)"
        [ -s "$spec" ] || fatal "Can't find spec $spec"
        mv $spec $tmpbuilddir || fatal
        spec="$tmpbuilddir/$(basename "$spec")"

        local pkgname="$(grep "^Name: " $spec | sed -e "s|Name: ||g" | head -n1)"

        # run generic scripts and repack script for the pkg
        cd $buildroot || fatal

        local repackscript="$pkgname"
        [ -n "$EPM_REPACK_SCRIPT" ] && repackscript="$EPM_REPACK_SCRIPT"

        __apply_fix_code "generic"             $buildroot $spec $pkgname $abspkg $SUBGENERIC
        __apply_fix_code "generic-$SUBGENERIC" $buildroot $spec $pkgname $abspkg
        __apply_fix_code $repackscript         $buildroot $spec $pkgname $abspkg
        if ! has_repack_script $repackscript ; then
            __apply_fix_code "generic-default" $buildroot $spec $pkgname $abspkg
        fi
        __apply_fix_code "generic-post"        $buildroot $spec $pkgname $abspkg
        cd - >/dev/null

        # reassign package name (could be renamed in fix scripts)
        pkgname="$(grep "^Name: " $spec | sed -e "s|Name: ||g" | head -n1)"

        if [ -n "$packversion" ]; then
            sed -i "s|^Version: .*|Version: $packversion|" "$spec"
        fi
        if [ -n "$packrelease" ]; then
            sed -i "s|^Release: .*|Release: $packrelease|" "$spec"
        fi

        if [ -n "$EEPM_INTERNAL_PKGNAME" ] && [ -z "$force" ]; then
            if ! estrlist contains "$pkgname" "$EEPM_INTERNAL_PKGNAME" ; then
                fatal 'Some bug: the name of the repacking package ($pkgname) differs with the package name ($EEPM_INTERNAL_PKGNAME) from play.d script.'
            fi
        fi

        TARGETARCH=$(epm print info -a | sed -e 's|^x86$|i586|')

        showcmd $RPMBUILD --buildroot $buildroot --target $TARGETARCH -bb $spec
        if [ -n "$verbose" ] ; then
            a='' $RPMBUILD --buildroot $buildroot --target $TARGETARCH -bb $spec || fatal
        else
            a='' $RPMBUILD --buildroot $buildroot --target $TARGETARCH -bb $spec >/dev/null || fatal
        fi

        # remove copy of source binary package (don't mix with generated)
        rm -f $tmpbuilddir/../$alpkg
        local repacked_rpm="$(realpath $tmpbuilddir/../*.rpm)"
        if [ -s "$repacked_rpm" ] ; then
            remove_on_exit "$repacked_rpm"
            repacked_pkg="$repacked_rpm"
        else
            fatal 'Can'\''t find converted rpm for source binary package $pkg (got $repacked_rpm)'
        fi

        epm_check_repacked_rpm "$repacked_pkg"

        cd "$EPMCURDIR" >/dev/null

    true
}

