#!/bin/bash
#
#   repoman, a script to build and maintain packages
#
#   Copyright (c) 2005, 2006, 2007, 2008, 2009, 2010, 2011 by Miklos Vajna <vmiklos@frugalware.org>
#
#   This program is free software; you can redistribute it and/or modify
#   it under the terms of the GNU General Public License as published by
#   the Free Software Foundation; either version 2 of the License, or
#   (at your option) any later version.
#
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.
#
#   You should have received a copy of the GNU General Public License
#   along with this program; if not, write to the Free Software
#   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
#   USA.
#

usage()
{
	man repoman
}

msg()
{
	echo -e "\033[1;32m==>\033[1;0m \033[1;1m$1\033[1;0m" >&2
}

dry_run()
{
	if [ -z "$dryrun" ]; then
		eval "$*"
		return $?
	else
		echo $*
	fi
}

check_servers()
{
	server=$(eval "echo \$${reponame}_servers")
	if [ "$F_makepkg_scm" = "git" ]; then
		_server=`GIT_DIR=$fst_root/$reponame/.git git config --get remote.origin.url 2>/dev/null`
		if echo $_server |grep -q :/[^/]; then
			server=$_server
		fi
	else
		if [ -f "$fst_root/$reponame/_darcs/prefs/defaultrepo" ]; then
			server="`cat $fst_root/$reponame/_darcs/prefs/defaultrepo`"
		fi
	fi
        if echo $server |grep -q :/[^/]; then
                host=${server%:*}
                path=${server#*:}
        else
                die "The first server in the $reponame repo is read-only, please update the list of servers."
        fi
}

check_sudo()
{
	sudouser=$(eval "echo \$${reponame}_sudo")
	if [ -n "$sudouser" ]; then
		sudo_cmd="sudo -E -H -u $sudouser"
	else
		sudo_cmd=""
	fi
}

get_root()
{
	local i
	if [ "$F_makepkg_scm" = "git" ]; then
		i=`git rev-parse --git-dir 2>/dev/null`
		echo `dirname $i`
	else
		i=`pwd`
		while true
		do
			if [ -e "$i/_darcs" ]; then
				break
			elif [ "$i" == "" ]; then
				break
			fi
			i=`echo $i|sed 's|\(.*\)/.*|\1|'`
		done
		echo $i
	fi
}

check_absolute_path()
{
	if [ "${path:0:1}" != "/" ]; then
		echo "Please use absolute paths in repoman.conf!"
		exit 1
	fi
}

# lock management
get_lock()
{
	local timeout=300
	while [ "$timeout" -gt 0 ]; do
		sleep 1
		timeout=$((timeout - 1))
		[ -e .git/lock ] || return 0
		echo "Waiting for lock to be released..."
	done
	echo "Couldn't get lock."
	return 1
}

put_lock()
{
	touch .git/lock
}

rm_lock()
{
	echo "$1"
	rm -f .git/lock
}

server()
{
	local i

	case "$1" in
		delete)
		shift
		if [ $# -lt 3 ]; then
			echo "Too few parameters!"
			echo "usage: repoman server delete opts path file1 [file2..]"
			return 1
		fi
		local verbose="$1" path="$2"
		shift 2
		check_absolute_path
		cd $path
		get_lock || return 1
		if [ -n "$verbose" ]; then
			rmopts="-v"
		else
			rmotps=""
		fi
		for i in "$@"
		do
			# strip leading / and any ..
			target=`echo $i|sed 's|^/||;s|\.\./||g'`
			if [ -d "$target" ]; then
				rmdir $rmopts $target
			else
				rm $rmopts $target
			fi
		done
		;;

		mktemp)
		shift
		local tmp="`mktemp -p /var/tmp 2>/dev/null`"
		if [ -z "$tmp" ]; then
			echo "Failed to get a temporary file :-/" >&2
		else
			chmod 664 $tmp
			echo $tmp
		fi
		;;

		upload)
		shift
		if [ $# -lt 4 ]; then
			echo "Too few parameters!"
			echo "usage: repoman server upload path yourtmpfile sha1 targetfile"
			return 1
		fi
		local path="$1" tmp="$2" sha="$3" dest="$4"
		shift 4
		check_absolute_path
		cd $path
		get_lock || return 1
		if ! echo "$sha  $tmp" |sha1sum -c - >/dev/null 2>&1; then
			echo "The uploaded file is corrupted :-/"
			rm $tmp
			return 1
		fi
		# strip leading / and any ..
		if ! mv -f $tmp "`echo $dest|sed 's|^/||;s|\.\./||g'`"; then
			echo "Failed to move the uploaded file"
			rm $tmp
			return 1
		fi
		;;

		list)
		shift
		if [ $# -lt 2 ]; then
			echo "Too few parameters!"
			echo "usage: repoman server list path file1 [file2..]"
			return 1
		fi
		local path="$1"
		shift
		check_absolute_path
		cd $path
		for i in "$@"
		do
			# strip leading / and any ..
			ls "`echo $i|sed 's|^/||;s|\.\./||g'`"
		done
		;;

		list-untracked)
		shift
		if [ $# -lt 1 ]; then
			echo "Too few parameters!"
			echo "usage: repoman server list-untracked path"
			return 1
		fi
		local path="$1"
		shift
		check_absolute_path
		if [ -d $path ]; then
			cd $path
			git ls-files --others --directory
		fi
		;;

		changelog)
		shift
		if [ $# -lt 5 ]; then
			echo "Too few parameters!"
			echo "usage: repoman server changelog path fdb group pkg arch"
			return 1
		fi
		local path="$1" fdb="$2" group="$3" pkg="$4" arch="$5"
		shift 5
		check_absolute_path
		cd $path
		get_lock || return 1
		put_lock
		if ! cd source/$group/$pkg; then
			rm_lock "There is no package with this group!"
			return 1
		fi
		startdir=`pwd`
		if ! source ./FrugalBuild; then
			echo "Failed to parse the FrugalBuid!"
			rm -f $(git rev-parse --show-cdup)/.git/lock
			return 1
		fi
		cd - >/dev/null
		cd frugalware-$arch
		if ! _check_nobuild; then
			if [ ! -e $fdb ]; then
				if ! arch=$arch gensync ../source/$group/$pkg $fdb; then
					echo "gensync failed!"
					rm ../.git/lock
					return 1
				fi
			else
				if ! arch=$arch updatesync upd $fdb ../source/$group/$pkg/FrugalBuild; then
					echo "updatesync failed!"
					rm ../.git/lock
					return 1
				fi
			fi
		fi
		rm ../.git/lock
		( cd ../source/$group/$pkg; arch=$arch; genchangelog )
		;;

		clean)
		shift
		if [ $# -lt 4 ]; then
			echo "Too few parameters!"
			echo "usage: repoman server clean path fdb group pkg nofdb exclusivearch"
			return 1
		fi
		local path="$1" fdb="$2" group="$3" pkg="$4" nofdb="$5" exclusivearch="$6"
		check_absolute_path
		cd $path
		if [ -z "$nofdb" ]; then
			get_lock || return 1
			put_lock
			for i in frugalware-*
			do
				if [ -n "$exclusivearch" -a "frugalware-$exclusivearch" != $i ]; then
					continue
				fi
				cd $i
				if ! _check_nobuild; then
					if [ ! -e $fdb ]; then
						rm_lock "No package database to clean from!"
						cd - >/dev/null
						return 1
					else
						if ! arch=$arch updatesync del $fdb $pkg; then
							rm_lock "updatesync failed!"
							return 1
						fi
					fi
				fi
				if [ -z "$exclusivearch" -a -e ../tools/fpm2db ]; then
					../tools/fpm2db -D -m $pkg
				fi
				cd - >/dev/null
			done
			rm .git/lock
		fi
		if [ -d source/$group/$pkg -a -z "$exclusivearch" ]; then
			if [ ! -f source/$group/$pkg/FrugalBuild ]; then
				rm -rfv source/$group/$pkg
			else
				git clean -x -d -f source/$group/$pkg
			fi
		fi
		;;

		rsync)
		shift
		if [ $# -lt 3 ]; then
			echo "Too few parameters!"
			echo "usage: repoman server rsync path src arch"
			return 1
		fi
		local path="$1" srcurl="$2" arch="$3"
		shift 3
		check_absolute_path
		cd $path
		cd frugalware-$arch
		rsync -avP `echo $srcurl|sed 's/^.*@//'`/frugalware-$arch/*.fpm ./
		;;

		*)
		echo "Unknown server command!"
		return 1
		;;
	esac
}

_ssh()
{
	
	[[ -z "$repoman_port" ]] && repoman_port="22"
	$repoman_ssh -p$repoman_port $host "$sudo_cmd repoman server $*"
}

delete()
{
	if ! ask "repoman del $*"; then
		return
	fi
	local files rmopts host verbose
	check_servers
	check_sudo
	if [ "$verbose" != 0 ]; then
		verbose="y"
	else
		verbose=""
	fi
	msg "Deleting file(s): $*"
	_ssh "delete '$verbose' '$path' $*"
	return $?
}

upload()
{
	if [ "$#" -lt 2 ]; then
		echo "Too few parameters!"
		usage
		exit 1
	fi
	if ! ask "repoman upload $*"; then
		return
	fi
	check_servers
	check_sudo
	dest=${@:$#}
	for src in "${@:1:$#-1}"
	do
		if echo $src |grep -q fpm$ && ! LANG= LC_ALL= pacman-g2 -Qi -p $src |grep -q "^Build Type.*chroot$"; then
			echo "$src is not built in chroot. Remove the -H option"
			echo "from your makepkg commandline switches, rebuild your"
			echo "package and try again."
			exit 1
		fi
		if echo $src | grep -q fpm$ && pacman-g2 -Ql -p $src | grep -E -q ' lib64/| usr/lib64/'; then
			echo "$src has invalid lib64 path , refusing to upload!"
			echo "Please fix your package."
			exit 1
		fi
		if echo $src | grep -q fpm$ && pacman-g2 -Ql -p $src | grep -q 'var/tmp/fst'; then
			echo "$src has broken DESTDIR , files are installed"
			echo "in DESTDIR/DESTDIR , refusing to upload!"
			echo "Please fix your package."
			exit 1
		fi
		if echo $src | grep -q fpm$ && pacman-g2 -Ql -p $src | grep -q 'usr/etc'; then
			echo "$src has invalid etc path , files are installed"
			echo "in /usr/etc , refusing to upload!"
			echo "Please fix your package."
			exit 1
		fi
		if echo $src | grep -q fpm$ && pacman-g2 -Ql -p $src | grep -q 'usr/usr'; then
                        echo "$src has broken /usr DIR , files are installed"
                        echo "in /usr/usr , refusing to upload!"
                        echo "Please fix your package."
                        exit 1
		fi
		if echo $src | grep -q fpm$ && pacman-g2 -Ql -p $src | grep -q 'usr/share/pkgconfig'; then
                        echo "$src has invalid pkgconfig path , files are installed"
                        echo "in /usr/share/pkgconfig , should be /usr/lib/pkgconfig, refusing to upload!"
                        echo "Please fix your package."
                        exit 1
		fi
		if echo $src | grep -q fpm$ && pacman-g2 -Ql -p $src | grep -q 'usr/share/perl5'; then
                        echo "$src has invalid perl path , files are installed"
                        echo "in /usr/share/perl5 , refusing to upload!"
                        echo "Please fix your package."
                        exit 1
		fi

		name=`basename $src`
		msg "Requesting a temporary file"
		tmp=`_ssh "mktemp"`
		[ -z "$tmp" ] && exit 1
		msg "Uploading file: $src (to $tmp)"
		[[ -z "$repoman_port" ]] && repoman_port="22"
        $repoman_scp -P$repoman_port $src $host:$tmp
		sha=`sha1sum $src|sed 's/\(.*\)  .*/\1/'`
		if ! _ssh "upload '$path' '$tmp' '$sha' '$dest/$src'"; then
			return 1
		fi
	done
}

