#!/bin/bash
#----------------------------------------------------------------------
# rpm2paco - Build paco logs from a local rpm database.
#----------------------------------------------------------------------
# Copyright (C) 2004-2009 David Rosal
# For more information visit http://paco.sourceforge.net
#----------------------------------------------------------------------


#-----------#
# Functions #
#-----------#


help()
{
cat << EOF
$ME - Create paco logs from a local rpm(8) database.

Usage:
  $ME [OPTIONS] <packages>

Options:
  -a, --all            Create a log for each package in the rpm database.
  -q, --quiet          Be silent, except for errors.
  -f, --force          Force overwrite of already logged packages.
  -s, --strip-release  Remove the release suffix from the name of the
                       packages (e.g. foo-2.0.2-1 --> foo-2.0.1).
  -j, --sync-version   Remove obsolete versions of the packages from the paco
                       database.
  -v, --version        Display version information and exit.
  -h, --help           Display this help message and exit.

EOF
exit 0
}


version()
{
	paco --version | sed "s@^paco@$ME@"
	exit $?
}


say()
{
	[ $QUIET -eq 0 ] && printf "$*" >&2
}


die()
{
	echo -e "$ME: $*" >&2
	exit 1
}


sync_versions()
{
	local base=$(echo $1 | sed -e 's@-[0-9].*@@')
	for p in $(paco --expand $base); do
		if ! ( rpm --query $p &>/dev/null ); then
			paco --unlog --verbose $p
		fi
	done
}


#---------------------------------------#
# Initialize and parse the command line #
#---------------------------------------#


ME=rpm2paco
MYDIR=${PWD:-$(pwd)}

# Defaults
ALL_PKGS=0
STRIP=0
QUIET=0
FORCE=0
SYNC=0
INPUT_PKGS=

## Parse the command line arguments

while [ -n "$1" ]; do
	case $1 in
		-v|--version)				version;;
		-h|--help)					help;;
		-a|--all)					ALL_PKGS=1;;
		-q|--quiet)					QUIET=1;;
		-f|--force)					FORCE=1;;
		-j|--sync-version|--sync)	SYNC=1;;
		-s|--strip-release|--strip)	STRIP=1;;
		
		-*) die "Unrecognized option: $1\nTry '$ME --help' for more information"
			;;
		*)	INPUT_PKGS="$INPUT_PKGS $1"
			;;
	esac
	shift
done

## Check for rpm(8) and paco(8)

for prog in rpm paco; do
	$prog --version &>/dev/null || die "Cannot find $prog executable"
done


#---------------------------------#
# Get the list of packages to log #
#---------------------------------#

PKGLIST=
if [ $ALL_PKGS -eq 1 ]; then
	say "Building package list... "
	PKGLIST=$(rpm --query --all)
	say "done\n"
elif [ -z "$INPUT_PKGS" ]; then
	die "No input packages\nTry '$ME --help' for more information"
else
	for pkg in $INPUT_PKGS; do
		out=$(rpm --query $pkg) && PKGLIST="$PKGLIST $out" || echo $out >&2
	done
fi

[ -z "$PKGLIST" ] && exit 1

# Remove repeated packages from the list
PKGLIST=$(for pkg in $PKGLIST; do echo $pkg; done | sort --unique)


#-----------------#
# Create the logs #
#-----------------#

## Get the paco log directory

PACORC=$(pkg-config --variable=pacorc paco 2>/dev/null || echo /etc/pacorc)
LOGDIR=$(pkg-config --variable=logdir paco 2>/dev/null || echo /var/log/paco)
if [ -s $PACORC ]; then
	logdir=$(grep '^LOGDIR=' $PACORC | sed 's@.*=@@')
	[ -n "$logdir" ] && LOGDIR=$(eval echo $logdir | tr -s /)
fi
install -d $LOGDIR || exit 1

## Tmp dir to store intermediate files

TMPDIR=$(mktemp -dt ${me}XXXXXX 2>/dev/null || echo /tmp/$ME.$$)
install -d $TMPDIR || exit 1

# Remove tmp stuff on exit
trap 'rm -rf $TMPDIR; cd $MYDIR &>/dev/null' 0

## Process the packages

for pkg in $PKGLIST; do
	
	name=$pkg

	# Strip the release suffix, if needed.
	if [ $STRIP -eq 1 ]; then
		name=$(echo $pkg | awk '{ 						\
			out = $0;									\
			cnt = gsub(/-[0-9][^-]*/, "&");				\
			if (cnt > 1)  								\
				out = gensub(/-[0-9][^-]*/, "", cnt);	\
			print out;									\
		}')
	fi

	log=$LOGDIR/$name

	say "Processing package $name... "

	# Check whether it is already logged
	if [ $FORCE -eq 0 -a -e $log ]; then
		say "already logged\n"
		[ $SYNC -eq 1 ] && sync_versions $name
		continue
	fi

	# List of files

	install -d $TMPDIR/$name || exit 1
	cd $TMPDIR/$name || exit 1
		
	# Fake spec file
	rpm --query $pkg --queryformat="\
Name: %{Name}\n\
Version: %{Version}\n\
Summary: %{Summary}\n\
URL: %{URL}\n\
Author: %{Vendor}\n\
License: %{License}\n\n\
%%description\n%{description}\n" \
	> $name.spec || true
	
	# Log the package with paco

	prev=%%%
	for path in $(rpm --query --list $pkg | sort --reverse); do
		# dirty way to detect directories (even missing ones)
		expr $prev : $path/ &>/dev/null || echo $path
		prev=$path
	done \
		| paco --log --log-missing --package=$name

	if [ ! -f $log ]; then
		say "no files (not logged)\n"
		continue
	fi

	# Fix installation date in the logs
	
	date=$(rpm --query $pkg --queryformat="%{InstallTime}")
	[ -n "$date" ] && sed -i "s|^#d:.*|#d:$date|" $log

	# Fix the sizes of the missing files

	grep -- '^-' $log | cut --characters=1 > misslist
	if [ -s misslist ]; then
		for line in $( \
			  rpm --query --list --dump $pkg \
			| cut --delimiter=" " --fields=1,2 \
			| sed 's;\[;\\[; ; s; ;|;')
		do
			path=$(expr $line : '\([^|]*\)')
			if ( egrep --quiet "^$path|" misslist ); then
				sed -i "s;-$path|-2;-$line;" $log
			fi
		done
				
		paco --update $name
	fi
	say "ok\n"

	[ $SYNC -eq 1 ] && sync_versions $name

done

exit 0

