#!/bin/sh
#
# Copyright (C) 2014, 2017, 2021  Etersoft
# Copyright (C) 2014, 2017, 2021  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/>.
#

# apt-file like. See also
# https://bugzilla.altlinux.org/show_bug.cgi?id=14449

# convert "http://download.etersoft.ru/pub/ALTLinux/p8/branch x86_64" to ALTLinux/p8/branch/x86_64
get_alt_repo_path()
{
    local DN1=$(dirname "$1")
    local DN2=$(dirname $DN1)
    local DN3=$(dirname $DN2)

    local BN0=$(basename "$1") # arch
    local BN1=$(basename $DN1) # branch/Sisyphus
    local BN2=$(basename $DN2) # p8/ALTLinux
    local BN3=$(basename $DN3) # ALTLinux/

    [ "$BN1" = "branch" ] && echo "$BN3/$BN2/$BN1/$BN0" && return
    [ "$BN1" = "Sisyphus" ] && echo "$BN2/$BN1/$BN0" && return
    # Fallback for non-standard repos: use last 4 path components
    echo "$BN3/$BN2/$BN1/$BN0"
}

# convert "http://download.etersoft.ru/pub/ALTLinux/p8/branch x86_64" to /tmp/epm/ALTLinux/p8/branch/x86_64
get_local_alt_mirror_path()
{
    echo "$epm_cachedir/contents_index/$(get_alt_repo_path "$1")"
}

ALT_CONTENTS_INDEX_LIST=$epm_cachedir/contents_index/contents_index_list

__rsync_check()
{
    a= rsync -n "$1" >/dev/null 2>/dev/null
}

# URL TARGETDIR OPTIONS
rsync_alt_contents_index()
{
    local URL="$1"
    local TD="$2"
    local res
    try_assure_exists rsync || return

    if ! __rsync_check "$URL" ; then
        warning '$URL is not accessible via rsync, skipping contents index update...'
        return 1
    fi

    # FIXME: permissions
    mkdir -p "$(dirname "$TD")"

    [ -n "$USER" ] && [ -f "$TD" ] && sudorun chown -R $USER "$TD"

    if [ -z "$quiet" ] ; then
        docmd rsync --partial --inplace $verbose $3 -a "$URL" "$TD"
    else
        a= rsync --partial --inplace $3 -a "$URL" "$TD"
    fi
    res=$?
    [ -f "$TD" ] && sudorun chmod a+rw "$TD"
    return $res
}

# URL TARGETDIR OPTIONS
eget_alt_contents_index()
{
    local URL="$1"
    local TD="$2"
    local res
    [ -n "$USER" ] && [ -f $TD ] && sudorun chown -R $USER $TD
    eget --compressed -O $TD $URL
    res=$?
    [ -f "$TD" ] && sudorun chmod a+rw "$TD"
    return $res
}

# URL
get_url_to_etersoft_mirror()
{
    local REPOPATH
    local ETERSOFT_MIRROR="rsync://download.etersoft.ru/pub"
    local ALTREPO=$(get_alt_repo_path "$1")
    echo "$ALTREPO" | grep -q "^ALTLinux" || echo "$ALTREPO" | grep -q "^altlinux" || return
    echo "$ETERSOFT_MIRROR/$(echo "$ALTREPO" | sed -E 's@^(ALTLinux|altlinux)/@ALTLinux/contents_index/@')"
}

# "comment" "file"
__add_to_contents_index_list()
{
    [ -n "$verbose" ] && info "Put $1 -> $2"
    [ -s "$2" ] || return
    echo "$2" >>$ALT_CONTENTS_INDEX_LIST
}

# "comment" file file2
__add_better_to_contents_index_list()
{
    if [ -s "$2" ] && [ -s "$3" ] ; then
        [ "$2" -ot "$3" ] && __add_to_contents_index_list "$1" "$3" && return
        __add_to_contents_index_list "$1" "$2" && return
    fi
    [ -s "$2" ] && __add_to_contents_index_list "$1" "$2" && return
    [ -s "$3" ] && __add_to_contents_index_list "$1" "$3" && return
}


check_alt_contents_index()
{
    [ -f "$ALT_CONTENTS_INDEX_LIST" ]
}

clean_alt_contents_index()
{
    sudocmd rm -vf "$ALT_CONTENTS_INDEX_LIST"
    sudocmd rm -rvf "$epm_cachedir/contents_index/"
}

