#!/bin/sh
# 2004-2010 (c) Etersoft www.etersoft.ru
# Author: Vitaly Lipatov <lav@etersoft.ru>
# Public domain
#
# Скачивает исходный src.rpm-пакет с одного из репозиториев (по умолчанию ALT Linux) для пакета с указанным названием.
# Также можно сразу указать название пакета с исходниками
# Функции скрипта похожи на команду apt-get source пакет
# -c - checkonline

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

# loads repos file and fill SYSNAME and SYSURL arrays
load_systems_list()
{
	local IDX=0
	local line
	while read line ; do
		# skip comments
		rhas "$line" "^#" && continue
		SYSNAME[$IDX]=${line/ *.*/}
		#FTP[$IDX]=${line/.* \+/}
		SYSURL[$IDX]=$(echo $line | sed -e "s|.* \+||g")
		IDX=$(($IDX+1))
	done < $ETERBUILDETC/repos/srpms

	while read name url ; do
		rhas "$name" "^#" && continue
		SYSNAME[$IDX]="git$name"
		SYSURL[$IDX]=$url
		IDX=$(($IDX+1))
	done <$ETERBUILDETC/repos/gits
}

list_systems()
{
	echo "Known systems:"
	for ((i=0; i < ${#SYSNAME[*]}; i++)) ; do
			printf "[%-17s] %s\n" ${SYSNAME[$i]} ${SYSURL[$i]}
	done
	echo
	echo "You can add src.rpm repo to /etc/eterbuild/repos/srpms or git url to /etc/eterbuild/repos/gits"
}

html_filter()
{
	grep "src.rpm" | sed -e "s|.*href=\"||g" | sed -e "s|\".*||g"
}

list_filter()
{
	sed -e "s|.src.rpm$||g"
}

get_git_list()
{
	local name=$1
	local url=$2
	local list=$3
	for i in $($CURL -s $url | grep folder | sed -e "s|.*HREF=\"||g" | sed -e "s|\".*||g") ; do
		$CURL -s $url/$i | grep 'class="link"' | sed -e "s|.*href=\"||g" | sed -e "s|\".*||g"
	done >$list
}

# Using: git_list idx [force]
# set LIST variable to list file
get_list()
{
	[ -n "$VERBOSE" ] && echo "get_list for $1"
	local URL=${SYSURL[$1]}
	local FORCE=$2
	local SYS=${SYSNAME[$1]}
	CURL=curl

	$EPMCMD assure $CURL || fatal "curl command needed for download"
	mkdir -p $OURTMPDIR/etersoft-build-utils/
	LIST=$OURTMPDIR/etersoft-build-utils/rpmgpall-$SYS
	if [ ! -f "$LIST" ] || [ "$FORCE" = "force" ] ; then
		if rhas "$SYS" "^git" ; then
			get_git_list $SYS $URL $LIST
			return
		fi
		#echo -e -n "\r"
		echo "Get list for $SYS from $URL ..."
		#curl -l $URL/ >$LIST
		touch $LIST
		# suitable for ftp and http lists
		rm -f $LIST.ok
		( $CURL -s -l $URL/ && touch $LIST.ok ) | tee $LIST.tmp | html_filter >$LIST
		if [ ! -e $LIST.ok ] ; then
			#echo -e -n "\r"
			warning "Could't download list for $SYS from $URL"
			#rm -f "$LIST.tmp"
			return
		fi
		rm -f $LIST.ok
		# check if there is letter subdirs (Fedora)
		for i in $(cat $LIST.tmp | sed -e "s|<a href=\"||g" -e "s|/\">.*||g") ; do
		    rhas "$i" rpm && break
		    # ignore more than one letter
		    [ -n "$(echo $i | cut -c2-)" ] && continue
		    [ "$i" = "-" ] && continue
		    #echo -e -n "\r"
		    echo "Try get $URL/$i ..."
		    $CURL -s -l $URL/$i/ | html_filter | sed -e "s|^|$i/|g" >>$LIST
		done
		rm -f $LIST.tmp
		#echo
	#else
	#	echo "List for $SYS"
	fi
}

get_system_idx()
{
	if [ -z "$1" ] ; then
		return 1
	fi
	for ((i=0; i < ${#SYSNAME[*]}; i++)) ; do
		if [ ${SYSNAME[$i]} = "$1" ] ; then
			echo $i
			return 0
		fi
	done
	return 1
}

check_name()
{
	if [ -z "$1" ] ; then
		return
		#echo "Error: missed package param"
		#exit 1
	fi
	NLIST=`cat $LIST | grep -i "$1"`
#	if [ `cat $LIST | list_filter | grep -i $1 | wc -l` -gt 1 ] ; then
		#echo "Please type a full name of the package"
#		print_list $NLIST
#		return 1
#	fi

	if [ -z "$NLIST" ] ; then
		echo "$1: Not found"
		return 1
	fi

	return 0
}

check_system()
{
	local i
	local IDX=$1
	local URL=${SYSURL[$IDX]}
	#echo "Check for $SYSTEM"
	get_list $IDX
	#ls -l $LIST
	check_name $PKGNAME || return
	if [ -n "$DOWNLOADALL" ] ; then
		for i in $NLIST ; do
			download_url $URL/$i
		done
	fi
}

update_cache_list()
{
	load_systems_list
	# if followed by system name
	IDX=`get_system_idx "$1"`
	if [ -n "$IDX" ] ; then
		get_list $IDX force
		shift
		exit 0
	fi
	# update all systems
	for ((irepo=0; irepo < ${#SYSNAME[*]}; irepo++)) ; do
		get_list $irepo force
	done
}

Usage="Usage: rpmgp [GIRAR/remote alias] [options] [-b $EXAMPLEALTDISTRVERSION] [system] pkgname"
mygetopts()
{
Descr="rpmgp (Get Package) - various package download operations"

phelp()
{
# TODO: improve description
	echog "$Descr"
	echog "$Usage"
	echog " pkgname - installed package name or src.rpm"
	echog " system  - name of system (ALT Linux by default if -a missed)"
	echo
	echog "Options:"
	echog "   -a   search pkgname in all known repositories"
	echog "   -b REPONAME  binary repository name (4.1, p5, t6 and so on)"
	echog "   -c   check if this package exists in the ALT Linux repository"
	echog "   -d   download all matched packages"
	echog "   -g   clone last built package repo"
	echog "   -gp  clone last built package repo via public access"
	echog "   -gm  remote clone repo to USER/packages and clone it locally"
	echog "   -m   migrate to gear from spec/srpm"
	echo
	echog "Ext. options:"
	echog "   -i   install packages needed for build (use epm)"
	echog "   -l   list packages needed for build (in local pkg system notation) (experimental)"
	echog "   -r   refresh package list (download it again)"
	echog "   -p   force use public access to the git repo"
	echog "   -s   list all known remote repositories"
	exit 0
}

while getopts :hab:icdglmpprs opt; do
    case $opt in
    h) phelp; exit 0;;
    a) ALLSYSTEM=1 ;;
# see functions/alt:set_binaryrepo() for BINARYREPONAME
    b) BINARYREPONAME=$OPTARG ;;
    i) INSTALLBINARY=1 ;;
    c) CHECKONLINE=1 ;;
    d) DOWNLOADALL=1 ;;
    g) CLONEGIT=1 ;;
    l) LISTREQS=1 ;;
    m) MIGRATEGIRAR=1 ;;
    p) PUBLICACCESS=1 ;;
    r) UPDATECACHE=1 ;;
    s) load_systems_list
       list_systems
       exit 0
       ;;
    +?) echog "$name: options should not be preceded by a '+'." 1>&2; exit 2;;
