#!/usr/bin/bash
#
# build_util_rpm - build RPMs for perl-Fidoconfig-Token, perl-Husky-Rmfiles
#                  and perl-Husky-util
# Author: Michael Dukelsky, 2:5020/1042
#

# Replace the lines between the two parentheses with your versions
# of already built RPMs of hpt and the libraries it depends on.
# The filenames should begin with huskylib, smapi, fidoconf, areafix, hpt.
hptlist=(
huskylib-1.9.20201016C-5.el7.x86_64.rpm \
smapi-2.5.20201016C-3.el7.x86_64.rpm \
fidoconf-1.9.20201016C-3.el7.x86_64.rpm \
areafix-1.9.20201103C-3.el7.x86_64.rpm \
hpt-1.9.20201109C-3.el7.x86_64.rpm
)

############### Nothing to change below this line ####################
VERSION="1.0"

show_help()
{
    cat <<EOF
Clone git repository and build RPMs for Husky Perl utilities and for the Perl
modules they depend on. This script may be used in Fedora, Centos Stream, RHEL,
Amazon Linux 2, Centos and other Linux distributions repackaged from RHEL.
Before using the script you have to replace filenames with your versions of
RPMs for hpt and the libraries it depends on at the beginning of the script.

Usage:
    build_util_rpm [-b|--build] [{--rootdir|--rootdirectory}{ |=}{DIRECTORY}]
                  [{--hptdir|--hptdirectory}{ |=}{DIRECTORY}]
                  [{--builddir|--builddirectory}{ |=}{DIRECTORY}]
                  [-v|--version] [-h|-\?|--help]
Options:
    -b
    --build.
        build libraries and hpt

    --rootdir DIRECTORY
    --rootdirectory DIRECTORY
    --rootdir=DIRECTORY
    --rootdirectory=DIRECTORY
        create subdirectory DIRECTORY in the current directory or create an
        absolute path if DIRECTORY begins with '/' and cd into it.
        Downloaded sources are saved here. If the option is missing, then the
        current directory is chosen.

    --hptdir DIRECTORY
    --hptdirectory DIRECTORY
    --hptdir=DIRECTORY
    --hptdirectory=DIRECTORY
        directory DIRECTORY containing the previously built RPMs of hpt and
        of the libraries it depends on. It is either an absolute path or a
        subdirectory of the current directory. If the option is missing, then
        the current directory is chosen.

    --builddir DIRECTORY
    --builddirectory DIRECTORY
    --builddir=DIRECTORY
    --builddirectory=DIRECTORY
        create subdirectory DIRECTORY in the rootdirectory. All RPMs will be
        created here and all logs will be written inside it.


    -v
    --version
        print the script version and exit.

    -h
    -?
    --help
        print this help and exit.
EOF
}

die()
{
    printf '%s\n' "$1" >&2
    exit 1
}

dead=0
almost_die()
{
    printf '%s\n' "$1" >&2
    dead=1
}

# Check that the script is not run by root
[ "$(id -u)" -eq 0 ] && die "DO NOT run this as root"

build=0
help=1

# process command line options
while :
do
    case $1 in
        -h|-\?|--help)
            break
            ;;
        -v|--version)
            echo "version = $VERSION"
            exit
            ;;
        --rootdir|--rootdirectory)
            if [ "$2" ]
            then
                rootdirectory="$2"
                help=0
                shift
            else
                die 'ERROR: "--rootdirectory" requires a non-empty option argument'
            fi
            ;;
        --rootdir=?*|--rootdirectory=?*)
            rootdirectory=${1#*=}
            help=0
            ;;
        --rootdir=|rootdirectory=)
            die 'ERROR: "--rootdirectory" requires a non-empty option argument'
            help=0
            ;;
        --hptdir|--hptdirectory)
            if [ "$2" ]
            then
                hptdirectory="$2"
                help=0
                shift
            else
                die 'ERROR: "--hptdirectory" requires a non-empty option argument'
            fi
            ;;
        --hptdir=?*|--hptdirectory=?*)
            hptdirectory=${1#*=}
            help=0
            ;;
        --hptdir=|hptdirectory=)
            die 'ERROR: "--hptdirectory" requires a non-empty option argument'
            help=0
            ;;
        --builddir|--builddirectory)
            if [ "$2" ]
            then
                builddirectory="$2"
                help=0
                shift
            else
                die 'ERROR: "--builddirectory" requires a non-empty option argument'
            fi
            ;;
        --builddir=?*|--builddirectory=?*)
            builddirectory=${1#*=}
            help=0
            ;;
        --builddir=|builddirectory=)
            die 'ERROR: "--builddirectory" requires a non-empty option argument'
            help=0
            ;;
        -b|--build)
            build=1
            help=0
            ;;
        -*)
            printf 'WARN: Unknown option (ignored): %s\n' "$1" >&2
            ;;
        *)
            break
    esac
    shift
done

if [ $help -eq 1 ]
then
    show_help
    exit
fi

# check whether the necessary utilities are installed
which -v > /dev/null
[ "$?" -ne 0 ] && almost_die "Please install \"which\""

