#!/bin/sh

export PATH=$HOME/bin:$PATH

# send mail on emergency exit if REPOCOP_ADMIN_MAIL is defined
REPOCOP_ADMIN_MAIL=viy@altlinux.org
ARCHDIFFHACK=/usr/share/repocop/pkgtests/unmet-dependency-build-missing-package/_archdiff
REPOCOP_WORKDIR=$HOME/.repocop
ARCHDIFFDIR=$REPOCOP_WORKDIR/testcache/_archdiff
BRANCH=sisyphus
DISTROMAP_REPOSITORY=altlinux

# for mutt to work
mkdir -p ~/Mail

PROG="${0##*/}"
quiet=

DO_rsync=
DO_archdiff=yes
DO_beehive=
DO_repology=
DO_metadatafix=
DO_collect=yes
DO_posttest=yes
DO_report=yes
DO_diff=yes
DO_cybertalk=
DO_prometheus=
DO_distrodb=yes
DO_archive=yes
DO_altnode=yes

# import beehive logs on Tuesdays
# [ `date +%u` = 2 ] && DO_beehive= 

REPOCOP_ARCH=x86_64
REPOCOP_RUN_COLLECT_OPTS=
REPOCOP_RUN_POSTTEST_OPTS=
REPOCOP_REPORT_PROMETHEUS_OPTS=
REPOCOP_REPORT_ACL_OPTS=

[ -e $REPOCOP_WORKDIR/daily.conf ] && . $REPOCOP_WORKDIR/daily.conf

REPODIR=${REPODIR:-~/Sisyphus}
ALLRPMS=${ALLRPMS:-$REPODIR/files/SRPMS $REPODIR/files/noarch/RPMS $REPODIR/files/$REPOCOP_ARCH/RPMS}
SRPMS=${SRPMS:-$REPODIR/files/SRPMS}
FTPDIR=${FTPDIR:-/var/ftp}
ALTNODE_DIR=${ALTNODE_DIR:-$FTPDIR/altnode/`whoami`}
PUBDIR=${PUBDIR:-$FTPDIR/pub/repocop}
PUB_PROMETHEUS1_DIR=${PUB_PROMETHEUS1_DIR:-$PUBDIR/prometeus}
PUB_PROMETHEUS3_DIR=${PUB_PROMETHEUS3_DIR:-$PUBDIR/prometheus3}
ARCHIVE_DIR=${ARCHIVE_DIR:-$PUBDIR/data}
DISTRODB_DIR=${DISTRODB_DIR:-$PUBDIR/data}
REPOCOP_METADATADIR=$REPOCOP_WORKDIR/metadata

Unlink_Except()
{
    local kept_file="$1"
    shift;
    for i in "$@"; do
	[ "$kept_file" != "$i" ] && ! [ -L "$i" ] && rm -f -- "$i"
    done
}

Message()
{
	[ -z "$quiet" ] || return 0
	printf %s\\n "$*"
}

Fatal()
{
	printf %s\\n "$PROG: $*" >&2
	exit 1
}

_emergency_exit()
{
    if [ -n "$DO_altnode" ] && [ -z "$NO_altnode" ]; then
	_altnode_stamp_common
	echo "$*" > $ALTNODE_DIR/repocop_summary
	echo fail > $ALTNODE_DIR/status
    fi
    if [ -n "$REPOCOP_ADMIN_MAIL" ]; then
	local adate=$(date +"%Y%m%d")
	add_repocop_log=
	! [ -f repocop-daily.log ] || add_repocop_log="-a repocop-daily.log"
	(echo "Repocop for $BRANCH have a problem:"; echo "$*"; cat <<EOF
--
Sincerely yours,
Repocop service.
EOF
	) | mutt -x -s "repocop for $BRANCH: aborted at $adate" $add_repocop_log -- "$REPOCOP_ADMIN_MAIL"
    fi
    Fatal "$@"
}