#    ?)  echog "$name: $OPTARG: bad option.  Use -h for help." 1>&2 ; exit 2;;
    ?) OPTIND=$((OPTIND-1)); break;
    esac
done

# FIXME: параметры передаются и дальше (например, -i, -b)
# remove args that were options
[ "$OPTIND" -gt 0 ] && shift $(($OPTIND - 1))


# pass other options to RPM:
LISTRPMARGS=$@
}

set_girar_host $1 && shift

# HACK
if [ "$1" = "-a" ] ; then
    parse_cmd_pre "$@"
else
    parse_cmd_pre_spec "$@"
fi

mygetopts $LISTARGS

# optional arg
if [ -n "$UPDATECACHE" ] ; then
    update_cache_list $1
    exit 0
fi

detect_target_env

PKGNAME=$(estrlist strip_spaces $LISTRPMARGS $LISTNAMES)

if [ -z "$ALLSYSTEM$UPDATECACHE" ] ; then
	test -z "$PKGNAME" && fatal "Please run with spec/package name"
fi

# список названий систем, адресов (с зеркалами?), и режимов фильтрации
# название кэш-файла строить из названия системы
# выводить найденное сразу везде
#
# уточнение - [система] пакет

# install required for build binary packages
if [ -n "$INSTALLBINARY" ] ; then
    # pack by LISTNAMES list
    pack_src_rpm --commit $LISTRPMARGS
    docmd $EPMCMD install --skip-installed $($ETERBUILDBIN/rpmreqs -p $LISTBUILT)
    exit
