#!/bin/bash
# (c) Etersoft 2003-2010
# Author: Vitaly Lipatov <lav@etersoft.ru>
# Public domain
#
# BS - build source
#
# Создаёт пакет с исходниками по спеку
# Параметры:
# - названия спек-файлов
# - или пакетов
# Если указан ключ -s, подписываем пакет
# Если указан ключ --nodeps, не учитываем сборочные зависимости
# Если указан ключ -u, отправляем пакет в incoming
# Если указан ключ -d, удаляем из incoming
# Если указан -n, не проверяем перед отправкой
# TODO: -r

# load common functions, compatible with local and installed script
. `dirname $0`/../share/eterbuild/functions/common
load_mod rpm tarball alt git web

SIGN=
SIGNTAG=
UPLOADNOW=
CHECKONLY=
NOSOURCE=
NOCHECK=
UPDATES=
DELETENOW=
POCKET=
TASKNUMBER=

#############################
Usage="Usage: $name [GIRAR] [-s|-t|-u|-a|-c] [-o -z -n -p --nodeps] [-k [TARGETDIR]] [spec or src.rpm]..."
function mygetopts()
{
name=${0##*/}
Descr="$name - run git repo build or make src.rpm from spec"

phelp()
{
	echog "$Descr"
	echog "$Usage"
	echog "Options:"
	echog " -u - sign and run gear build task after build"
	echog " -a TASK - sign package(s)/repo, push/upload it and add to (shared) task TASK"
	echog " -p POCKET - build package in POCKET (supported on git.etersoft.ru only)"
	echog "Korinf options:"
	#echog " -k [TARGET] - generate src.rpm and publish to TARGET dir (from Source: by default)"
	#echog " -r [RELEASE] - publish to RELEASE target dir version"
	echog "Ext. options:"
	echog " -b REPONAME - binary repository name (4.1, 5.0, 5.1 and so on)"
	echog " -c - only sign package(s) with checking"
	echog " -f - force operation (overwrite tag)"
	echog " -s - sign package(s) (and move it to dir ETERDESTSRPM if defined)"
	echog " -t - set tag with sign"
	echog " -n - do not check with sisyphus_check before upload"
	echog " -o - create nosrc.rpm package"
	echog " -z - create src.rpm with compatible gzip compression"
#	echog " -U - sign package(s) and upload it to Incoming (updates)"
#	echog " -d - remove package(s) from SRPMS and Incoming"
}

while getopts :hfstcuUdnop:a:b:z opt; do
    case $opt in
    h) phelp; exit 0;;
    s) SIGN=1 ;;
    t) SIGNTAG=1 ;;
    f) FORCE="-f" ;;
# FIXME: handle SIGN separately
    c) CHECKONLY=1 ; SIGN=1 ;;
    u) UPLOADNOW=1 ; SIGN=1 ;;
#    U) UPLOADNOW=1 ; SIGN=1 ; UPDATES=1 ;;
    a) UPLOADNOW=1 ; SIGN=1 ; TASKNUMBER=$OPTARG ;;
# see functions/alt:set_binaryrepo() for BINARYREPONAME
    b) BINARYREPONAME=$OPTARG ;;
    n) NOCHECK=1; ;;
    o) NOSOURCE=1; ;;
    p) UPLOADNOW=1 ; SIGN=1 ; POCKET=$OPTARG ;;
    z) export USE_LEGACY_COMPRESSION=1;
       ;;
    d) DELETENOW=1 ;;
    +?) echog "$name: options should not be preceded by a '+'." 1>&2; exit 2;;
#    ?)  echog "$name: $OPTARG: bad option.  Use -h for help." 1>&2 ; exit 2;;
	?) OPTIND=$((OPTIND-1)); break;
    esac
done
 
## remove args that were options
if [ $# -gt 0 ]; then
	shift $((OPTIND - 1))
fi

LISTRPMARGS=$@

}

# create tag according to package release
check_gear_and_tag()
{
	local RESULT=0
	local GEARCTAG=gear-create-tag

	test -n "$TAG" && echo "Create $TAG tag..."
	# FIXME: uncomment use-agent in ~/.gnupg/gpg.conf, but with ssh access to build server I got
	#  gpg: problem with the agent - disabling agent use
	#  gpg: Invalid passphrase; please try again ...

	# gpg tries to use the agent but will fallback to the regular mode
	# if there is a problem connecting to the agent.
	# GPG_AGENT_INFO=

	# set SPECDIR from LISTNAMES if empty
	[ -n "$SPECDIR" ] || set_specdir $LISTNAMES

	if is_gear $SPECDIR ; then
		# needed correct user.name/user.email for get GPG id
		pushd $SPECDIR >/dev/null
		# default: <VERSION>-<RELEASE>
		$GEARCTAG $FORCE || RESULT=1
		test -z "$TAG" || git tag -v "$TAG" || fatal "Tag $TAG is missed in repo"
		popd >/dev/null
	fi
	return $RESULT
}

