#!/bin/bash
# 2003-2010, 2012, 2015, 2017 (c) Etersoft www.etersoft.ru
# Author: Vitaly Lipatov <lav@etersoft.ru>
# Public domain
#
# BPH - backport package with hasher checking

# Used ROOTDIR if defined (for non ALT systems)

# load common functions, compatible with local and installed script
. `dirname $0`/../share/eterbuild/functions/common
load_mod repl rpm git buildsrpm spec branch


#############################

# FIXME: CURRENTBRANCHNAME??
Usage="Usage: $name [-r -u -U -n -i -m -v -q -e] [-b REPONAME] spec..."
function mygetopts()
{
name=${0##*/}
Descr="$name (BackPort and Hasher) - backports spec and rebuild it"

phelp()
{
	echog "$Descr"
	echog "$Usage"
	echo  "Usage: rpmbph [GIRAR] -b $EXAMPLEALTDISTRVERSION for backport to ALT Linux $EXAMPLEALTDISTRVERSION and so on"
	echo
	echog "Options:"
	echog "   -u           sign and upload after build" # will pass to rpmbs/rpmbsh
	echog "   -n           do not build in hasher"
	echog "   -i           install built packages in test hasher" # will pass to rpmbs/rpmbsh
	echog "   -b REPONAME  binary repository name (4.1, p5, t6 and so on)"
	echo
	echog "Ext. options:"
	echog "   -v           more verbose"
	echog "   -q           quiet"
	echog "   -e           sign and run gear test only task girar build"
	echog "   -z           create src.rpm with compatible gzip compression (obsoleted)"
	echo
	echog "Examples:"
	echog " $ rpmbph -b $EXAMPLEALTDISTRVERSION -n -u  - backport to $EXAMPLEALTDISTRVERSION and ask to build it"
#	echog "Set ROOTDIR variable for backport to the other system"
#	echog " -m - send result via e-mail"
}

FORCE=
PASSEDARGS=
while getopts :hnuaeAfvqb: opt; do
    case $opt in
        h) phelp; exit 0 ;;
        n) NOBUILD=1 ;;
        u|e|a|A) PASSEDARGS="$PASSEDARGS -$opt" ;;
        f) FORCE=1 ; PASSEDARGS="$PASSEDARGS -$opt" ;;
        v) VERBOSE=1 ;;
        b) BINARYREPONAME=$OPTARG ;;
        q) QUIET=1 ;;
        +?) echog "$name: options should not be preceded by a '+'." 1>&2; exit 2;;
        ?) OPTIND=$((OPTIND-1)); break;
    esac
done

# remove args that were options
if [ $# -gt 0 ]; then
	[ "$OPTIND" -gt 0 ] && shift $(($OPTIND - 1))
fi

# pass other options
LISTRPMARGS="$PASSEDARGS $*"
}

set_girar_host $1 && shift

parse_cmd_pre_spec "$@"
mygetopts $LISTARGS

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

# assure we have only specs or src.rpm
LISTNAMES=$(repodirs_to_specs $LISTNAMES)

test -z "$LISTNAMES" && fatal "file not found in '$@'"

if [ "$PKGVENDOR" = "alt" ] ; then
	MDISTR=$MENV
	[ "$MDISTR" = "SS" ] && fatal "It makes no sense to backport to Sisyphus (You need to try with -b $EXAMPLEALTDISTRVERSION)."
	# override by defined target version
	DISTRVERSION=$BINARYREPO
else
	MDISTR=LOCAL
fi

[ -n "$VERBOSE" ] && echo "DISTRVERSION=$DISTRVERSION LISTRPMARGS=$LISTRPMARGS"

if [ -z "$BUILDCOMMAND" ] ; then
	[ -n "$NOBUILD" ] && BUILDCOMMAND="$ETERBUILDBIN/rpmbs $GIRARHOST" || BUILDCOMMAND="$ETERBUILDBIN/rpmbsh $GIRARHOST"
fi

# set SPECDIR from LISTNAMES if empty (need for is_gear below)
[ -n "$SPECDIR" ] || set_specdir $LISTNAMES