fpmmerge()
{
	if [ ! "`type -p rsync`" ]; then
		die "The rsync program is missing. Please install it with pacman-g2 -S rsync."
	elif [ -z "$1" ]; then
		echo "fpmmerge needs a parameter! (a repo name to pull in fpms from)"
		usage
		exit 1
	fi
	check_servers
	check_sudo
	srcurl=$(eval "echo \$$1_servers")
	if [ -z "$srcurl" ]; then
		die "so such repo!"
	fi
	# for each arch
	mergearchs="`rsync -vP $srcurl/|grep ^d.*frugalware-|sed 's/.* //'`"
	for i in $mergearchs
	do
		if ! _ssh "rsync '$path' '${srcurl#*:}' '${i//frugalware-}'"; then
			echo "WARNING: syncing $i failed"
		fi
	done

	# now push
	dg push -a

	# finally run repoman cl for each arch and pkg
	for i in $mergearchs
	do
		for j in `$0 -t $1 ls /$i/ 2>/dev/null|sed 's/-[^-]\+-[^-]\+-[^-]\+$//'`
		do
			cd `git rev-parse --git-dir`/../source/*/$j 2>/dev/null || continue
			arch=${i//frugalware-} $0 -t $reponame -k cl $j
		done
	done
}

list()
{
	check_servers
	check_sudo
	msg "Fetching contents of: $*"
	_ssh "list '$path' $*"
	return $?
}

split_group_pkg()
{
	if echo $1 |grep -q '^[^/]\+/[^/]\+$'; then
		group=${1%/*}
		pkg=${1#*/}
	else
		group=$groups
		pkg=$1
	fi
}

