#!/bin/bash
#
# Yaourt (Yet Another Outil Utilisateur): More than a Pacman frontend
#
# Copyright (c) 2008-2010 Julien MISCHKOWITZ <wain@archlinux.fr>
# Copyright (c) 2010-2012 tuxce <tuxce.net@gmail.com>
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU Library General Public License as published
# by the Free Software Foundation; either version 2, 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, see <http://www.gnu.org/licenses/>.
#
export TEXTDOMAINDIR='/usr/share/locale'
export TEXTDOMAIN=yaourt

NAME='yaourt'
VERSION='1.5'
. '/usr/lib/yaourt/util.sh'

###################################
### General functions           ###
###################################

usage() {
	if ((${#ARGSANS[*]} > 1)); then
		echo "$(gettext 'Yaourt does not support --help for a particular option.')"
		echo "$(_gettext 'The following is %s help :' "$PACMAN")"
		echo
		pacman_out "${ARGSANS[@]}"
		return
	fi
	echo "$(gettext 'Usage: yaourt <operation> [...]')"
	echo "$(gettext 'operations:')"
	echo -e "\t$(gettext 'yaourt (search pattern|package file)')"
	echo -e "\t$(gettext 'yaourt {-h --help}')"
	echo -e "\t$(gettext 'yaourt {-V --version}')"
	echo -e "\t$(gettext 'yaourt {-Q --query}       [options] [package(s)]')"
	echo -e "\t$(gettext 'yaourt {-R --remove}      [options] <package(s)>')"
	echo -e "\t$(gettext 'yaourt {-S --sync}        [options] [package(s)]')"
	echo -e "\t$(gettext 'yaourt {-U --upgrade}     [options] <package(s)>')"
	echo -e "\t$(gettext 'yaourt {-C --clean}       [options]')"
	echo -e "\t$(gettext 'yaourt {-B --backup}      [save directory|restore file]')"
	echo -e "\t$(gettext 'yaourt {-G --getpkgbuild} [options] <package(s)>')"
	echo -e "\t$(gettext 'yaourt {--stats}')"
}

version() {
	echo "yaourt $VERSION"
	echo "$(gettext 'homepage: http://archlinux.fr/yaourt-en')"
}


###################################
### Handle actions              ###
###################################

# Search for packages
# usage: search ($interactive, $set_pkgsfound)
# interactive:1 -> line number
# set_pkgsfound:1 -> put result in PKGSFOUND
search() {
	local interactive=${1:-0}
	local set_pkgsfound=${2:-$interactive}
	local search_option="${PACMAN_Q_ARG[@]//-q/}"
	local pager_out=$(mktemp -u --tmpdir="$YAOURTTMPDIR")
	local ret=0
	if [[ "$MAJOR" = "query" ]]; then
		search_option+=" -Q"
		((AUR)) && ((FOREIGN || UPGRADES)) && search_option+=" -A"
	else
		search_option+=" -S"
	fi
	if (( SEARCH )); then
		search_option+=" -s"
	else
		[[ $ARGS ]] && (( ! GROUP )) && search_option+=" -i"
	fi
	(( AURSEARCH )) && search_option+=" -A"
	[[ $SORT ]] && search_option+=" --sort $SORT"
	[[ $RSORT ]] && search_option+=" --rsort $RSORT"
	(( QUIET )) && { pkgquery $search_option -f "%n" -- "${ARGS[@]}";return $?; }
	if ((set_pkgsfound)); then
		((interactive)) && search_option+=" --number"
		if ((USEPAGER)); then
			{ readarray -t PKGSFOUND < <(pkgquery --get-res $search_option -- "${ARGS[@]}" 3>&1 1>&2 ); } 2> "$pager_out"
		else
			{ readarray -t PKGSFOUND < <(pkgquery --get-res $search_option -- "${ARGS[@]}" 3>&1 1>&2 ); } 2>&1
		fi
		[[ $PKGSFOUND ]] || ret=1
	else
		if ((USEPAGER)); then
			pkgquery $search_option -- "${ARGS[@]}" > "$pager_out"
		else
			pkgquery $search_option -- "${ARGS[@]}"
		fi
		ret=$?
	fi
	if ((USEPAGER)); then
		[[ -s "$pager_out" ]] && ${PAGER:-cat} "$pager_out"
		[[ -f "$pager_out" ]] && rm "$pager_out"
	fi
	return $ret
}
	
# Handle special query
yaourt_query_type() {
	local arg
	title $(gettext 'query packages')
	load_lib alpm_query
	for arg in ${ARGS[@]}; do
		search_pkgs_which "$QUERYTYPE" "$arg"
	done
}

yaourt_install_packages() {
	load_lib abs aur misc
	prepare_status_list
	SP_ARG="" sync_packages "${ARGS[@]}" || return $?
	analyse_status_list
	#show package which have not been installed
	if [[ $ERROR_PKGS ]]; then
		warning "$(gettext 'Following packages have not been installed:')"
		echo_wrap 4 "${ERROR_PKGS[*]}"
		return 1
	fi
}
	
# Handle sync
yaourt_sync() {
	local arg
	((PRINT && REFRESH))  && pacman_cmd 1
	((PRINT && !REFRESH)) && pacman_cmd 0
	if (( GROUP || LIST || SEARCH)); then
		(( LIST )) && {
			title $(gettext 'listing all packages in repo(s)')
			msg $(gettext 'Listing all packages in repo(s)')
		}
		(( GROUP )) && title $(gettext 'show groups')
		search 0
		return $?
	elif (( SYSUPGRADE )); then
		load_lib abs aur misc
		prepare_status_list
		sysupgrade
		# Upgrade devel packages
		((DEVEL)) && upgrade_devel_package
		analyse_status_list
		return
	fi
	[[ ! $ARGS ]] && (( ! REFRESH )) && pacman_cmd 1; 
	if [[ $QUERYTYPE ]]; then
		yaourt_query_type
		return
	elif (( INFO )); then
		load_lib aur
		for arg in ${ARGS[@]}; do
			title $(_gettext 'Informations for %s' $arg)
			local _repo="${arg%/*}"
			if [[ "$_repo" = "$arg" || "$_repo" != "aur" ]]; then
				pacman_out -S "${PACMAN_S_ARG[@]}" "$arg" 2> /dev/null ||\
					 info_from_aur "${arg#*/}"
			else
				info_from_aur "${arg#*/}"
			fi
		done
		return
	fi
	yaourt_install_packages
}

# Handle query
yaourt_query() {
	[[ -n $BACKUPFILE ]] && if [[ -r "$BACKUPFILE" ]]; then   # -Q --backupfile
		load_lib alpm_backup 
		is_an_alpm_backup "$BACKUPFILE" || die 1
		program_arg $((A_PC | A_PKC)) "-b" "$backupdir"
	else
		error $(_gettext 'Unable to read %s file' "$BACKUPFILE")
		die 1
	fi
	if (( CHANGELOG || LIST || INFO || FILE )); then
		pacman_out -Q "${PACMAN_Q_ARG[@]}" "${ARGS[@]}"
		return $?
	fi
	if (( DEPENDS && UNREQUIRED )); then
		load_lib alpm_query
		search_forgotten_orphans
	elif [[ $QUERYTYPE ]]; then
		yaourt_query_type
	else
		#title $(gettext "Query installed packages")
		#msg $(gettext "Query installed packages")
		AURSEARCH=0 search 0
	fi
}

# Handle interactive search
yaourt_interactive() {
	local line packages
	SEARCH=1 search 1 
	[[ $PKGSFOUND ]] || die 0
	prompt $(gettext 'Enter n° of packages to be installed (ex: 1 2 3 or 1-3)')
	read -ea packagesnum
	[[ $packagesnum ]] || die 0
	for line in ${packagesnum[@]/,/ }; do
		(( line )) || die 1	# not a number, range neither 
		(( ${line%-*}-1 < ${#PKGSFOUND[@]} )) || die 1	# > no package corresponds
		if [[ ${line/-/} != $line ]]; then
			for ((i=${line%-*}-1; i<${line#*-}; i++)); do
				packages+=(${PKGSFOUND[$i]});
			done
		else
			packages+=(${PKGSFOUND[$((line - 1))]})
		fi
	done
	echo 
	ARGS=("${packages[@]}")
	yaourt_install_packages
}

# No action specified
yaourt_no_action() {
	local file
	declare -a filelist
	[[ $ARGS ]] || pacman_cmd 0
	# If no action and files as argument, act like -U *
	for file in "${ARGS[@]}"; do
		[[ "${file%.pkg.tar.*}" != "$file" && -r "$file" ]] && filelist+=("$file")
	done
	if [[ $filelist ]]; then
		ARGS=( "${filelist[@]}" )
		su_pacman -U "${ARGS[@]}"
		die $?
	else
		# Interactive search else.
		MAJOR="interactivesearch"
	fi
}

###################################
### MAIN PROGRAM                ###
###################################
# Basic init and librairies

unset MAJOR AUR SEARCH BUILD REFRESH SYSUPGRADE CLEAN \
      IGNOREGRP IGNOREPKG CHANGELOG LIST INFO RSORT SORT UNREQUIRED \
      FOREIGN GROUP QUERYTYPE QUIET DEPENDS PRINT \
      AURVOTEINSTALLED CUSTOMIZEPKGINSTALLED PACMAN_CMD \
	  NEEDED

# Disable color if output is not a terminal
[[ -t 1 ]] || { ((USECOLOR!=2)) && USECOLOR=0; USEPAGER=0; TERMINALTITLE=0; }

# Grab environement options
{
	type -p aurvote && AURVOTEINSTALLED=1
	type -p customizepkg && CUSTOMIZEPKGINSTALLED=1
} &> /dev/null

# makepkg check root
if (( ! UID )); then
	warning $(gettext 'Building package as root is dangerous.\n Please run yaourt as a non-privileged user.')
	sleep 2
	program_arg $A_M "--asroot"
fi

# Explode arguments (-Su -> -S -u)
ARGSANS=("$@")
explode_args "$@"
set -- "${OPTS[@]}"
unset OPTS

while [[ $1 ]]; do
	case "$1" in
		-D|--database|-w|--downloadonly)      PACMAN_CMD=1;;
		-R|--remove|-U|--upgrade)             [[ ! $PACMAN_CMD ]] && PACMAN_CMD=2;;
		-o|--owns|--changelog|--check|--file) [[ ! $PACMAN_CMD ]] && PACMAN_CMD=0;;
		--dbpath)           DBPATH="$2"
		                    program_arg $((A_PC | A_PKC)) "$1" "$2"; shift;;
		--config|-r|--root) program_arg $((A_PC | A_PKC)) "$1" "$2"; shift;;
		--cachedir|--logfile|--arch) program_arg $A_PC "$1" "$2"; shift;;
		--noprogressbar|--noscriptlet) program_arg $A_PC "$1";;
		--asexplicit|--asdeps) program_arg $A_PS $1;;
		--needed)           NEEDED=1; program_arg $A_PS $1;;
		--clean)            ((CLEAN++));;
		-c)                 ((CLEAN++)); ((CHANGELOG++)); program_arg $A_PQ "$1";;
		--deps)             ((DEPENDS++)); program_arg $A_PQ $1;;
		-d)                 ((DEPENDS++)); program_arg $((A_PS | A_M | A_PQ)) $1;;
		-e|--explicit)      program_arg $A_PQ $1;;
		-m|--foreign)       FOREIGN=1; program_arg $A_PQ $1;;
		-g|--groups)        GROUP=1; program_arg $A_PQ $1;;
		-i|--info)          INFO=1; program_arg $((A_PQ | A_PS)) $1;;
		-l|--list)          LIST=1; program_arg $A_PQ $1;;
		--noconfirm)        NOCONFIRM=1;;
		--nodeps)           program_arg $((A_PS | A_M )) $1;;
		-Q|--query)         MAJOR="query";;
		-y|--refresh)       (( REFRESH ++ ));;
		-S|--sync)          MAJOR="sync";;
		--sysupgrade)       SYSUPGRADE=1; (( UPGRADES ++ ));;
		-t|--unrequired)    UNREQUIRED=1; program_arg $A_PQ $1;;
		-u|--upgrades)      (( UPGRADES ++ )); program_arg $A_PQ $1;;
		--holdver)          program_arg $A_M $1;;
		-A|--ignorearch)    program_arg $A_M $1;;
		--ignore)           program_arg $A_PS $1 "$2"; shift; IGNOREPKG+=(${1//,/ });;
		--ignoregroup)      program_arg $A_PS $1 "$2"; shift; IGNOREGRP+=(${1//,/ });;
		-a|--aur)           AUR=1; AURUPGRADE=1; AURSEARCH=1;;
		-B|--backup)        MAJOR="backup";;
		--backupfile)       shift; BACKUPFILE="$1";;
		-b|--build)         ((BUILD++));;
		-C)                 MAJOR="clean";;
		--conflicts|--depends|--provides|--replaces) QUERYTYPE=${1:2};;
		--date)             SORT=1;;
		--devel)            DEVEL=1;;
		--export)           EXPORT=1; EXPORTSRC=1; shift; EXPORTDIR="$1";;
		--force)            FORCE=1;;
		-G|--getpkgbuild)   MAJOR="getpkgbuild";;
		-h|--help)          usage; exit 0;;
		--insecure)         program_arg $((A_PKC | A_CC)) $1;;
		--color)            USECOLOR=2;;
		--m-arg)            program_arg $((A_M)) $2; shift;;
		--nocolor)          USECOLOR=0;;
		--pager)            USEPAGER=1;;
		-p|--print)         PRINT=1; FILE=1; program_arg $A_PQ $1;;
		--file)             FILE=1; program_arg $A_PQ $1;;
		--print-format)     ((PRINT++));; # --print-format needs --print
		--pkg)              program_arg $((A_M)) $1 "$2"; shift;;
		-s|--search)        SEARCH=1; program_arg $A_PQ $1;;
		--rsort)            RSORT=$2; shift;;
		--sort)             SORT=$2; shift;;
		--stats)            MAJOR="stats";;
		--sucre)            MAJOR="sync"
			FORCE=1; SYSUPGRADE=1; REFRESH=2;
			AURUPGRADE=1; DEVEL=1; NOCONFIRM=2;;
		--tmp)              shift; TMPDIR="$1";;
		-V|--version)       version; exit 0;;
		-v)                 program_arg $((A_PQ | A_PS)) $1;;
		-q|--quiet)         QUIET=1; DETAILUPGRADE=0; program_arg $((A_PS | A_PQ)) $1;;
		--)                 shift; ARGS+=("$@"); break;;
		-*)                 [[ ! $PACMAN_CMD ]] && PACMAN_CMD=0;;
		*)                  ARGS+=("$1") ;; 
	esac
	shift