# TODO: use special user for this files?
init_alt_contents_index()
{
    info "Creating local cache for contents_index ..."
    sudocmd mkdir -p "$(dirname $ALT_CONTENTS_INDEX_LIST)"
    sudocmd chmod a+rw "$(dirname $ALT_CONTENTS_INDEX_LIST)"
    sudocmd truncate -s0 $ALT_CONTENTS_INDEX_LIST
    sudocmd chmod a+rw $ALT_CONTENTS_INDEX_LIST
    update_alt_contents_index
}

# fills ALT_CONTENTS_INDEX_LIST
update_alt_contents_index()
{
    load_helper epm-repolist
    check_alt_contents_index || return

    truncate -s0 "$ALT_CONTENTS_INDEX_LIST"

    info "Retrieving contents_index ..."

    mapfile -t URL_LIST < <(
        (quiet=1 epm_repolist) | \
        grep -v " task$" | \
        grep -E "rpm.*(ftp://|http://|https://|rsync://|file:/)" | \
        sed -e "s@.*rpm.*file:/@/@" -e "s@^.*\]@@" -e "s@^rpm *@@"
    )

    for line in "${URL_LIST[@]}"; do
        URL1=$(echo "$line" | awk '{print $1}')
        URL2=$(echo "$line" | awk '{print $2}')
        component=$(echo "$line" | awk '{print $3}')

        [ "$component" = "debuginfo" ] && continue
        URL="$URL1/$URL2"

        [ -n "$verbose" ] && info "Checking $URL ..."
        if is_abs_path "$URL" ; then
            # first check for local mirror
            local LOCALPATH="$(echo "$URL/base")"
            local LOCALPATHGZIP="$(echo "$LOCALPATH" | sed -e "s|/ALTLinux/|/ALTLinux/contents_index/|")"
            __add_better_to_contents_index_list "$URL" "$LOCALPATHGZIP/contents_index.gz" "$LOCALPATH/contents_index"
            continue
        fi

        local LOCALPATH="$(get_local_alt_mirror_path "$URL")"
        # original url, converted to rsync://
        local RSYNCURL="$(echo "$URL" | sed -e "s@\(ftp://\|http://\|https://\)@rsync://@g")" #"
        # mirrored url for contents_index.gz
        local MIRRORURL="$(get_url_to_etersoft_mirror "$RSYNCURL")"

        mkdir -p "$LOCALPATH"

        # we never had x86_64-i586 content_index, see https://bugzilla.altlinux.org/52908
        rhas "$URL" "x86_64-i586" && continue

        # 1. check contents_index.gz via rsync from RSYNCURL
        [ -n "$verbose" ] && info "1.    Local: $LOCALPATH  Remote: $RSYNCURL"

        # don't access via rsync to uknown repos
        if false && [ -n "$RSYNCURL" ] ; then
            if rsync_alt_contents_index "$RSYNCURL/base/contents_index.gz" "$LOCALPATH/contents_index.gz" ; then
                __add_to_contents_index_list "$RSYNCURL" "$LOCALPATH/contents_index.gz"
                continue
            fi
        fi

        # 2. check contents_index.gz via rsync from REMOTEURL
        [ -n "$verbose" ] && info "2.    Local: $LOCALPATH  Remote: $MIRRORURL"
        if [ -n "$MIRRORURL" ] ; then
            [ -n "$verbose" ] && info "Note: Can't retrieve $RSYNCURL/base/contents_index.gz, fallback to $MIRRORURL/base/contents_index.gz"
            if rsync_alt_contents_index "$MIRRORURL/base/contents_index.gz" "$LOCALPATH/contents_index.gz" ; then
                __add_to_contents_index_list "$MIRRORURL" "$LOCALPATH/contents_index.gz"
                continue
            fi
        fi

        if rhas "$URL" "archive/" ; then
            info "Skipping contents_index for archive from $URL"
            continue
        fi

        # TODO: add timestamping to eget and use it
        # 3. check contents_index via eget from RSYNCURL
        [ -n "$verbose" ] && info "Note: Can't retrieve $MIRRORURL/base/contents_index.gz, fallback to $URL/base/contents_index"
        if eget --check-url $URL/base/contents_index.gz ; then
            if eget_alt_contents_index $URL/base/contents_index.gz $LOCALPATH/contents_index.gz ; then
                __add_to_contents_index_list "$URL" "$LOCALPATH/contents_index.gz"
                continue
            fi
        fi

        # 4. check contents_index via eget from REMOTEURL
        if eget --check-url $URL/base/contents_index ; then
            if eget_alt_contents_index $URL/base/contents_index $LOCALPATH/contents_index ; then
                __add_to_contents_index_list "$URL" "$LOCALPATH/contents_index"
                continue
            fi
        fi

        #warning "Can't download contents_index from $URL/base"

    done
}

