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

# Used ROOTDIR if defined
# Makes backport package to any target platfrom (RPM, DEB, TGZ)
# Релиз строится на основе релиза из Сизифа. Если там был alt4, то здесь будет alt0.M24.4
# TODO: use RPMBUILDARG

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

# for rpm + (d)ash
remove_bashism()
{
	local SPECNAME=$1

	subst "s|^pushd \(.*\)|cd \1 >/dev/null|g" $SPECNAME
	subst "s|^popd|cd - >/dev/null|g" $SPECNAME

	# {1,2} translation
	# FIXME: miss first spaces
	while read -r n ; do
		echo "$n" | grep -v "{.*}" && continue
		eval echo "$n"
	done < $SPECNAME >$SPECNAME.tmp
	[ -e "$SPECNAME.tmp" ] && mv -f $SPECNAME.tmp $SPECNAME
	checkbashisms $SPECNAME
}


altspec_to_local()
{
local i
local TXTRELEASE
local SPECNAME
SPECNAME=$1

BASERELEASE=$(get_numrelease $SPECNAME)
RELEASE=$(get_release $SPECNAME)

ADDFIXCOMMAND=""

# hack against very straight patch command
FIXPATCHFUZZ="%define _default_patch_fuzz 3"

echo "Converting spec $(basename $SPECNAME) to $MDISTR..."

# Set buildreq
if [ "$PKGVENDOR" = "alt" ] ; then
	# FIXME: needed for some backport level...
	#BUILDREQ="BuildRequires: rpm-build-compat >= 0.95"
	BUILDREQ=

	# FIXME: use separate macro list
	if grep -q _sharedstatedir $SPECNAME ; then
		BUILDREQ="BuildRequires: rpm-build-compat >= 1.7.24"
	fi

	# Change release according to alt policy with extensions
	# General rule: alwars alt(N-1).MM.(N)
	docmd set_release $SPECNAME $(get_txtrelease $SPECNAME)$(decrement_release $BASERELEASE).$MDISTR.$BASERELEASE
	ADDDEF=""
	CLEANTEXT=""
	# due new libtool, affected on ALT Linux
	if echo "$MDISTR" | egrep -q "M24|M30|M40|M41|M50" ; then
		ADDFIXCOMMAND="$ADDFIXCOMMAND
%undefine __libtoolize"
	fi
else
	# Hack for allow repack on x86_64 packages with ExclusiveArch: %{ix586}
	[ "$SYSARCH" = "x86_64" ] && subst "s|^ExclusiveArch:.*||g" $SPECNAME
	# Need our compat package and disable strong patch checking
	BUILDREQ="BuildRequires: rpm-build-altlinux-compat >= 0.95 make gcc\n$FIXPATCHFUZZ"
	[ -z "$BUILDCOMMAND" ] && BUILDCOMMAND=$ETERBUILDBIN/rpmbb
	TXTRELEASE=$(get_txtrelease $SPECNAME)
	# HACK: Override release with KORINFTARGETRELEASE if set
	[ -z "$KORINFTARGETRELEASE" ] || TXTRELEASE=$KORINFTARGETRELEASE
	docmd set_release $SPECNAME $TXTRELEASE$BASERELEASE$PKGVENDOR
	test -z "$VERBOSE" || echo "Build package with release $TXTRELEASE"
	ADDDEF="%defattr(-, root, root)"
	CLEANTEXT=""
fi


# FIXME 05.05.2012: it is needed now?
if [ "$PKGVENDOR" = "mdv" ] || [ "$PKGVENDOR" = "pclinux" ] || [ "$PKGVENDOR" = "rosa" ] ; then
	# due new libtool, affected on Mandriva 2009.0
	test -z "$VERBOSE" || echo "Disable libtoolize"
	# FIXME
	#RECONFT="%define _disable_libtoolize 1"
	ADDFIXCOMMAND="$ADDFIXCOMMAND
%define __libtoolize true"
fi

# Do not add BuildReq if already exist
cat $SPECNAME | grep rpm-build-compat &>/dev/null && BUILDREQ=""

# fix readlink -m, introduced by new libtool and missed in RHEL4 (replace with readlink -f)
if [ "$DISTRNAME/$DISTRVERSION" = "ASPLinux/11.2" ] ; then
	test -z "$VERBOSE" || echo "Add subst readlink -m"
	ADDFIXCOMMAND="$ADDFIXCOMMAND
%__subst 's|readlink -m|readlink -f|g' libtool ltmain.sh"
fi

# fix readlink -mv, introduced by new libtool and missed in FreeBSD (replace with realpath)
if [ "$PKGVENDOR" = "freebsd" ] ; then
	test -z "$VERBOSE" || echo "Add subst readlink -mv"
	ADDFIXCOMMAND="$ADDFIXCOMMAND
%__subst 's|readlink -mv|realpath|g' libtool configure ltmain.sh"
fi

# HACK need only for wine on x86_64
if [ "$BUILDARCH" = "x86_64" ] && echo $SPECNAME | grep -q wine ; then
	test -z "$VERBOSE" || echo "Add remove_optflags -m64"
	ADDFIXCOMMAND="$ADDFIXCOMMAND
%remove_optflags -m64"
fi

# fix mktemp using for MCBC
if [ "$PKGVENDOR" = "mcbc" ] ; then
	test -z "$VERBOSE" || echo "Add subst mktemp -dt"
	ADDFIXCOMMAND="$ADDFIXCOMMAND
%__subst 's|mktemp -dt|mktemp -d|g' configure ; %__subst 's|readlink -mv|ls -1|g' configure ltmain.sh"
fi

# Too old problem
TOCHANGELOG=
if [ "$MDISTR" = "M23" ] ; then
	if grep "%configure" $SPECNAME >/dev/null && ! grep "^autoreconf" $i >/dev/null && ! grep "^%__autoreconf" $i >/dev/null ; then
		ADDFIXCOMMAND="$ADDFIXCOMMAND
%__autoreconf"
		TOCHANGELOG="add __autoreconf macros in build section for fix so name problem (by script)"
	fi
fi

LISTBUILDDEP=`print_buildreq $SPECNAME`
LISTREQDEP=`print_pkgreq $SPECNAME`
LISTDEP=`echo $LISTBUILDDEP $LISTREQDEP | xargs -n1 echo | sort -u`
LISTGROUP=`eval_spec $SPECNAME | grep Group | sed -e "s|^.*:||g"  | xargs -n1 echo | sort -u`


# Build replacement rules for spec
ALLREPLRULES=""
[ -n "$VERBOSE" ] && echo "Checking req names for $LISTDEP"

if [ -n "$VERBOSE" ] ; then
	echo -n "Use replacement file: "
	print_pkgrepl_list
	echo
fi

local pkgrepl_list=$(print_pkgrepl_list)
for i in $LISTDEP ; do
	tolocal_anyrepl $i $pkgrepl_list || continue
	#NRL="s!\(.*Req.*\)$REPLRULE1\( |,|\$\)!\1$REPLRULE2\2!g"
	NRL="s!(.*Req.*)$ALTPKGNAME( |,|\$)!\1$TARGETPKGNAME\2!g"
	[ -n "$VERBOSE" ] && echo "Use req rule $NRL"
	ALLREPLRULES="$ALLREPLRULES $NRL;"
done

# Build replacement rules for spec
[ -n "$VERBOSE" ] && echo "Checking group names for $LISTGROUP"
ALLGRPREPLRULES=""
grprepl_list=$(print_grprepl_list)
for i in $LISTGROUP ; do
	tolocal_anyrepl $i $grprepl_list || continue
	#NRL="s!\(Group.*\)$REPLRULE1\( |,|\$\)!\1$REPLRULE2\2!g"
	NRL="s!(Group.*)$ALTPKGNAME( |,|\$)!\1$TARGETPKGNAME\2!g"
	[ -n "$VERBOSE" ] && echo "Use group name rule $NRL"
	ALLGRPREPLRULES="$ALLGRPREPLRULES $NRL;"
done
#echo GRP: $LISTGROUP, ALLGRPREPLRULES: $ALLGRPREPLRULES

# add %defattr to files sections
# FIXME: добавляет ненужные пустые строки
function awk_e1()
{
	[ -n "$ADDDEF" ] &&	awk 'BEGIN{desk=0}{print;if(/^%files/){printf("%s\n", text)}}' text="$ADDDEF" || cat
}

# add clean before %files
function awk_e2()
{
	[ -n "$CLEANTEXT" ] && awk 'BEGIN{desk=0}{if(/^%files/&&desk==0){printf("%s\n\n", text);desk++};print}' text="$CLEANTEXT" || cat
}

# add rpm-build-compat buildreq
function awk_e3()
{
	[ -n "$BUILDREQ" ] && awk 'BEGIN{desk=0}{if(/^%description/&&desk==0){printf("%s\n\n", text);desk++};print}' text="$BUILDREQ" || cat
}

# add commands in build section
function awk_section_build()
{
	[ -n "$ADDFIXCOMMAND" ] && awk 'BEGIN{desk=0}{print;if(/^%build/&&desk==0){printf("%s\n", text);desk++}}' text="$ADDFIXCOMMAND" || cat
}

# apply replacement rules
repl_reqs()
{
	local PREGE
	PREGE="perl -p -e"
	[ -n "$ALLREPLRULES" ] && $PREGE "$ALLREPLRULES" || cat
}

# apply replacement rules
repl_groups()
{
	local PREGE
	PREGE="perl -p -e"
	[ -n "$ALLGRPREPLRULES" ] && $PREGE "$ALLGRPREPLRULES" || cat
}

if [ -n "$VERBOSE" ] ; then
	echo "Requires rules: $ALLREPLRULES"
	echo "Group rules: $ALLGRPREPLRULES"
fi

# apply all rules, awk excludes, remove empty tag lines
mv $SPECNAME $SPECNAME.old &&
	cat $SPECNAME.old | \
		repl_reqs | repl_groups | \
		awk_e1 | awk_e2 | awk_e3 | awk_section_build | \
		sed -e "s|^BuildRequires: *\$||g" | \
		sed -e "s|^BuildPreReq: *\$||g" | \
		sed -e "s|^Requires: *\$||g" | \
		sed -e "s|^Conflicts: *\$||g" | \
		sed -e "s|^Provides: *\$||g" | \
		sed -e "s|^Obsoletes: *\$||g" | \
		cat > $SPECNAME

# Some system does mismatch for Patch: and %patch0, Patch0: and %patch
subst "s|^Patch0:|Patch:|g" $SPECNAME
subst "s|^%patch0 |%patch |g" $SPECNAME

if [ "$PKGVENDOR" != "alt" ] ; then 
	# Due possible using %release in Source: and Patch: names
	subst "s|^\(Source.*\)%release|\1$RELEASE|g" $SPECNAME
	subst "s|^\(Patch.*\)%release|\1$RELEASE|g" $SPECNAME

	subst "s|^%setup|%setup -q|g" $SPECNAME
	# obsoletes since Slackware/13 (rpm 4.10)
	subst "s|^BuildPreReq:|BuildRequires:|g" $SPECNAME
fi

# Auto*=yes,nomingw32 works only since ALT 4.1
if [ "$PKGVENDOR" = "alt" ] ; then
	if echo "$MDISTR" | egrep -q "M24|M30|M40" ; then
		subst "s|^\(Auto[RP].*\),nomingw32|\1|g" $SPECNAME
		subst "s|^\(Auto[RP].*\), nomingw32|\1|g" $SPECNAME
	fi
fi

if [ "$PKGVENDOR" = "ubuntu" ] || [ "$PKGVENDOR" = "debian" ] ; then
	# for systems with (d)ash as sh (f.i., Ubuntu)
	remove_bashism $SPECNAME
fi

if [ "$DISTRNAME/$DISTRVERSION" = "CentOS/5" ] ; then
	test -z "$VERBOSE" || echo "Remove egg-info from file list"
	subst "s|.*\.egg-info.*||g" $SPECNAME
fi



#TODO:
#%if %{undefined buildroot}
#BuildRoot: %{_tmppath}/%{name}-%{version}-buildroot
#%endif

#TODO:
#%clean section

rm -f $SPECNAME.old

if [ "$PKGVENDOR" = "alt" ] ; then
	subst "1i#" $SPECNAME
	# use old compress method for the src.rpm on ALT 4.0 and 4.1
	if [ "$DISTRVERSION" = "4.0" ] || [ "$DISTRVERSION" = "4.1" ] ; then
		export USE_LEGACY_COMPRESSION=1
	fi

	subst "1i# This spec is backported to $DISTRNAME $DISTRVERSION automatically by rpmbph script. Do not edit it." $SPECNAME
	ENTRY="- backport to $DISTRNAME $DISTRVERSION (by rpmbph script)"
	DISTRARG="-$MDISTR"
else
	subst "1i# This spec is autoported from ALT Linux Sisyphus to $DISTRNAME $DISTRVERSION automatically by rpmbph script. Do not edit it." $SPECNAME
	ENTRY="- autoport to $DISTRNAME $DISTRVERSION (by rpmbph script)"
	export USE_VENDOR=$RPMVENDOR
	export USE_LEGACY_COMPRESSION=1
	DISTRARG=""
fi

test -n "$TOCHANGELOG" && ENTRY=`echo -e "$ENTRY\n- $TOCHANGELOG"`
add_changelog $SPECNAME -e "$ENTRY"

}


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

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

