#!/bin/bash


# start as root?
if [ $UID -ne 0 ]
	then sudo bash -c "export HOME=$HOME; $0 $*"; exit $?
fi

trap "sleep 1; cleanupandexit" 0 1 2 3 15

echo "---> zbuild version 1.6"

configdir="/etc/zbuild"
configs="buildhome ccache chrootbin zypperbin linux32bin rpmbuildbin dist arch jobs delchroot buildchecks"

# print help message 
usage()
{
cat << EOF 
usage: $0 options 
 
With zbuild you can create rpm packages in a clean chroot.

 -h		Helpmessage
 -d	DIST	Distribution
 -a	ARCH	Architecture
 -s	SPEC	Specfile
 -j	X	Build with X jobs
 -c		Use ccache
 -D		Don't delete old buildchroot
 -C		Don't run post build checks

Example:

zbuild -d 11.2 -a x86_64 -c -j 2 -s test.spec

EOF
}

cleanupandexit()
{
echo $message 2>&1 | tee -a $logfile
# umount /dev and /proc
if [ $buildchroot"x" != "x" ]
	then
	while [ -e $buildchroot/proc/uptime ]
		do umount $buildchroot/proc
	done
	while [ -e $buildchroot/dev/urandom ]
		do umount $buildchroot/dev
	done
fi
exit $rc
}

# which zbuild.conf to use?
if [ -e $HOME/.zbuild/zbuild.conf ]
	then configdir="$HOME/.zbuild"
fi
echo "---> Config: $configdir"
# read zbuild.conf
if [ -e $configdir/zbuild.conf ]
	then . $configdir/zbuild.conf
	else message="ERROR: $configdir/zbuild.conf not found !"; rc=1; cleanupandexit
fi

# check for missing options in zbuild.conf
for i in $configs
do
	eval conf=\$$i
	if [ -z $conf ]
		then message="Missing option $i in zbuild.conf"; rc=1; cleanupandexit
	fi
done

# optargs
while getopts "d:a:s:j:hcDC" OPTION
do
	case $OPTION in
		h)
			usage
			exit 1
			;;
		d)
			dist=$OPTARG
			;;
		a)
			arch=$OPTARG
			;;
		s)
			spec=$OPTARG
			;;
		j)
			jobs=$OPTARG
			;;
		c)
			ccache="y"
			;;
		D)
			delchroot="n"
			;;
		C)
			buildchecks="n"
			;;
	esac
done


# use linux32 to create 32bit chroot?
maschine=`uname -m`
if [ $maschine != "x86_64" ] && [ $arch == "x86_64" ]
	then
		message="ERROR: You can't build x86_64 on 32bit maschine!"; rc=1; cleanupandexit
elif [ $maschine == "x86_64" ] && [ $arch != "x86_64" ]
	then
		zyppercmd=$linux32bin
		chrootcmd=$linux32bin
		rpmbuildreq=$linux32bin
fi
zyppercmd+=" $zypperbin"
chrootcmd+=" $chrootbin"
rpmbuildreq+=" $rpmbuildbin"
rpmlintbin="/usr/bin/rpmlint"

# read config for $dist
if [ -e $configdir/$dist.conf ]
	then . $configdir/$dist.conf
	else message="ERROR: $configdir/$dist.conf not found!"; rc=1; cleanupandexit
fi

# get spec file
if [ -z $spec ]
	then spec=`ls -1 *.spec 2> /dev/null | head -n 1`
	if [ -z $spec ]
		then message="ERROR: No Spec-File found!"; rc=1; cleanupandexit
	fi
fi

buildchroot="$buildhome/buildroots/$dist-$arch"
logfile="$buildchroot/.build.log"

# print summary
echo " * Start at:  " `date` 2>&1 | tee $logfile
echo " * Building:  " $dist-$arch 2>&1 | tee -a $logfile
echo " * Spec:      "  $spec 2>&1 | tee -a $logfile

# delete/create targetdirs
# - buildchroot
if [ -d $buildchroot ]
	then
	if [ $delchroot == "y" ]
		then
			echo "--- Delete old chroot! ---"
			echo $buildchroot
			rm -rf $buildchroot
	fi
	else
	delchroot=y
fi
if [ ! -d $buildchroot/dev ]
	then mkdir -p $buildchroot/dev
fi
if [ ! -d $buildchroot/proc ]
	then mkdir -p $buildchroot/proc