clean()
{
	check_servers
	check_sudo
	fdb=$(eval "echo \$${reponame}_fdb")
	[ -z "$fdb" ] && fdb="$reponame.fdb"
	nofdb=
	if [ "$1" == "--nofdb" ]; then
		shift
		nofdb=t
	fi
	if [ "$1" == "--exclusivearch" ]; then
		shift
		exclusivearch=$1
		shift
	fi
	for i in $*
	do
		if [ -z "$exclusivearch" ]; then
			msg "Cleaning up $i"
		else
			msg "Cleaning up $i (only on $exclusivearch)"
		fi
		split_group_pkg $i
		if ! _ssh "clean '$path' '$fdb' '$group' '$pkg' '$nofdb' '$exclusivearch'"; then
			return 1
		fi
	done
}

changelog()
{
	if ! ask "repoman changelog $*"; then
		return
	fi
	msg "Generating Changelog for $1"
	split_group_pkg $1
	check_servers
	check_sudo
	fdb=$(eval "echo \$${reponame}_fdb")
	[ -z "$fdb" ] && fdb="$reponame.fdb"
	_ssh "changelog '$path' '$fdb' '$group' '$pkg' '$arch'"
	return $?
}

_keypress()
{
	local old=$(stty -g)
	stty -icanon
	c=$(head -c1)
	stty "$old"
	echo $c
}

