#! /bin/sh

# $NetBSD: genrpm,v 1.3 2007/08/20 21:44:03 agc Exp $

#
# Copyright  2005,2007 Alistair Crooks.  All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
# 3. The name of the author may not be used to endorse or promote
#    products derived from this software without specific prior written
#    permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

# small shell script to convert from an installed NetBSD package to an rpm
#
# Usage: genrpm [--distdir=distdir] [--objdir=objdir] [--rpmdir=rpmdir] [--srpmdir=srpmdir] [--sign] [-s] [-v] pkgname

# find a program and set a global variable with its path
check_prog()
{       
	_var="$1"; _name="$2"

	eval _tmp=\"\$$_var\" 
	if [ "x$_tmp" != "x" ]; then
		# Variable is already set (by the user, for example)
		return 0
	fi      

	for _d in `echo $PATH | tr ':' ' '`; do
		if [ -x "$_d/$_name" ]; then
			# Program found
			eval $_var=\""$_d/$_name"\"
			return 1
		fi
	done

	eval $_var=\"""\"
}

# make sure we have a directory (given as argument)
safemkdir()
{
	_dir="$1"

	echo "Making directory \"${_dir}\""
	if [ ! -d ${_dir} ]; then
		${mkdir_cmd} -p ${_dir}
	fi

	if [ ! -d ${_dir} ]; then
		echo "can't create firectory ${_dir} - please do this by hand, and then restart" 2>&1
		exit 1
	fi
}

# our definitions
DISTVENDOR=${DISTVENDOR:-"pkgsrc/genrpm"}
DISTRIBUTION=${DISTRIBUTION:-"pkgsrc genrpm `date +%Y%m%d`"}

# program definitions
check_prog awk_cmd awk
check_prog cp_cmd cp
check_prog gzip_cmd gzip
check_prog ln_cmd ln
check_prog ls_cmd ls
check_prog mkdir_cmd mkdir
check_prog mv_cmd mv
check_prog pkg_info_cmd pkg_info
check_prog rm_cmd rm
check_prog sed_cmd sed
check_prog tar_cmd tar

extract_cmd="${tar_cmd} xf -"

# find the right name for make(1)
opsys=`uname -s | tr -d /`
case "${opsys}" in
NetBSD)	check_prog bmake_cmd make ;;
*)	check_prog bmake_cmd bmake ;;
esac

# set defaults
DISTDIR=${DISTDIR:-/usr/pkgsrc/distfiles}
objdir=/usr/obj
rpmdir=/usr/pkgsrc/packages/rpms
srpmdir=/usr/pkgsrc/packages/srpms
arch=`uname -m`

PKG_DBDIR=${PKG_DBDIR:-/var/db/pkg}
PKGSRC=${PKGSRC:-/usr/pkgsrc}

verbose=""	# by default, quiet running
sign=""		# by default, no signature
genpat="-bb"	# by default, just create a binary rpm

# and the immutables
redhatdir=/usr/pkg/src/redhat
reqpkgs="pkg_tarup rpm"
metafiles="+BUILD_INFO +BUILD_VERSION +COMMENT +CONTENTS +DESC +SIZE_ALL +SIZE_PKG"

# check any given args
while [ $# -gt 0 ]; do
	case "$1" in
	--arch=*)	arch=`echo "$1" | ${sed_cmd} -e 's|--arch=||'` ;;
	--distdir=*)	DISTDIR=`echo "$1" | ${sed_cmd} -e 's|--distdir=||'` ;;
	--objdir=*)	objdir=`echo "$1" | ${sed_cmd} -e 's|--objdir=||'` ;;
	--rpmdir=*)	rpmdir=`echo "$1" | ${sed_cmd} -e 's|--rpmdir=||'` ;;
	--srpmdir=*)	srpmdir=`echo "$1" | ${sed_cmd} -e 's|--srpmdir=||'` ;;
	--sign)		sign="$1" ;;
	-s)		genpat="-ba" ;;
	-v)		verbose="-v"; set -x ;;
	*)		break ;;
	esac
	shift
done

# check canonical directories are there on NetBSD
safemkdir ${redhatdir}
safemkdir ${rpmdir}
safemkdir ${rpmdir}/${arch}
safemkdir ${srpmdir}

if [ ! -e ${redhatdir}/BUILD ]; then
	(cd $redhatdir && ${ln_cmd} -s $objdir/rpm BUILD)
fi

if [ ! -e ${redhatdir}/RPMS ]; then
	(cd $redhatdir && ${ln_cmd} -s $rpmdir RPMS)
fi

if [ ! -e ${redhatdir}/SRPMS ]; then
	(cd $redhatdir && ${ln_cmd} -s $srpmdir SRPMS)
fi

if [ ! -e ${redhatdir}/SOURCES ]; then
	(cd $redhatdir && ${ln_cmd} -s $objdir/rpm/SOURCES SOURCES)
fi

# check that we have required packages installed
for p in $reqpkgs; do
	if ${pkg_info_cmd} -qe $p; then
		echo "Using $p version `${pkg_info_cmd} -e $p`"
	else
		echo "The $p needs to be installed to use this rpm generator" 2>&1
		exit 1
	fi
done

# generate an rpm for each package
while [ $# -gt 0 ]; do
	if ${pkg_info_cmd} -qe "$1"; then

		# expand the package name to include version information
		name=`${pkg_info_cmd} -e $1`

		# 3 components to package's name
		pkgbase=`echo $name | ${sed_cmd} -e 's|-[0-9].*||'`
		case "$name" in
		*-[0-9]*nb*)
			pkgversion=`echo $name | ${sed_cmd} -e 's|\(.*\)-\([0-9].*\)\(nb[0-9]*\)|\2|'`
			nb=`echo $name | ${sed_cmd} -e 's|\(.*\)-\([0-9].*\)nb\([0-9]*\)|\3|'`
			;;
		*)
			pkgversion=`echo $name | ${sed_cmd} -e 's|\(.*\)-\([0-9].*\)|\2|'`
			nb=0
			;;
		esac

		# retrieve information on prefix and pkgsrc directory from the package
		pkgprefix=`${pkg_info_cmd} -qp $name | ${awk_cmd} '{ print $2; exit }'`
		pkgpath=`${pkg_info_cmd} -B $name | ${awk_cmd} '/^PKGPATH=/ { sub("PKGPATH=", ""); print }'`
		pkgname=$pkgbase-$pkgversion

		# generate the rpm spec file first
		echo "Making an rpm spec file for $name - $pkgname - ($pkgbase-$pkgversion-$nb)"

		# make the build root
		${mkdir_cmd} -p $objdir/rpm/BUILD/$pkgname/$pkgprefix

		# make the single source directory
		${mkdir_cmd} -p $objdir/rpm/SOURCES

		# define the build directory
		builddir=$objdir/rpm/BUILD/$pkgname
		sourcesdir=$objdir/rpm/SOURCES/$pkgname

		# create the specfile in the right place
		specfile=$builddir/$pkgbase.spec

		echo "%define name $pkgbase" > $specfile
		echo "%define version $pkgversion" >> $specfile
		echo "%define release $nb" >> $specfile
		echo "%define prefix $pkgprefix" >> $specfile
		echo "" >> $specfile
		echo "" >> $specfile

		echo "Summary: %{name}, `${pkg_info_cmd} -qc $name`" >> $specfile
		echo "Name: %{name}" >> $specfile
		echo "Version: %{version}" >> $specfile
		echo "Release: %{release}" >> $specfile
		echo "Copyright: unknown" >> $specfile
		echo "URL: `${pkg_info_cmd} -d $name | ${awk_cmd} 'BEGIN { homepage=\"http://www.pkgsrc.org\"; }/^Homepage:/ { getline; homepage=$0 } END { print homepage }'`" >> $specfile
		echo "Packager: Alistair Crooks <agc@pkgsrc.org>" >> $specfile
		echo "Distribution: ${DISTRIBUTION}" >> $specfile
		echo "Vendor: ${DISTVENDOR}" >> $specfile
		echo "Prefix: ${pkgprefix}" >> $specfile
		for p in "" `${pkg_info_cmd} -qn $name`; do
			case "$p" in
			"")	continue ;;
			*)	case "$p" in
				*-[0-9]*)	p=`echo "$p" | ${sed_cmd} -e 's|\(.*\)-\([0-9].*\)|\1=\2|'` ;;
				esac
				case "$p" in
				*nb[0-9]*)	p=`echo "$p" | ${sed_cmd} -e 's|\(.*\)nb\([0-9]*\)|\1-\2|'` ;;
				esac
				echo "Requires: $p" >> $specfile ;;
			esac
		done
		for p in "" `${pkg_info_cmd} -qv $name | ${awk_cmd} '/conflicts with/ { print $4 }'`; do
			case "$p" in
			"")	continue ;;
			*)	case "$p" in
				*-[0-9]*)	p=`echo "$p" | ${sed_cmd} -e 's|\(.*\)-\([0-9].*\)|\1=\2|'` ;;
				esac
				case "$p" in
				*nb[0-9]*)	p=`echo "$p" | ${sed_cmd} -e 's|\(.*\)nb\([0-9]*\)|\1-\2|'` ;;
				esac
				echo "Conflicts: $p" >> $specfile ;;
			esac
		done

		echo "Buildroot: $builddir" >> $specfile
		echo "Group: $pkgpath" >> $specfile
		srcs="`${pkg_info_cmd} -Q _DISTFILES $name`"
		case "$srcs" in
		"")	srcs="`cd $PKGSRC/$pkgpath && ${bmake_cmd} show-var VARNAME=_DISTFILES`" ;;
		esac
		i=0
		for f in "" $srcs; do
			case "$f" in
			"")	continue ;;
			*)	echo "Source$i: $f" >> $specfile
				${cp_cmd} $DISTDIR/$f $objdir/rpm/SOURCES
				i=`expr $i + 1`
				;;
			esac
		done
		if [ -d $PKGSRC/$pkgpath ]; then
			(cd $PKGSRC/$pkgpath && tar -cf $objdir/rpm/SOURCES/$pkgname-pkgsrc.tar .)
			echo "Source$i: $pkgname-pkgsrc.tar" >> $specfile
		fi
		echo "" >> $specfile

		i=0
		if [ -d $PKGSRC/$pkgpath/patches ]; then
			(cd $PKGSRC/$pkgpath/patches && for f in "" patch-*; do
				case "$f" in
				"")	continue ;;
				*)	echo "Patch$i: $pkgname-$f" >> $specfile
					${cp_cmd} $f $objdir/rpm/SOURCES/$pkgname-$f
					i=`expr $i + 1`
					;;
				esac
			done)
			echo "" >> $specfile
			echo "" >> $specfile
		fi

		echo "%description" >> $specfile
		${pkg_info_cmd} -qd $name | ${awk_cmd} 'NF == 0 { next } { gsub("%", "percent"); print }' >> $specfile

		echo "" >> $specfile
		echo "%prep" >> $specfile
		echo "echo prep finished" >> $specfile

		echo "" >> $specfile
		echo "%setup -c" >> $specfile
		echo "echo setup finished" >> $specfile

		echo "" >> $specfile
		echo "%build" >> $specfile
		echo "echo build finished" >> $specfile

		echo "" >> $specfile
		echo "%install" >> $specfile
		echo "(cd $builddir/$pkgprefix && ${gzip_cmd} -d -c $builddir/$name.tgz | ${extract_cmd} && ${mkdir_cmd} -p $builddir/${PKG_DBDIR}/$name && ${mv_cmd} ./+CONTENTS $builddir/${PKG_DBDIR}/$name)" >> $specfile

		echo "" >> $specfile
		echo "%clean" >> $specfile
		echo "${rm_cmd} -rf $builddir $objdir/rpm/$name" >> $specfile

		echo "" >> $specfile
		echo "%files" >> $specfile
		${pkg_info_cmd} -qL $name | ${sed_cmd} -e "s|${pkgprefix}|%{prefix}|g" >> $specfile
		echo "${PKG_DBDIR}/$name/+CONTENTS" >> $specfile

		# make the build root, tarup the NetBSD binary package, and insert it in the build root
		${mkdir_cmd} -p $builddir/$pkgprefix
		pkg_tarup -d $builddir $pkgbase

		# create the binary rpm itself
		(cd $builddir && rpm $verbose $genpat $sign $pkgbase.spec)

		# tell people where we've put it/them
		${ls_cmd} -al $rpmdir/${arch}/$pkgname-*

		# cleanup
		${rm_cmd} -rf $builddir $objdir/rpm/$pkgname
	else
		echo "genrpm: WARNING!!! Package \"$1\" not found" 2>&1
	fi

	shift
done

exit 0