phelp()
{
	echog "$Descr"
	echog "$Usage"
	echo  "Usage: rpmbph -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 "   -r           remote build" # will pass to rpmbs/rpmbsh
	echog "   -v           more verbose"
	echog "   -q           quiet"
	echog "Set ROOTDIR variable for backport to the other system"
#	echog " -m - send result via e-mail"
}


while getopts :hnuivqb: opt; do
    case $opt in
        h) phelp; exit 0 ;;
        n) NOBUILD=1 ;;
        u) UPLOADARG="-$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
	shift $((OPTIND - 1))
fi

# pass other options to RPM (exclude -v):
LISTRPMARGS=$(drop_args "$*" v)
}

set_girar_host $1 && shift

parse_cmd_pre_spec "$@"
mygetopts $LISTARGS

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

if [ "$PKGVENDOR" = "alt" ] ; then
	MDISTR=$MENV
	[ -n "$BINARYREPONAME" ] && MDISTR=$(get_altdistr_mod $BINARYREPONAME)
	[ "$MDISTR" = "SS" ] && fatal "It is senseless to backport to Sisyphus (You can try with -b $EXAMPLEALTDISTRVERSION)."
	# override by defined target version
	DISTRVERSION=$(get_altdistr_version $MDISTR)
else
	MDISTR=LOCAL