GREP=$(which --skip-alias grep)
[ -z "$GREP" ] && almost_die "Please install \"grep\""

GIT=$(which --skip-alias git)
[ -z "$GIT" ] && almost_die "Please install \"git\""

MOCK=$(which --skip-alias mock)
[ -z "$MOCK" ] && almost_die "Please install \"mock\""

[ "$dead" -ne 0 ] && exit 1


if [ $build -eq 1 ]
then
    # set hptdirectory
    if [ -n "$hptdirectory" ]
    then
        [ "${hptdirectory:0:1}" != '/' ] && hptdirectory="$(pwd)/$hptdirectory"
        [ -d "$hptdirectory" ] || die "##### The directory $hptdirectory does not exist"
    else
        hptdirectory="$(pwd)"
    fi

    # check whether hptlist contains the necessary RPMs
    dead=0
    names=( huskylib smapi fidoconf areafix hpt )
    for name in "${names[@]}"
    do
        is_here=0
        for item in "${hptlist[@]}"
        do
            [ -n "$(echo $item | grep -Po "$name-\S+\.rpm")" ] && is_here=1
        done
        [ "$is_here" -eq 0 ] && almost_die "$name RPM is missing in the hptlist"
    done
    [ "$dead" -ne 0 ] && die "Please list your RPMs of hpt and its libraries at the beginning of this script"

    # Check whether hptlist corresponds to the files in $hptdirectory
    extglob=$(shopt -p extglob)
    shopt -s extglob
    for item in "${hptlist[@]}"
    do
        file_exists=0
        for file in $hptdirectory/*.rpm
        do
            bfile=$(basename "$file")
            if [ "$bfile" = "$item" ]
            then
                file_exists=1
                break
            fi
        done
        if [ "$file_exists" -eq 0 ]
        then
            almost_die "File $item does not exist in $hptdirectory"
            almost_die "The hptlist at the beginning of the script must contain the real file names"
            die "of the hpt and its libraries RPMs you have in $hptdirectory"
        fi
    done
    $extglob

    # set rootdirectory
    if [ -n "$rootdirectory" ]
    then
        [ "${rootdirectory:0:1}" = '/' ] && fullPath="$rootdirectory" || fullPath="$(pwd)/$rootdirectory"
        mkdir -p "$fullPath"
        [ -d "$fullPath" ] || die "##### Could not make directory $fullPath"
        cd "$fullPath"
    else
        fullPath="$(pwd)"
    fi

    # download sources
    $GIT clone https://github.com/huskyproject/util.git
    [ "$?" -ne 0 ] && die "##### Could not clone util.git"

    # start with populating chroot
    echo
    echo "### mock --scrub=all ###"
    echo
    mock --scrub=all
    echo
    echo "### mock --init ###"
    echo
    mock --init

    # prepend $hptdirectory to every element of "${hptlist[@]}"
    for (( i=0; i<"${#hptlist[@]}"; i++ ))
    do
        hptlist[$i]="$hptdirectory/${hptlist[$i]}"
    done

    # install hpt with its libraries in chroot
    echo
    echo "### mock --install ###"
    echo
    mock --install ${hptlist[*]}
    [ "$?" -ne 0 ] && die "##### Installing prebuilt Husky RPMs failed"

    resultdir=$(mock --debug-config 2>/dev/null | grep -m 1 -Po "'resultdir': '\K[^',]+")
    srpm_list=

    # make all SRPMs
    for subproject in Fidoconfig-Token Husky-Rmfiles Husky-util
    do
        if [ "$subproject" = "Husky-util" ]
        then
            specpath=util/perl-Husky-util.spec
        else
            specpath=util/$subproject/perl-$subproject.spec
        fi
        ver_major=$($GREP -Po '%global\s+ver_major\s+\K\d+' $specpath)
        ver_minor=$($GREP -Po '%global\s+ver_minor\s+\K\d+' $specpath)
        srcname="$subproject-$ver_major.$ver_minor"
        srcfile="$srcname.tar.gz"
        if [ -f "$fullPath/$srcfile" ]
        then
            echo "##### $srcfile already exists"
        else
            if [ "$subproject" = "Husky-util" ]
            then
                tar --exclude .git \
                    --exclude Fidoconfig-Token \
                    --exclude Husky-Rmfiles \
                    -czf $fullPath/$srcfile util
            else
                pushd util > /dev/null
                tar -czf $fullPath/$srcfile $subproject
                popd > /dev/null
            fi
            srcrpm=$(LANG=C mock -n --buildsrpm --spec "$specpath" --sources "$fullPath/$srcfile")
            [ "$?" -ne 0 ] && die "##### Building srpm from $srcfile failed"
            srcrpm=$resultdir/$(basename $(echo $srcrpm | $GREP -Po 'Wrote:\s+\K.+$'))
            echo
            echo srcrpm=$srcrpm
            echo
            srpm_list+=" $srcrpm"
        fi
    done

    # make RPMs from SRPMs
    echo
    echo "### mock --chain ###"
    echo
    mock -n --localrepo=$builddirectory --chain $srpm_list
fi