# SRC.RPM DIR
extract_tarball_to_dest()
{
	local TDIR=$(mktemp -d || fatal "can't create tmp dir")
	cd $TDIR
		cat "$1" | rpm2cpio | cpio -i "*.tar*"
		local TARNAME=$(querypackage $1 "" "%{NAME}-%{VERSION}")
		# FIXME: hack to replace alt release to eter
		local TARGETTARNAME=$(querypackage $1 "" "%{NAME}-%{VERSION}-%{RELEASE}" | sed -e "s/-alt/-eter/g")
		copy_tarball_to_tar_bz2 $TARNAME*.tar* $2/$TARGETTARNAME.tar.bz2
		make_md5sum $2 $TARGETTARNAME.tar.bz2
		# copy other tarballs
		for i in $(ls -1 *.tar* | grep -v "^$TARNAME.*\.tar.*") ; do
			cp -fv $i $2/
			make_md5sum $2 $(basename $i)
		done
	cd -
	rm -f $TDIR/*
	rmdir $TDIR
}

rpmbs_copying_built()
{
	[ -n "$ETERDESTSRPM" ] || return 0
	echog "Moving package(s) in \$ETERDESTSRPM"
	if is_ssh_target "$ETERDESTSRPM" ; then
		scp $LISTBUILT $ETERDESTSRPM && rm -fv $LISTBUILT || echog "Error during copying"
	else
		mkdir -p $ETERDESTSRPM || echog "Error mkdir $ETERDESTSRPM"
		chmod ug+rw $LISTBUILT
		# Publish tarball if target dir is exist
		if [ -d "$ETERDESTSRPM/tarball" ] ; then
			echog "There is tarball dir exists. Extract tarball for other build system compatibility."
			for i in $LISTBUILT ; do
				extract_tarball_to_dest $i $ETERDESTSRPM/tarball
			done
		fi
		mv -fv $LISTBUILT $ETERDESTSRPM || echog "Error during copying"
		make_md5sum "$ETERDESTSRPM"
	fi
}

set_girar_host $1 && shift

parse_cmd_pre_spec "$@"
# quotes brokes option handling
mygetopts $LISTARGS

#############################
LISTBUILT=""
CURDIR=`pwd`

if [ -n "$SIGNTAG" ] ; then
	echo "Set tag..."
	check_gear_and_tag ""
	exit $?
fi

if [ -n "$NOSOURCE" ] ; then
	$RPMBUILD -bs --nosource 0 $LISTNAMES
	exit $?
fi

# set SPECDIR from LISTNAMES if empty
[ -n "$SPECDIR" ] || set_specdir $LISTNAMES

# see functions/alt:set_binaryrepo() for BINARYREPONAME
set_binaryrepo $MENV

# If we build from gear repo, run task
if [ -n "$UPLOADNOW" ] && is_gear $SPECDIR ; then
	echo "Run with gear repo..."
	build_rpms_name "$LISTNAMES"
	# hack: get project name from package name
	PROJECTNAME=$(echo $BASENAME | filter_gear_name)
	#PROJECTNAME=$(get_gear_name)
	pkg_release_check
	TAG=$VERSION-$RELEASE
	check_gear_and_tag "$TAG"  # || fatal "Can't make tag"
	$ETERBUILDBIN/gpush $GIRARHOST $FORCE "$TAG" || fatal "gpush failed. Possibly you need to run ginit for create remote repo. Try \$ gpush $GIRARHOST $TAG command separately"
	$ETERBUILDBIN/gpush $GIRARHOST $FORCE || fatal "gpush failed"
	echo
	echo "Run build $PROJECTNAME at $GIRARHOST"
	if [ -n "$TASKNUMBER" ] ; then
		ssh $GIRARHOST task add $TASKNUMBER repo $PROJECTNAME $TAG 2>&1 | tee $RPMDIR/uploaded.log.tmp
	else
		[ -n "$POCKET" ] && POCKETARG="-p $POCKET" || POCKETARG=""
		ssh $GIRARHOST build -b $BINARYREPO $POCKETARG $PROJECTNAME $TAG 2>&1 | tee $RPMDIR/uploaded.log.tmp
	fi
	# FIXME: incorporate
	cat $RPMDIR/uploaded.log.tmp | grep task | head -n2 | tail -n1 >> $RPMDIR/uploaded.log
	echo "     run $TASKNUMBER task $PROJECTNAME with tag $TAG at $GIRARHOST (in $BINARYREPO) at `date "+%c"`" >>$RPMDIR/uploaded.log
	rm -f $RPMDIR/uploaded.log.tmp
	exit
fi

pack_src_rpm ${LISTRPMARGS}

if [ -n "${DELETENOW}" ]; then
	fatal "Removing did not realized yet"
fi

# if just packing
if [ -z "$SIGN" ]; then
	rpmbs_copying_built
	exit $?
fi

######## Sign src.rpm and upload it

# check package releases according to ALT
pkg_release_check $LISTBUILT

# if only one file
if [ -r "$LISTBUILT" ] ; then
	check_gear_and_tag ""
fi


echog "Will try to sign follow packages with GPG: \$LISTBUILT"
# 1. only rpm command has --addsign 2. do 3 retries
rpm --addsign $LISTBUILT || rpm --addsign $LISTBUILT || rpm --addsign $LISTBUILT
RET=$?
if [ ! "$RET" = "0" ] ; then
	echog "Impossible to sign package. Check your password and try again."
	echog "Wait for ten seconds."
	sleep 10
	exit 1
fi


############################################
echog "Changing permissions..."
chmod 644 -- $LISTBUILT || fatal "can't chmod"
echog -n "Checking with sisyphus_check..."

# TODO: check for ALT specific
# skip some checking for src.rpm if it is local upload
CHECK_OPTIONS=""
[ -n "${UPLOADNOW}" ] || CHECK_OPTIONS="--no-check=$HASHER_NOCHECK"

test -n "$NOCHECK" || sisyphus_check $CHECK_OPTIONS --files $LISTBUILT || fatal "sisyphus check failed"
echog "OK"

# due rpm's find-req
RPMLINT=rpmlint
if which $RPMLINT &>/dev/null ; then
	echog -n "Checking with rpmlint..."
	echo
	$RPMLINT $LISTBUILT
#else
#	echog "It is recommended to install rpmlint package for additional checking"
fi

test -n "$CHECKONLY" && exit 0
############################################

# If upload signed package is not needed
if [ -z "${UPLOADNOW}" ] ; then
	rpmbs_copying_built
	exit $?
fi

echog "Uploading to $GIRARHOST"
check_ssh_key

$RSYNC -vay --partial --progress --checksum \
 	-e ssh $LISTBUILT $GIRARHOST: && \
echo "---------------------" && \
echog "All files synced" || fatal "Error during rsync"

TASKLIST=""
for i in $LISTBUILT ; do
	TASKLIST="$TASKLIST srpm $(basename $i)"
done
if [ -n "$TASKNUMBER" ] ; then
	echo "Add $TASKLIST to task $TASKNUMBER"
	[ -n "$VERBOSE" ] && echo "...with command ssh $GIRARHOST task add $TASKNUMBER $TASKLIST"
	ssh $GIRARHOST task add $TASKNUMBER $TASKLIST 2>&1 | tee $RPMDIR/uploaded.log.tmp
else
	echo "Create task for $TASKLIST"
	[ -n "$VERBOSE" ] && echo "...with command ssh $GIRARHOST build -b $BINARYREPO $TASKLIST"
	ssh $GIRARHOST build -b $BINARYREPO $TASKLIST 2>&1 | tee $RPMDIR/uploaded.log.tmp
fi

# FIXME: parse and incorporate
cat $RPMDIR/uploaded.log.tmp | grep task | head -n2 | tail -n1 >> $RPMDIR/uploaded.log

for i in $LISTBUILT ; do
	# FIXME: more general way
	LOGFILE="$LOGDIR/`basename $i .src.rpm`$MENVARG.log"
	echo >>$LOGFILE
	date >>$LOGFILE
	echo "uploaded">>$LOGFILE
	TEXTADD="     run $TASKNUMBER build src.rpm"
	[ -z "$TASKNUMBER" ] || TEXTADD="     add src.rpm to task $TASKNUMBER"
	echo "$(basename $i) $TEXTADD at $GIRARHOST ($BINARYREPO) at `date "+%c"`" >>$RPMDIR/uploaded.log
done

rm -f $RPMDIR/uploaded.log.tmp

echog "Removing buildroot after upload..."
for i in $LISTNAMES ; do
	if [ -z ${i/*.src.rpm/} ] ; then
		echo "  skipping for $i"
		continue
	fi
	# Hack about paths
	test -f "$i" && NAME=$i || NAME=$CURDIR/$i
	build_rpms_name $NAME
	echo -n "    $BUILDROOT "
	if [ -d "$BUILDROOT" ] ; then
		rm -rf "$BUILDROOT" && echog "DONE" || echog "failed"
	else
		echog "missed"
	fi
done