do_rsync()
{
    Message "rsync (nothing to do)..."
}

do_archdiff()
{
    if [ -x $ARCHDIFFHACK ]; then
	Message "running _archdiff hack..."
	$ARCHDIFFHACK "$ARCHDIFFDIR" "$REPODIR" $REPOCOP_ARCH || _emergency_exit "Failed: $ARCHDIFFHACK $ARCHDIFFDIR $REPODIR"
    fi
}

do_beehive()
{
    cmd=/usr/bin/repocop-import-beehive
    if [ -x $cmd ]; then
	if [ -z "$NO_beehive_get" ]; then
	    Message "run (beehive get)..."
	    cmd=repocop-get-beehive
	    $cmd || _emergency_exit "Failed: repocop-get-beehive"
	fi
	Message "run (beehive import)..."
	$cmd || _emergency_exit "Failed: $cmd"
    else
	Message "skip (beehive) - $cmd not found"
    fi
}

do_repology()
{
    cmd=/usr/bin/repocop-import-repology
    if [ -x $cmd ]; then
	if [ -z "$NO_repology_get" ]; then
	    Message "run (repology get)..."
	    cmd=repocop-get-repology
	    $cmd || _emergency_exit "Failed: repocop-get-repology"
	fi
	Message "run (repology import)..."
	$cmd || _emergency_exit "Failed: $cmd"
    else
	Message "skip (repology) - $cmd not found"
    fi
}

do_metadatafix()
{
    cmd=/usr/bin/repocop-report-broken-metadata
    if [ -x $cmd ]; then
	Message "run (broken metadata fix)..."
	$cmd > broken_metadata.ls || _emergency_exit "Failed: $cmd"
	[ -s broken_metadata.ls ] || return
	repocop-purge-given --novacuum `cat broken_metadata.ls`
    else
	Message "skip (broken metadata fix) - $cmd not found"
    fi
}

do_collect()
{
    Message "run (collect)..."
    # if repocop-run exited abnormally it should just stop
    repocop-run --no-posttest $REPOCOP_RUN_COLLECT_OPTS $ALLRPMS || _emergency_exit "Failed: repocop-run --no-posttest $REPOCOP_RUN_COLLECT_OPTS $ALLRPMS"
    vacuum_opt=--novacuum
    [ -z "$NO_vacuum" ] && [ `date +%u` = 3 ] && vacuum_opt=--vacuum
    [ -n "$DO_vacuum" ] && vacuum_opt=--vacuum
    repocop-purge-except --last-run $vacuum_opt || _emergency_exit "Failed: repocop-purge-except --last-run $vacuum_opt"
}


do_posttest()
{
    Message "run (posttest)..."
    # if repocop-run exited abnormally it should just stop
    repocop-run --no-collect --posttest --distrotest $REPOCOP_RUN_POSTTEST_OPTS || _emergency_exit "Failed: repocop-run --no-collect --posttest --distrotest $REPOCOP_RUN_POSTTEST_OPTS"
}

do_diff()
{
    cmd=/usr/bin/repocop-report-diff
    if [ -x $cmd ]; then
	Message "diff..."
	$cmd --write-report $REPOCOP_REPORT_ACL_OPTS $REPOCOP_WORKDIR/testcache/specfile
    fi
}

check_pubdir()
{
    [ -d $PUBDIR ] && [ -w $PUBDIR ] && [ -x $PUBDIR ] && return;
    echo "ERROR: bad permissions for PUBDIR: $PUBDIR"
    exit 1
}

do_report()
{
    cmd=/usr/bin/repocop-report-txt
    if [ -x $cmd ]  && [ -z "$NO_report_txt" ]; then
	Message "report (txt)..."
	$cmd --report experimental $REPOCOP_REPORT_ACL_OPTS $REPOCOP_REPORT_TXT_OPTS
    fi
    cmd=/usr/bin/repocop-report-html
    if [ -x $cmd ]  && [ -z "$NO_report_html" ]; then
	Message "report (html)..."
	$cmd --report experimental $REPOCOP_REPORT_ACL_OPTS $REPOCOP_REPORT_HTML_OPTS
    fi
    rsync -a --delete-after $REPOCOP_WORKDIR/reports $PUBDIR/
}