ask()
{
	if [ -z "$noask" ]; then
		echo $*
		echo -n "Is this ok? [Y/n] "
		c=`_keypress`
		echo
	fi
	if [ -n "$noask" ] || [[ "(y|Y)?" =~ "$c" ]]; then
		return 0
	else
		return 1
	fi
}

ask_and_eval()
{
	if [ -z "$noask" ]; then
		echo $*
		echo -n "Is this ok? [Y/n] "
		c=`_keypress`
		echo
	fi
	if [ -n "$noask" ] || [[ "(y|Y)?" =~ "$c" ]]; then
		eval "$*"
	fi
}

_check_nobuild()
{
	# trick: we require subpkgs not to be set. this is because this way:
	# 1) kde-i18n and such pkgs (only the main pkg is a nobuild one) is
	# recognized as a normal pkg
	# 2) opera and friends (where we use nobuild is there because of
	# license issues) will be recognized as a nobuild one
	if echo ${options[@]} | grep -q nobuild && [ -z "$subpkgs" ]; then
		return 0
	else
		return 1
	fi
}

_do_record()
{
	if [ "$F_makepkg_scm" = "git" ]; then
		git add -u .
		echo -e "$pkgname-$pkgver-$pkgrel-$arch

$@" | git commit -F -
	else
		root="`_get_root`"
		echo -e "`LANG= LC_ALL= date +"%a %b %d %H:%M:%S %Z %Y"`
`cat $root/_darcs/prefs/author`
$pkgname-$pkgver-$pkgrel-$arch
$@" | darcs rec -a --pipe .
	fi
}

__pkg_commit_info()
{
	local commitmsg
	if [ -e ./FrugalBuild ]; then
		commitmsg="$pkgname-$pkgver-$pkgrel-$arch"
		msg "Your git commit command is:"
		msg "git commit -a -e -m $commitmsg"
	else
		msg "Cannot find any FrugalBuild in `pwd`"
		msg "Commit command cannot be auto generated"
		exit 1
	fi
}

commit_info()
{
	__pkg_commit_info
}