fi

# TODO: do gpull -a for get all branches?
get_all_remote_branches()
{
	local CURRENTBRANCH=$(get_current_branch)
	# create all branches
	for i in $(git branch -a | grep -v "/HEAD" | grep "remotes/origin/") ; do
		local BRANCHNAME=$(echo $i | sed -e "s|remotes.*/||g")
		if is_exist_branch $BRANCHNAME ; then
			docmd git checkout $BRANCHNAME || fatal "can't checkout $BRANCHNAME"
			docmd git pull origin $BRANCHNAME
		else
			docmd git checkout -b $(echo $i | sed -e "s|remotes.*/||g") $i
		fi
	done
	docmd git checkout sisyphus || docmd git checkout master || docmd git checkout $CURRENTBRANCH
}

git_clone()
{
	local RREPO="$1"
	# Test if ssh access is available
	if [ -z "$PUBLICACCESS" ] && giter $GITHOST check girar access ; then
		docmd git clone $GIRARHOST:$RREPO
	else
		local GIRARURL=$(get_git_url $GITHOST)
		[ -n "$GIRARURL" ] || fatal "Can't get public URL for $GIRHOST"
		PUBLICACCESS=1
		docmd git clone $GIRARURL$RREPO
	fi
}

# clone remote git
if [ -n "$CLONEGIT" ] ; then
	if [ -z "$MIGRATEGIRAR" ] ; then
		RREPO=$(giter $GITHOST print girar pubrepo $PKGNAME) || fatal "$PKGNAME does not exists in $GIRARHOST:/gears, nor in $GIRARHOST:/srpms. Can't clone."
		git_clone $RREPO || fatal "Can't clone $RREPO for $PKGNAME"
		if cd $PKGNAME ; then
			docmd git remote rename origin gear
			cd - >/dev/null
		fi
	else
		[ -z "$PUBLICACCESS" ] || fatal "Can't remote clone via public access"
		RREPO=$(giter $GITHOST print girar pubrepo $PKGNAME) || fatal "$PKGNAME does not exists in $GIRARHOST:/gears, nor in $GIRARHOST:/srpms. Can't clone."

		echo "Remote clone from $RREPO ..."
		docmd ssh $GIRARHOST clone $RREPO packages/$PKGNAME.git || warning "Can't remote clone."

		GITUSER=$(giter $GITHOST print girar user)
		UREPO=$(giter $GITHOST print girar userrepo $GITUSER $PKGNAME)
		docmd git clone $GIRARHOST:$UREPO

		if cd $PKGNAME ; then
			# add remotes
			docmd git remote rename origin $GIRARHOST && docmd gremote $GIRARHOST -o
			cd - >/dev/null
		fi
	fi

	if cd $PKGNAME ; then
		# get or update all branches
		get_all_remote_branches
		cd - >/dev/null
	fi

	if [ -z "$PUBLICACCESS" ] ; then
		echo "See other repos at $GIRARHOST:"
		giter $GITHOST list packages $PKGNAME
	fi

	exit 0
fi