do_cybertalk()
{
    cmd=/usr/bin/repocop-report-email
    if [ -x $cmd ] && [ -n "$REPOCOP_CYBERTALK_EMAIL" ]; then
	Message "cybertalk..."
	$cmd "$REPOCOP_CYBERTALK_EMAIL"
    fi
}

# ----- prometheus -----------
do_prometheus()
{
    cmd=/usr/bin/repocop-report-prometheus-dump
    if [ -x $cmd ]; then
	Message "prometheus..."
	mkdir -p $PUB_PROMETHEUS1_DIR
	$cmd --out $PUB_PROMETHEUS1_DIR/repocop-prometeus.sql.gz
	stat $PUB_PROMETHEUS1_DIR/repocop-prometeus.sql.gz --format %y > $PUB_PROMETHEUS1_DIR/timestamp
    fi
    cmd=/usr/bin/repocop-report-packages.altlinux
    if [ -x $cmd ]; then
	Message "packages.altlinux (json)..."
	CURDATA=`date '+%Y%m%d'`
	mkdir -p $PUB_PROMETHEUS3_DIR
	outprefix=packages.altlinux-$BRANCH${DISTROMAP_COMPONENT:+-"$DISTROMAP_COMPONENT"}
	rm -f $PUB_PROMETHEUS3_DIR/$outprefix-$CURDATA.json.bz2
	$cmd --branch $BRANCH ${DISTROMAP_COMPONENT:+--component "$DISTROMAP_COMPONENT"} --out $PUB_PROMETHEUS3_DIR/$outprefix-$CURDATA.json.bz2
	ln -sf $PUB_PROMETHEUS3_DIR/$outprefix-$CURDATA.json.bz2 $PUB_PROMETHEUS3_DIR/$outprefix.json.bz2
	Unlink_Except $PUB_PROMETHEUS3_DIR/$outprefix-$CURDATA.json.bz2 $PUB_PROMETHEUS3_DIR/$outprefix-*.json.bz2
    fi
}
# ---- end prometheus ----

Pack_and_Rotate()
{
    local destdir=$1
    local fileprefix=$2
    shift;shift;
    mkdir -p $destdir/ || _emergency_exit "Pack_and_Rotate: Failed: mkdir -p $destdir/"
    local CURDATA=`date '+%Y%m%d'`
    local suffix=${REPOCOP_ARCHIVE_SUFFIX:-gz}
    # tar czf too slow for sequential gzip
    local compress_program=pigz
    case $suffix in
	gz) compress_program=pigz ;;
	bz*) compress_program=bzip2 ;;
	xz) compress_program=xz ;;
	zst) compress_program=pzstd ;;
    esac
    rm -rf $destdir/$fileprefix-$CURDATA.tar.$suffix
    tar --use-compress-program="$compress_program" -cf $destdir/$fileprefix-$CURDATA.tar.$suffix "$@" \
	|| _emergency_exit "Pack_and_Rotate: Failed: tar czf $destdir/$fileprefix-$CURDATA.tar.$suffix "$@""
    ln -sf $fileprefix-$CURDATA.tar.$suffix $destdir/$fileprefix-current.tar.$suffix
    Unlink_Except $destdir/$fileprefix-$CURDATA.tar.$suffix $destdir/$fileprefix*
}

check_distrodb()
{
    [ -d $DISTRODB_DIR ] || mkdir -p $DISTRODB_DIR
    [ -d $DISTRODB_DIR ] && [ -w $DISTRODB_DIR ] && [ -x $DISTRODB_DIR ] && return;
    echo "ERROR: bad permissions for DISTRODB_DIR: $DISTRODB_DIR"
    exit 1
}