record()
{
	echo -n "Checking FrugalBuild... "
	if fblint &>/dev/null; then
		echo "OK"
	else
		echo "Failed"
		exit 1
	fi
	if [ -n "$*" ]; then
		_do_record "$*"
	else
		if [ "$F_makepkg_scm" = "git" ]; then
			if ! git symbolic-ref -q HEAD >/dev/null; then
				echo
				echo "WARNING: Your HEAD is detached. In most cases you get into this
state by running 'git pull --rebase', getting a conflict, but not
resolving it. Run 'git status' to see the list of files which have
conflicts, resolve them, run 'git add <file1> [<file2> ...]', finally
'git rebase --continue' before you try to commit again. Continue without
the steps above only in case you know what you are doing."
				echo
			fi
			dg what -s .
			ask_and_eval "dg record --edit-long-comment -m '$pkgname-$pkgver-$pkgrel-$arch' ."
		else
			darcs what -s .
			ask_and_eval "darcs record --edit-long-comment -m '$pkgname-$pkgver-$pkgrel-$arch' ."
		fi
	fi
}

# returns true if the file is a build log for some other arch (we should not remove them)
_is_log()
{
	local i
	for i in ${archs[@]}
	do
		[ $i = $arch ] && continue
		if echo $1 |grep -q "$i\.log\.bz2$"; then
			return 0
		fi
	done
	return 1
}

srcdel()
{
	mydir=$(pwd|sed "s|$(get_root)||")
	for i in ${archs[@]} $arch
	do
		export CARCH=$i
		unset pkgver source
		for j in `set|grep ^_F_|sed 's/\(=.*\| ()\)//'`; do unset $j; done
		export startdir=`pwd`
		. ./FrugalBuild
		srclocal=(${srclocal[@]} ${source[@]})
	done
	srclocal=(${srclocal[@]} ${signatures[@]})
	if [ "$F_makepkg_scm" = "git" ]; then
		check_servers
		for i in $(_ssh "list-untracked '$path/$mydir'")
		do
			if ! echo ${srclocal[@]} |grep -q $i && ! _is_log $i && [ "$i" != "Changelog" ]; then
				dry_run delete $mydir/$i
			fi
		done
	else
		srckeep=$($mktemp_local)

		darcsdir="_darcs/pristine"
		if ! $0 -t $reponame ls $darcsdir &>/dev/null; then
			darcsdir="_darcs/current"
		fi

		$0 -t $reponame ls $darcsdir/$mydir 2>/dev/null >$srckeep

		for i in $($0 -t $reponame ls $mydir 2>/dev/null)
		do
			if ! grep -q $i $srckeep && ! _is_log $i && [ "$i" != "Changelog" ]; then
				if ! echo ${srclocal[@]} |grep -q $i; then
					dry_run delete $mydir/$i
				fi
			fi
		done

		rm -f $srckeep
	fi
}

fpmdel()
{
	fpmkeep=$($mktemp_local)
	fpmserver=$($mktemp_local)

	for i in $pkgname ${subpkgs[@]}
	do
		echo $i-$pkgver-$pkgrel-$arch.fpm >> $fpmkeep
		$0 -t $reponame ls frugalware-$arch 2>/dev/null |grep "^$i-[^-]\+-[^-]\+-$arch.fpm" >> $fpmserver
	done

	for i in $(cat $fpmserver)
	do
		if ! grep -q $i $fpmkeep; then
			dry_run delete frugalware-$arch/$i
		fi
	done

	rm -f $fpmkeep $fpmserver
}

bzip()
{
	ask_and_eval "bzip2 $*"
}

sync()
{
	ls *-$arch.fpm &>/dev/null && srcdel

	if ls *-$arch.fpm &>/dev/null; then
		for i in *-$arch.fpm
		do
			if ! _check_nobuild; then
				if ! dry_run upload $i frugalware-$arch/; then
					return 1
				fi
			fi
		done
	fi

	modpkgname=$(echo $pkgname | sed 's/\+/\\+/g')
	if [ -n "$noask" ]; then
		opts="-a"
	else
		opts=""
	fi
	if [ "$F_makepkg_scm" = "git" ]; then
		cmd="dg push $opts"
	else
		cmd="darcs push --match 'name $modpkgname' $opts"
	fi
	dry_run "$cmd" || die "push failed"

	# here we _could_ upload the new sources but that'll be done by changelog()

	buildlog="$pkgname-$pkgver-$pkgrel-$arch.log"
	if [ -f $buildlog -o -f $buildlog.bz2 ]; then
		[ -f $buildlog ] && dry_run bzip $buildlog
		_check_nobuild || dry_run upload $buildlog.bz2 source/$groups/$pkgname/
	fi

	ls *-$arch.fpm &>/dev/null && fpmdel
	if ! dry_run changelog $groups/$pkgname; then
		return 1
	fi
	if [ "$1" == "-c" ]; then
		if [ "$F_makepkg_scm" = "git" ]; then
			git clean -x -d -f
		else
			rm -rvf *-$arch.fpm
			rm -vf *.log.bz2
			rm -rf src
		fi
	fi
}