fi
mount --bind /dev $buildchroot/dev
mount --bind /proc $buildchroot/proc

# rpm macros
# delete old macro file
if [ -e /etc/rpm/macros.zbuild ]
	then
		cmd="rm -f /etc/rpm/macros.zbuild"
		echo $cmd
		$cmd
fi
# copy new macro file
if [ -e $configdir/$dist.rpm_macros ]
	then
		cp $configdir/$dist.rpm_macros /etc/rpm/macros.zbuild
		mkdir -p $buildchroot/etc/rpm
		cp $configdir/$dist.rpm_macros $buildchroot/etc/rpm/macros.zbuild
fi

# - zyppercache
zyppercache="$buildhome/packagecache/$dist"
if [ ! -d $zyppercache ]
	then
	mkdir -p $zyppercache
fi
if [ ! -L $buildchroot/var/cache/zypp ]
	then
	mkdir -p $buildchroot/var/cache
	ln -s $zyppercache $buildchroot/var/cache/zypp
fi

# - localrepo
localrepo="$buildhome/repos/$dist"
if [ ! -d "$buildhome/repos/$dist" ]
	then
	mkdir -p $localrepo
	createrepo $localrepo
fi

# calculate buildrequires
echo "--- Calculate BuildRequires ---" 2>&1 | tee -a $logfile
buildreqtest=`grep -m 1 "^BuildRequires:" $spec`
if [ ! -z "$buildreqtest" ]
	then
	suseversion=`echo $dist | sed 's/\.//'`0
	sourcedir=`pwd`
	$rpmbuildreq --define "suse_version $suseversion" \
		--define "arch $arch" \
		--define "_sourcedir $sourcedir" \
		-r /tmp/zbuild -ba --nobuild $spec 2>&1 \
		| cut -f 1 -d" " \
		| grep -v "^error:"  \
		| grep -v "^sh:"  \
		> buildrequires.tmp
	buildrequires=`cat buildrequires.tmp`
	rm -f buildrequires.tmp
	rm -rf /tmp/zbuild
fi

# delete macro file
if [ -e /etc/rpm/macros.zbuild ]
	then rm -f /etc/rpm/macros.zbuild
fi

# install ccache?
if [ $ccache == "y" ]
	then
	buildrequires+=" ccache"
fi
echo "Buildrequires: " $buildrequires 2>&1 | tee -a $logfile


# add repositories
zyppercmd+=" --root $buildchroot --no-gpg-checks --non-interactive"
if [ $delchroot == "y" ]
	then
	echo "--- Add repositories ---" 2>&1 | tee -a $logfile
	$zyppercmd ar --refresh $localrepo localrepo 2>&1 | tee -a $logfile
	$zyppercmd mr -p 1 localrepo 2>&1 | tee -a $logfile
	for i in $add_sources
	do
		eval url=\$url_$i
		eval prio=\$prio_$i
		if [[ -z $url ]]
			then message="ERROR: Repository "$i" doesn't exist in $dist.conf!"; rc=1; cleanupandexit
		fi
		$zyppercmd ar --refresh --keep-packages $url $i 2>&1 | tee -a $logfile
		if [ $? -ne 0 ]
			then message="ERROR: Couldn't add $i!"; rc=1; cleanupandexit
		fi
		$zyppercmd mr -p $prio $i 2>&1 | tee -a $logfile
		if [ $? -ne 0 ]
			then message="ERROR: Couldn't set prio for $i!"; rc=1; cleanupandexit
		fi
	done
fi
echo "--- Refresh repositories ---" 2>&1 | tee -a $logfile
$zyppercmd ref 2>&1 | tee -a $logfile
#$zyppercmd dup --auto-agree-with-licenses --no-recommends 2>&1 | tee -a $logfile

# install chroot
echo "--- Install chroot ---"
for i in required buildrequires
do
	echo "---> "$i
	eval rpms=\$$i
	$zyppercmd in --download-in-advance --no-recommends --auto-agree-with-licenses $rpms 2>&1 | tee -a $logfile
	rc=${PIPESTATUS[0]}
	if [ $rc -ne 0 ]
		then message="ERROR: Zypper returns with RC $rc"; cleanupandexit
	fi
done