# if run for ALT inside gear repo, just create backported spec
if [ "$PKGVENDOR" = "alt" ] && is_gear $SPECDIR ; then

	for SPEC in $LISTNAMES ; do

		set_specdir $SPEC
		docmd cd $SPECDIR || fatal

		checkout_original_branch

		is_last_commit_tag || fatal "We allow backport only when last commit has (release) tag"
		LASTTAG="$(get_last_tag)" || fatal "Can't get tag for last tag"

		# set USEBRANCH
		set_usebranch

		# spec name for branch
		BPSPEC=$SPEC.$USEBRANCH

		set_currentbranch

		#[ -f "$BPSPEC" ] && fatal "File $BPSPEC is already exists, check it and remove"
		cp -f $SPEC $BPSPEC || fatal "Can't copy to $BPSPEC"
		# backport spec
		docmd $ETERBUILDBIN/rpmbps -b $BINARYREPO $BPSPEC || fatal

		# checkout to $USEBRANCH
		checkout_bpbranch

		# if version-release from backported spec is already committed
		if [ -z "$FORCE" ] && is_last_commit_tag "$(get_version $BPSPEC)-$(get_release $BPSPEC)" ; then
			info "Tag $(get_last_tag) already exists for the last commit, skipping"
			rm -f $BPSPEC
			# so just skipping
			continue
		fi

		docmd git merge --no-ff $LASTTAG

		# override spec conflicts
		docmd mv -f $BPSPEC $SPEC || fatal

		# FIXME: Ctrl-\ and q will cancelled less with return error code
		if [ -z "$QUIET" ] && tty -s ; then
			if [ "$(git diff | wc -l)" = "0" ] ; then
				info "Strange, there is no differences in backported spec."
			else
				( echo "etersoft-build-utils INFO: Please check diff for backported spec:" ; \
				echo "# etersoft-build-utils NOTE: You can press Ctrl-\ for cancel the process."; \
				echo ; git diff ) | less
				[ $? = 0 ] || fatal "Cancelled by user. You are still in $USEBRANCH branch with modified spec."
			fi
		fi

		docmd git add $SPEC
		if ! git_commit_ignore_nothing -a -m "backported to $USEBRANCH as $(get_version $SPEC)-$(get_release $SPEC) (with rpmbph script)" ; then
			#git checkout $CURBRANCH
			fatal "Commit error. You are still in $CURBRANCH branch with modified and uncommitted spec file."
		fi
		cd - >/dev/null
	done

	docmd $BUILDCOMMAND -b $BINARYREPO $LISTRPMARGS $LISTNAMES
	RET=$?

	# TODO: move it to some exit handler?
	# usually it will done in rpmbs after upload
	for SPEC in $LISTNAMES ; do
		set_specdir $SPEC
		docmd cd $SPECDIR || fatal
		checkout_original_branch
		cd - >/dev/null
	done

	exit $RET
fi

# handle src.rpm and spec both, LISTBUILT - result with full paths to src.rpms
pack_src_rpm

export RPMTOPDIR=$(mktemp -d || fatal "can't create tmp dir")
mark_file_to_remove $RPMTOPDIR

# prevent gear detecting (operate inside our dir)
export IGNOREGEAR=1
# NOTE: we can do cd to some other dir...

for i in $LISTBUILT ; do
	uni_rpminstall $i
	# remove primary src.rpm only if src.rpm was not primary
	rhas "$LISTNAMES" "$i" || rm -f $i

	SPECNAME=$RPMTOPDIR/SPECS/$(spec_by_srpm $i)
	test -f "$SPECNAME" || fatal "Spec $SPECNAME is not found"
	docmd $ETERBUILDBIN/rpmbps -b $BINARYREPO $SPECNAME

	docmd $BUILDCOMMAND -b $BINARYREPO $LISTRPMARGS $SPECNAME || fatal "Can't build"
	uni_rpmrm $SPECNAME || true
done

rm -rf $RPMTOPDIR
remove_file_from_remove $RPMTOPDIR