push()
{
	if [ "$1" == "--clean" -o "$1" == "-c" ]; then
		clean="-c"
		shift 1
	else
		clean=""
	fi
	dry_run record "$*"
	sync $clean
}

die()
{
	echo -e "$0: $*"
	exit 1
}

strip_url()
{
	echo $1 | sed 's|^.*://.*/||g'
}

genchangelog()
{
	[ -z "$arch" ] && arch=`arch`
	[ -z "$uploader" ] && uploader=`echo $HOME|sed 's|.*/\(.*\)$|\1|'`

	if [ ! -e Changelog ] || [ `stat -c %Y Changelog` -lt `stat -c %Y FrugalBuild` ]; then
		echo -n "running git log... "
		git log --follow --name-status FrugalBuild 2>/dev/null|grep -v $'^M\t' > Changelog
		echo "done."
	fi

	CARCH=$arch source ./FrugalBuild || die "errors parsing the FrugalBuild"

	if [ -e README.Frugalware ]; then
		if [ ! -e $pkgname.html ] || [ `stat -c %Y $pkgname.html` -lt `stat -c %Y README.Frugalware` ]; then
			echo -n "updating $pkgname.html... "
			mkpkghtml
			echo "done."
		fi
	fi

	CWD=`pwd`

	if [ ! "`check_option NOMIRROR`" -a ! "`check_option NOBUILD`" ]; then
		echo "downloading missing source files..."

		for i in "${source[@]}" "${signatures[@]}"
		do
			[[ "$i" =~ "http://ftp.frugalware.org" ]] && continue
			file=`strip_url "$i"`
			if [ -n "$file" -a ! -e "$file" ]; then
				echo "downloading "$file"..."
				$FTPAGENT "$i"
			fi
		done
	fi

	cd ../../../frugalware-$arch

	if [ -e ../t/functions.sh ]; then
		. ../t/functions.sh
	else
		# custom repo
		return 0
	fi

	if [ -x ../tools/fpm2db ]; then
		echo -n "updating the mysql2 database... "
		if [ ! "`check_option NOBUILD`" ]; then
			../tools/fpm2db -f $pkgname-$pkgver-$pkgrel-$arch.fpm
		else
			../tools/fpm2db -f $pkgname-$pkgver-$pkgrel-$arch.fpm -g $groups
		fi

		if [ ! -z "$subpkgs" ]; then
			i=0
			for subpkg in "${subpkgs[@]}"
			do
				cd $CWD
				cd ../../../frugalware-$arch
				if in_array $arch ${subarchs[$i]}; then
					../tools/fpm2db -f $subpkg-$pkgver-$pkgrel-$arch.fpm -m $pkgname -g $groups
				fi
				i=$(($i+1))
			done
		fi

		echo "done."
	fi

	if [ -x ../tools/fpm2irc ]; then
		echo -n "sending irc notifications... "
		if [ ! "`check_option NOBUILD`" ]; then
			../tools/fpm2irc -f $pkgname-$pkgver-$pkgrel-$arch.fpm
		else
			../tools/fpm2irc -f $pkgname-$pkgver-$pkgrel-$arch.fpm -g $groups
		fi

		echo "done."
	fi
}