if [ -n "$MIGRATEGIRAR" ] ; then
	for INFILE in $LISTNAMES ; do
		# call for each file due generated BASENAME
		LISTNAMES=$INFILE pack_src_rpm $INFILE $LISTRPMARGS
		PKGNAME="$LISTBUILT"
		if [ -z "$BASENAME" ] ; then
			echo "Can't get basename for $PKGNAME, skipping"
			continue
		fi
		echo "Create gear repo $BASENAME from $PKGNAME in $GITREPODIR"
		[ -n "$GITREPODIR" ] || GITREPODIR=$(pwd)
		GEARDIR=$GITREPODIR/$BASENAME
		test -d "$GEARDIR" && fatal "repo $GEARDIR already exists"
		docmd mkdir -p "$GEARDIR" || fatal "can't create dir $GEARDIR"
		docmd cd $GEARDIR || fatal "can't cd to $GEARDIR"
		docmd git init-db || fatal "can't init db"
		docmd gear-srpmimport $PKGNAME || fatal "can't import srpm $PKGNAME"
		# remove src.rpm only if it was generated from spec
		[ -z ${INFILE/*rpm/} ] || rm -vf $PKGNAME
		docmd rpmcs
	done
	exit 0
fi

# lists packages for build
if [ -n "$LISTREQS" ] ; then
	print_target_buildreq "$PKGNAME"
	exit $?
fi

# Check online
if [ -n "$CHECKONLINE" ] ; then

	# possible it is spec
	if [ -f "$PKGNAME" ] ; then
		build_rpms_name "$PKGNAME"
		SRCRPM=$NAMESRPMIN
		PKGNAME=$(get_pkgname_from_filename $SRCRPM)
	else
		if rhas "$PKGNAME" "\.rpm" ; then
			# possible it is rpm package name
			SRCRPM=$PKGNAME
			PKGNAME=$(get_pkgname_from_filename $SRCRPM)
		else
			SRCRPM=$(querypackage $PKGNAME "" "%{SOURCERPM}\n" | tail -n 1)
		fi
	fi

	if [ -n "$GIRAR_USER" ] ; then
		# FIXME: we have a function to get correct url
		local GIRARURL=$(get_git_url $GITHOST)
		[ -n "$GIRARURL" ] || fatal "Can't get public URL for $GIRHOST"
		GITURL=${GIRARURL}$(giter $GITHOST print girar userrepo $GIRAR_USER $PKGNAME)
		if $GET -d $GITURL ; then
			echog "Published at $GITURL by $GIRAR_USER"
		else
			echog "There is no git repo $GITURL"
		fi
	fi
	echo "Get repositories at $GIRARHOST:"
	giter $GITHOST list packages $PKGNAME

	set_binaryrepo $MENV

	docmd $ETERBUILDBIN/gacl $GIRARHOST -b $BINARYREPO $PKGNAME show

	RET="MISSED"
	if [ -n "$SRCRPM" ] ; then
		RSYNCPATH=$(get_rsync_path $GIRARHOST $BINARYREPO)
		echog "Checking '$PKGNAME' in '$RSYNCPATH' ..."
		if $RSYNC -n $RSYNCPATH/files/SRPMS/$SRCRPM 2>/dev/null | grep $PKGNAME ; then
			RET=OK
			echo "Package $SRCRPM is the latest version from $RSYNCPATH"
		else
			# upstream version difference, just printout list
			RSYNCPATH=$(get_rsync_path $GIRARHOST $BINARYREPO)
			docmd $RSYNC -n "$RSYNCPATH/files/SRPMS/$PKGNAME-[0-9]*" 2>/dev/null | grep $PKGNAME || echo "Package $PKGNAME is missed"
			echo "Local package $SRCRPM differs from the latest version from $RSYNCPATH"
		fi
	else
		SRCRPM="$PKGNAME-[0-9]*"
		RSYNCPATH=$(get_rsync_path $GIRARHOST $BINARYREPO)
		echog "Checking '$SRCRPM' in '$RSYNCPATH' ..."
		docmd $RSYNC -n $RSYNCPATH/files/SRPMS/$SRCRPM 2>/dev/null | grep $PKGNAME
		echo "Package '$PKGNAME' is not installed locally"
	fi

	[ "$RET" = "OK" ]
	exit
fi

# FIXME: use mygetopts (LISTRPMARGS and so)

#if [ -n "$2" ] && [ "$1" = "all" ] ; then
#    shift
#    ALLSYSTEM=1
#fi

# DISABLED. TODO: REWRITE
# Check concrete system
# two params: system, package
if [ -n "$2" ] && false ; then
	PKGNAME=$2
	load_systems_list
	IDX=`get_system_idx "$1"`
	if [ -n "$IDX" ] ; then
		check_system $IDX
		print_list $NLIST
	else
		fatal "Unknown system '$1', use rpmgp -s for get list"
		#PKGNAME=
	fi
	exit 0
fi

# Check all systems
if [ -n "$ALLSYSTEM" ] ; then
	#info "Note: you can use whohas also"
	NFLAG=
	load_systems_list
	# search throw all systems
	for ((i=0; i < ${#SYSNAME[*]}; i++)) ; do
		check_system $i > /dev/null
		[ -n "$NLIST" ] || continue
		echo
		echo "List for ${SYSNAME[$i]}:"
		print_list $NLIST
		NFLAG=1
	done
	if [ -z "$NFLAG" ] ; then
		echo "No search result for $PKGNAME. Check rpmgp -s for list of all systems."
	fi
	exit 0
fi

phelp
exit 1