do_distrodb()
{
    cmd=/usr/bin/repocop-report-distrodb
    if [ -x $cmd ]; then
	Message "distrodb..."
	$cmd --branch $BRANCH ${DISTROMAP_COMPONENT:+--component "$DISTROMAP_COMPONENT"}
	distrodb_main_file=repocop-distrodb-$BRANCH${DISTROMAP_COMPONENT:+-$DISTROMAP_COMPONENT}
	distrodb_extra_file=repocop-distrodb-extra-$BRANCH${DISTROMAP_COMPONENT:+-$DISTROMAP_COMPONENT}
	# pushd ~ due to *.raw
	pushd ~
	    Pack_and_Rotate $DISTRODB_DIR $distrodb_extra_file  -C ~ .cache/distrodb/$DISTROMAP_REPOSITORY/$BRANCH/*.raw
	    Pack_and_Rotate $DISTRODB_DIR $distrodb_main_file  -C ~ --exclude '*.raw*' .cache/distrodb/$DISTROMAP_REPOSITORY/$BRANCH
	popd
    fi
}

check_archive()
{
    [ -d $ARCHIVE_DIR ] && [ -w $ARCHIVE_DIR ] && [ -x $ARCHIVE_DIR ] && return;
    if [ "$ARCHIVE_DIR" = "$PUBDIR/data" ] && [ -d "$PUBDIR" ] && [ -w "$PUBDIR" ]; then
	mkdir "$PUBDIR/data" && return;
    fi
    echo "ERROR: bad permissions for ARCHIVE_DIR: $ARCHIVE_DIR"
    exit 1
}

do_archive()
{
    Message "archive..."
    _wd_base=`basename "$REPOCOP_WORKDIR"`
    _wd_dir=`dirname "$REPOCOP_WORKDIR"`
    Pack_and_Rotate $ARCHIVE_DIR repocop-data  -C "$_wd_dir" "$_wd_base"/testcache "$_wd_base"/db "$_wd_base"/testdb* ${DO_archive_data_reports:+"$_wd_base"/reports}
    if [ -z "$NO_archive_extra" ]; then
	! [ -d $REPOCOP_WORKDIR/reports/diff ] || Pack_and_Rotate $ARCHIVE_DIR repocop-report -C "$_wd_dir" "$_wd_base"/reports/diff "$_wd_base"/reports/txt
	! [ -d $REPOCOP_WORKDIR/testcache/watch ] || Pack_and_Rotate $ARCHIVE_DIR repocop-watchfiles -C $REPOCOP_WORKDIR/testcache watch
	! [ -d $REPOCOP_WORKDIR/testcache/specfile ] || Pack_and_Rotate $ARCHIVE_DIR repocop-specfiles -C $REPOCOP_WORKDIR/testcache specfile
	rm -f $ARCHIVE_DIR/freedesktop-desktop.db
	if [ -f $REPOCOP_WORKDIR/db/freedesktop-desktop.db ]; then
	    workdir_dev_id=$(stat -c "%d" "$REPOCOP_WORKDIR")
	    archive_dev_id=$(stat -c "%d" "$ARCHIVE_DIR")
	    if [ "$workdir_dev_id" -eq "$archive_dev_id" ]; then
		echo "same filesystem, hardlinking freedesktop-desktop.db"
		ln -f $REPOCOP_WORKDIR/db/freedesktop-desktop.db $ARCHIVE_DIR/
	    else
		echo "different filesystems, copy freedesktop-desktop.db"
		cp -a $REPOCOP_WORKDIR/db/freedesktop-desktop.db $ARCHIVE_DIR/
	    fi
	fi
    fi
}

_altnode_stamp_common()
{
    echo repocop > $ALTNODE_DIR/type
    echo $BRANCH > $ALTNODE_DIR/platform
    echo ${DISTROMAP_COMPONENT:+$DISTROMAP_COMPONENT/}$BRANCH > $ALTNODE_DIR/repository
    echo ${PUBDIR##$FTPDIR/}/reports > $ALTNODE_DIR/relative_path
    date +'%F %T %Z' > $ALTNODE_DIR/datastring
}

do_altnode()
{
    Message "altnode..."
    _altnode_stamp_common
    repocop-report-total-messages > $ALTNODE_DIR/repocop_summary
    echo ok > $ALTNODE_DIR/status
}

while [ "$#" -ge 1 ]; do
	case "$1" in
		-q|--quiet) quiet=-q
			;;
		-v|--verbose) quiet=
			;;
		-h|--help) show_help
			;;
		--) shift; break
			;;
		--no-[a-z]*)
			arg="NO_${1##--no-}"
			eval $arg=1
			;;
		--[a-z]*)
			arg="DO_${1##--}"
			eval $arg=1
			;;
		*) Fatal "unrecognized option: $1"
			;;
	esac
	shift
done

latest_symlink=
if [ -n "$REPO_LATEST_SYMLINK" ]; then
    [ -L "$REPO_LATEST_SYMLINK" ] || _emergency_exit "Bad REPO_LATEST_SYMLINK $REPO_LATEST_SYMLINK: not a symlink."
    latest_symlink=`readlink "$REPO_LATEST_SYMLINK"`
    [ -n "latest_symlink" ] || _emergency_exit "failed to readlink $REPO_LATEST_SYMLINK"
    if [ -e $REPOCOP_METADATADIR/repo_symlink_processed ]; then
	processed_symlink=`cat $REPOCOP_METADATADIR/repo_symlink_processed`
	if [ "$latest_symlink" = "$processed_symlink" ]; then
	    exit 0
	fi
    fi
    repocop-workdir-lock --is-locked-by-others $$ && exit 0 ||:
fi
repocop-workdir-lock --lock $$ || _emergency_exit "can't lock the workdir. "`repocop-workdir-lock $$`

# Failsafe tmp cleanup
me=`whoami`
[ -d /tmp/.private/$me ] && for i in /tmp/.private/$me/*; do rm -rf $i; done

[ -n "$DO_rsync" ] && [ -z "$NO_rsync" ] && do_rsync
[ -n "$DO_archdiff" ] && [ -z "$NO_archdiff" ] && do_archdiff
[ -n "$DO_beehive" ] && [ -z "$NO_beehive" ] && [ -z "$NO_import" ] && do_beehive
[ -n "$DO_repology" ] && [ -z "$NO_repology" ] && [ -z "$NO_import" ] && do_repology
[ -n "$DO_metadatafix" ] && [ -z "$NO_metadatafix" ] && do_metadatafix
[ -n "$DO_collect" ] && [ -z "$NO_collect" ] && do_collect
[ -n "$DO_posttest" ] && [ -z "$NO_posttest" ] && do_posttest
[ -n "$DO_diff" ] && [ -z "$NO_diff" ] && do_diff
[ -n "$DO_report" ] && [ -z "$NO_report" ] && check_pubdir && do_report
[ -n "$DO_cybertalk" ] && [ -z "$NO_cybertalk" ] && do_cybertalk
[ -n "$DO_prometheus" ] && [ -z "$NO_prometheus" ] && check_pubdir && do_prometheus
[ -n "$DO_distrodb" ] && [ -z "$NO_distrodb" ] && check_distrodb && do_distrodb
[ -n "$DO_archive" ] && [ -z "$NO_archive" ] && check_archive && do_archive
[ -n "$DO_altnode" ] && [ -z "$NO_altnode" ] && do_altnode

if [ -n "$REPO_LATEST_SYMLINK" ]; then
    mkdir -p $REPOCOP_METADATADIR/
    echo "$latest_symlink" > $REPOCOP_METADATADIR/repo_symlink_processed
fi

repocop-workdir-lock --unlock $$
exit 0