update()
{
	if [ ! "`type -p git`" ]; then
		die "The git program is missing. Please install it with pacman-g2 -S git."
	fi
	for i in ${repos[@]}
	do
		pushonly=$(eval "echo \$${i}_pushonly")
		[ "$pushonly" = "y" ] && continue
		# Search for a server.
		eval "servers=(\${${i}_servers[@]})"
		if [ -z "$servers" ]; then
			echo -e "$0: Can't find any server!"
			if [ -e /etc/repoman.conf.pacnew ]; then
				echo -e "$0: HINT: merge the contents of /etc/repoman.conf.pacnew to /etc/repoman.conf!"
			fi
			exit 1
		fi
		echo ":: Synchronizing source trees..."
		for j in ${servers[@]}
		do
			# check if we need to clone or pull
			if [ -d $fst_root/$i/.git ]; then
				cmd="cd $i && git pull"
			else
				cmd="git clone $j $i"
			fi
			mkdir -p $fst_root
			cd $fst_root
			echo -n "$i: "
			eval $cmd
			if [ $? != 0 ]; then
				echo "failed."
			else
				break
			fi
		done
		git config --file $fst_root/$i/.git/config --get remote.origin.receivepack >/dev/null 2>&1
		if [ $? != 0 ]; then
			sudouser=$(eval "echo \$${i}_sudo")
			if [ -n $sudouser ]; then
				git config --file $fst_root/$i/.git/config remote.origin.receivepack "sudo -u $sudouser git-receive-pack" >/dev/null 2>&1
			fi
		fi
	done
}

chk_updated()
{
	if [ ! -d $1 ]; then
		echo "ERROR: Could not find FrugalBuild scripts in $1"
		echo "       have you used 'repoman upd' yet?"
		exit 1
	fi
}

search()
{
	chk_updated $fst_root
	[ -z "$*" ] || grepcmd="|grep $*"
	for i in ${repos[@]}
	do
		eval "find $fst_root/$i/source -name FrugalBuild |xargs grep '\(options=(.*nobuild.*)\|^nobuild=\)' |sed 's|$fst_root/||;s|/source/[^/]*||;s|/FrugalBuild:.*||' $grepcmd"
	done
}