done

# Init path & colors 
init_paths
init_color
[[ $PACMAN_CMD ]] && pacman_cmd $PACMAN_CMD

# No options
[[ -z $MAJOR ]] && yaourt_no_action
# Complete options
(( ! SYSUPGRADE && UPGRADES )) && [[ $MAJOR = "sync" ]] && SYSUPGRADE=1 # -Su
if (( NOCONFIRM )); then
	EDITFILES=0
	BUILD_NOCONFIRM=1
	AURVOTE=0
	program_arg $((A_PS | A_M)) "--noconfirm"
elif ((SYSUPGRADE && UP_NOCONFIRM)) || ((PU_NOCONFIRM)); then
	program_arg $A_PU "--noconfirm"
fi
((FORCE)) && program_arg $((A_PS | A_M)) "--force"

# Refresh
# Don't refresh now if yaourt is called with -Syp*
# or, if DETAILUPGRADE=0, with -Syu*
if [[ $MAJOR = "sync" ]] && ((REFRESH)); then
	((!PRINT && !SYSUPGRADE)) && pacman_refresh $REFRESH
fi

# Action
case "$MAJOR" in
	clean)
		(( CLEAN )) && _arg="-c" || _arg=""
		launch_with_su pacdiffviewer $_arg
		;;

	stats)
		load_lib alpm_stats
		yaourt_stats
		;;

	getpkgbuild)
		title "$(gettext 'get PKGBUILD')"
		load_lib pkgbuild
		get_pkgbuild "${ARGS[@]}"
		;;

	backup) 
		load_lib alpm_backup
		yaourt_backup "${ARGS[0]}"
		;;
	
	sync) yaourt_sync ;;
	query) yaourt_query ;;
	interactivesearch) yaourt_interactive ;;
		
	*) pacman_cmd 0 ;;
esac

# vim: set ts=4 sw=4 noet: 