fi

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

[ -n "$NOBUILD" ] && BUILDCOMMAND="$ETERBUILDBIN/rpmbs"
[ -z "$BUILDCOMMAND" ] && BUILDCOMMAND="$ETERBUILDBIN/rpmbsh $GIRARHOST"

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

	# if run for ALT inside gear repo, just create backported spec
if [ "$PKGVENDOR" = "alt" ] && is_gear $SPECDIR ; then
	[ -f "$LISTNAMES" ] || fatal "Run with one spec inside gear repo"

	# set branch name
	USEBRANCH=$(get_altdistr_version $MDISTR)
	SPEC=$LISTNAMES
	BPSPEC=$SPEC.$USEBRANCH

	# support for obsoleted M?? names
	OLDBRANCH=$MDISTR
	if [ "$OLDBRANCH" != "$USEBRANCH" ] ; then
		if is_exist_branch $OLDBRANCH ; then
			echo "Exists $OLDBRANCH branch, will use it instead $USEBRANCH"
			USEBRANCH=$OLDBRANCH
		fi
		# hack about p5, M50 -> p5
		#if [ "$USEBRANCH" = "M50" ] && is_exist_branch p5 ; then
		#	USENUMBRANCH=p5
		#	echo "Exists $USENUMBRANCH branch, will use it instead $USEBRANCH"
		#	USEBRANCH=$USENUMBRANCH
		#fi
	fi

	[ -f "$BPSPEC" ] && fatal "File $BPSPEC is already exists, check it and remove"

	CURBRANCH=$(get_current_branch)

	if [ "$CURBRANCH" = "$USEBRANCH" ] ; then
		fatal "Run rpmbph in sisyphus or master branch, not in backport branch $USEBRANCH"
	fi

	# Create branch if not exist yet
	if ! is_exist_branch $USEBRANCH ; then
		docmd git branch $USEBRANCH
	fi

	cp -f $LISTNAMES $BPSPEC
	altspec_to_local $BPSPEC

	docmd git checkout $USEBRANCH || fatal "Can't checkout branch $USEBRANCH. Use $BPSPEC manually or remove it."
	docmd git merge $CURBRANCH
	mv -f $BPSPEC $SPEC
	# FIXME: Ctrl-\ and q will cancelled less with return error code
	if [ -z "$QUIET" ] && tty -s && ! ( echo "etersoft-build-utils INFO: Please check diff for backported spec:" ; echo "# etersoft-build-utils NOTE: You can press Ctrl-\ before quit for cancel process."; echo ; git diff $USEBRANCH ) | less; then
		#git checkout $SPEC $MDISTR
		#git checkout $CURBRANCH
		fatal "User cancelled. You are still in $USEBRANCH branch with modified spec"
	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 $MDISTR branch with modified and uncommitted spec"
	fi
	[ -n "$NOBUILD" ] && BUILDCOMMAND="$ETERBUILDBIN/rpmbs $GIRARHOST"
	echo "Run $BUILDCOMMAND"
	docmd $BUILDCOMMAND $LISTRPMARGS $UPLOADARG $REMOTEBUILD $DISTRARG $SPEC || { git checkout $CURBRANCH ; fatal "Can't build" ; }
	docmd git checkout $CURBRANCH
	exit $?
fi

unset MENV MENVARG

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

export RPMTOPDIR=$RPMDIR/BP

# 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
	echo $LISTNAMES | grep -q $i || rm -f $i

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

	docmd $BUILDCOMMAND $LISTRPMARGS $UPLOADARG $REMOTEBUILD $DISTRARG $SPECNAME || fatal "Can't build"
	uni_rpmrm $SPECNAME || true
done