# adduser zbuild in chroot
echo 'zbuild::399:399:zbuild:/home/zbuild:/bin/bash' >> $buildchroot/etc/passwd
echo 'zbuild::399:' >>$buildchroot/etc/group
mkdir -p $buildchroot/home/zbuild/bin
chown -R 399:399 $buildchroot/home/zbuild

# copy files to chroot
echo "--- Copy files to chroot ---" 2>&1 | tee -a $logfile
if [ -e $buildchroot/usr/src/packages ]
	then rm -rf $buildchroot/usr/src/packages
fi
for i in BUILD BUILDROOT SOURCES SPECS SRPMS RPMS/i386 RPMS/i586 RPMS/x86_64 RPMS/noarch
	do
	mkdir -p $buildchroot/usr/src/packages/$i
	chmod 777 $buildchroot/usr/src/packages/$i
	done
find . -maxdepth 1 -type f -exec cp -v {} $buildchroot/usr/src/packages/SOURCES 2>&1 \; | tee -a $logfile

# use ccache?
if [ $ccache == "y" ]
	then
	rm -f $buildchroot/home/zbuild/bin/*
	for i in gcc g++ cc c++
	do
		if [ -e "$buildchroot/usr/bin/$i" ]
			then
			ln -sf /usr/bin/ccache $buildchroot/home/zbuild/bin/$i
		fi
	done
fi

# build the rpm
rpmbuildcmd="$rpmbuildbin -ba $spec --define '_topdir /usr/src/packages' --define 'jobs $jobs'"
echo "--- Build RPM ---" 2>&1 | tee -a $logfile
echo "Buildcommand: " $rpmbuildcmd 2>&1 | tee -a $logfile
$chrootcmd $buildchroot su -l zbuild -c "cd /usr/src/packages/SOURCES; $rpmbuildcmd" 2>&1 | tee -a $logfile
rc=${PIPESTATUS[0]}
if [ $rc -ne 0 ]
	then message="ERROR: Rpmbuild returns with RC $rc"; cleanupandexit
fi

# run post build checks
if [ $buildchecks == "y" ]
	then
	if [ -e $buildchroot/usr/lib/build/checks ]
		then
		echo "--- Run post build checks ---" 2>&1 | tee -a $logfile
		pname=`echo $spec | cut -f1 -d"."`
		for check in $buildchroot/usr/lib/build/checks/*
			do
			echo "-- "`basename $check`
			BUILD_ROOT=$buildchroot PNAME=$pname $check 2>&1 | tee -a $logfile
			rc=${PIPESTATUS[0]}
			if [ $rc -ne 0 ]
				then message="ERROR: "`basename $check`" returns with RC $rc"; cleanupandexit
			fi
			done
	fi
fi

# run rpmlint
if [ $buildchecks == "y" ]
	then
	echo "--- Run rpmlint ---" 2>&1 | tee -a $logfile
	rpm=`$chrootbin $buildchroot su -l zbuild -c "find /usr/src/packages/RPMS \\
		-not -name \"*-lang-*\" \\
		-not -name \"*-debuginfo-*\" \\
		-not -name \"*-debugsource-*\" \\
		-name \"*.rpm\""`
	rpm+=" "
	rpm+=`$chrootbin $buildchroot su -l zbuild -c "find /usr/src/packages/SRPMS \\
		-name \"*.rpm\""`
	$chrootbin $buildchroot $rpmlintbin --info $rpm 2>&1 | tee -a $logfile
	rc=${PIPESTATUS[0]}
	if [ $rc -ne 0 ]
		then message="ERROR: Rpmlint returns with RC $rc"; cleanupandexit
	fi
fi

# copy files to localrepo
echo "--- Copy files to local repository ---" 2>&1 | tee -a $logfile
for dir in x86_64 i386 i586 noarch
	do
	mkdir -p $localrepo/$dir
	find $buildchroot/usr/src/packages/RPMS/$dir -type f -name "*.rpm" -exec cp -v {} $localrepo/$dir \; 2>&1 | tee -a $logfile
	done
mkdir -p $localrepo/src
find $buildchroot/usr/src/packages/SRPMS -type f -name "*.rpm" -exec cp -v {} $localrepo/src \; 2>&1 | tee -a $logfile

# update localrepo
echo "--- Update local Repository ---" 2>&1 | tee -a $logfile
createrepo -v --database --update $localrepo 2>&1 | tee -a $logfile

# finished
message="--- Finished job at "`date`" ---"; rc=0; cleanupandexit