info()
{
	chk_updated $fst_root
	if [ -z "$1" ]; then
		msg " Use repoman info <pkgname>"
		exit 1
	fi
	for i in ${repos[@]}
	do
		if [ ! -d $fst_root/$i/source/*/$1 ]; then
			msg "  Could not find package $1.. Typo?"
			exit 1
		else
			cd $fst_root/$i/source/*/$1
			startdir=`pwd`
			source ./FrugalBuild
			[[ -n ${rodepends[@]} ]] && depends+=" ${rodepends[@]}"
			echo "Repository        : $i"
			echo "Name              : $pkgname"
			echo "Version           : $pkgver-$pkgrel"
			echo "Groups            : ${groups[@]}"
			echo "Provides          : ${provides[@]:-None}"
			echo "Depends On        : ${depends[@]:-None}"
			echo "Removes           : ${removes[@]:-None}"
			echo "Conflicts With    : ${conflicts[@]:-None}"
			echo "Replaces          : ${replaces[@]:-None}"
			echo "Description       : $pkgdesc"
			cd - >/dev/null
			break
		fi
	done
}

upgrade()
{
	chk_updated $fst_root
	echo ":: Searching for nobuild packages..."
	localpkgs=$(pacman-g2 -Qm|sed 's/ .*//')
	echo ":: Starting local database upgrade for nobuild packages..."
	targets=""
	targetstr="Targets:"
	for i in $localpkgs
	do
		remotever=$(info $i|grep ^Version|sed 's/.*: //')
		[ -z "$remotever" ] && continue
		localver=$(pacman-g2 -Qi $i|grep ^Version|sed 's/.*: //')
		diff=$(vercmp $remotever $localver)
		if [ $diff -le 0 ]; then
			[ $diff -lt 0 ] && "warning: $i-$localver: local version is newer"
			continue
		fi
		if echo $upgrade_ignore |grep -q $i; then
			echo "warning: $i-$localver: ignoring package upgrade ($remotever)"
			continue
		fi
		targets="$targets $i"
		targetstr="$targetstr $i-$remotever"
	done

	[ -n "$targets" ] && echo -e "\n$targetstr\n"

	if [ -z "$dryrun" ]; then
		for i in $targets
		do
			echo ":: Merging $i..."
			if ! $0 -f merge $i; then
				echo "Failed to merge $i."
				echo "Try merging the package manually then run 'repoman upgrade' again to merge the"
				echo "rest of the targets."
				exit 1
			fi
		done
	else
		[ -n "$targets" ] && echo "Run 'repoman upgrade' to merge all target packages."
	fi
}

merge()
{

	local i repo target
	if echo $1 |grep -q /; then
		repo=${1%/*}
		target=${1#*/}
	else
		repo="${repos[@]}"
		target=$1
	fi
	#if [ -z "$force" ]; then
	#	# install essential packages if necessary
	#	echo -n "checking for essential packages... "
	#	. /etc/makepkg.conf
	#	for i in "$COREPKGS"
	#	do
	#		missing="$missing `pacman -Sg $i |grep -v '^\w'` "
	#	done
	#	missdep=`pacman-g2 -T $missing| sed 's|.\+: ||'`
	#	if [ -n "$missdep" ]; then
	#		echo "failed"
	#		echo "Use the following command to install the missing packages:"
	#		echo "pacman-g2 -S `echo $missdep| sed 's|=.*$||;s|>.*$||;s|<.*$||'`"
	#		exit 1
	#	else
	#		echo "done"
	#	fi
	#fi
	found=0
	for i in ${repo[@]}
	do
		# sanity checks
		chk_updated $fst_root/$i
		pushonly=$(eval "echo \$${i}_pushonly")
		[ "$pushonly" = "y" ] && continue
		dir=`find $fst_root/$i -maxdepth 4 -type d -name "$target"|sed -n '$ p'`
		if [ -z "$dir" ]; then
			continue
		else
			found=1
			cd $dir
			makepkg $makepkg_opts
			exit $?
		fi
	done
	[ "$found" = 0 ] && die "package '$target' not found"
}

if [ "$1" != "upd" -a "$1" != "update" ]; then
	[ -e /usr/lib/frugalware/fwmakepkg ] && . /usr/lib/frugalware/fwmakepkg || \
		die "Can't find /usr/lib/frugalware/fwmakepkg!"
	[ -e /etc/makepkg.conf ] && . /etc/makepkg.conf || \
		die "Can't find /etc/makepkg.conf!"
else
	[ -e /etc/repoman.conf ] && . /etc/repoman.conf || \
		die "Can't find /etc/repoman.conf!"
fi

if [ -e FrugalBuild ]; then
	. ./FrugalBuild
fi

# Initializing variables.
version='0.3.1'
if [ -z "$arch" ]; then
		arch="`uname -m`"

fi
mktemp_local="mktemp -p $HOME"
sudo_env="sudo -E"
unset LANG LC_ALL

if [ "$F_makepkg_scm" = "git" ]; then
# Checking for git.
which git >/dev/null 2>&1
if [ $? != 0 ]; then
	echo "ERROR: Can't find git. You can install it with pacman-g2 -S git."
	exit 1
fi
fi

# Parsing parameters.

if [ $# -le 0 ]; then
	usage
	exit 0
fi

# default for the -t parameter
reponame=${repos[0]}

while [ "$1" != "" ]; do
	case "$1" in
		-h|--help)
			usage
			exit 0
		;;
		-v|--verbose)
			 verbose=1
		;;
		--version)
			echo repoman $version
			exit 0
		;;
		-t|--tree)
			shift 1
			reponame=$1
		;;
		-k)
			noask=1
		;;
		-d|--dry-run)
			dryrun=1
		;;
		-f|--force)
			force=1
		;;
		-*)
			echo "Unknown option: $1"
			usage
			exit 1
		;;
		*)
			break
		;;
	esac
	shift
done

if [ "$1" != "" ]; then
	case "$1" in
		cl|changelog)
			shift 1
			changelog $*
			exit $?
		;;
		c|clean)
			shift 1
			clean $*
			exit $?
		;;
		del|delete)
			shift 1
			delete $*
			exit $?
		;;
		server)
			shift 1
			server "$@"
			exit $?
		;;
		ls|list)
			shift 1
			list $*
			exit $?
		;;
		m|merge)
			shift 1
			merge $*
			exit $?
		;;
		fpmmerge)
			shift 1
			fpmmerge $*
			exit $?
		;;
		up|upload)
			shift 1
			upload $*
			exit $?
		;;
		upd|update)
			shift 1
			update $*
			exit $?
		;;
		s|search)
			shift 1
			search $*
			exit $?
		;;
		rec|record)
			shift 1
			record "$*"
			exit $?
		;;
		push)
			shift 1
			push $*
			exit $?
		;;
		sync)
			shift 1
			sync $*
			exit $?
		;;
		info)
			shift 1
			info $*
			exit $?
		;;
		upgrade)
			shift 1
			upgrade $*
			exit $?
		;;
		ci)
			shift 1
			commit_info $*
			exit $?
		;;
		*)
			echo "Unknown command: $1"
			usage
			exit 1
		;;
	esac
else
	echo "No command given"
	exit 1
fi

exit 0
