#!/bin/bash
#   d-shlibmove -- move shared library files around for Debian packaging
#   Copyright (C) 2002, 2005 Junichi Uekawa
#
#   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

# 2002 Apr 23. Created.
#   automatic packaging of libtool-created library packages.

# from d-shlibs package

set -e
set -o pipefail

function getname() {
	local SONAMELIBNAME
	local SONAMEVERSION
	local SONAME
	SONAME="$1"
	SONAMELIBNAME=$(echo $SONAME | sed 's/\.so\..*$//')
	SONAMEVERSION=$(echo $SONAME | sed 's/^.*\.so\.//')
	case "$SONAMELIBNAME" in
	  *[0-9])
		RETURN="$SONAMELIBNAME-$SONAMEVERSION"
		;;
	  *)
		RETURN="$SONAMELIBNAME$SONAMEVERSION"
		;;
	esac
}

function readlibnameinfo() {
	LIBNAME="$1"

	if  [ -z "$1" ] || ! echo "$1" | grep ".so$" > /dev/null ; then
		echo "$0: [$1] is not a valid shared library file name " >&2
		exit 1;
	fi

	if [ ! -h "$1" ]; then
		echo "$0: expected [$1] to be a symlink, but it is not" >&2
		exit 1;
	fi

	SONAME=$(set -o pipefail; objdump -p ${LIBNAME} |sed -n 's/^.*SONAME *//p' )
	getname "$SONAME"
	SONAMEPKGNAME=$(echo "$RETURN" | tr '[A-Z_]' '[a-z\-]')
	PK=$(basename "$1" | sed 's/\.so$//')
	PK_LOWER=$(echo ${PK} | tr '[A-Z_]' '[a-z\-]')
	REALSO=$(readlink -f "${LIBNAME}")
}

function check_line() {
	local PKGNAME="$1"
	local ENTRYLINE="$2"

	if ! awk '/^Package:.*'"$PKGNAME"'/,/^$/{print}' "$CONTROL" | \
		perl -0 -pe 's/\n[ \t]+/ /g' | \
		grep "$ENTRYLINE"  > /dev/null; then
		echo "E: line [$ENTRYLINE] not found in $CONTROL section for $PKGNAME"
		# set this error signifier to true
		CHECK_ERROR=true
	fi
}


echo "Library package automatic movement utility"

CONTROL=debian/control

execscript=$(tempfile)
INSTALLFILE_SHLPKG=$(tempfile)
INSTALLFILE_DEVPKG=$(tempfile)
cat > ${execscript} <<EOF
set -e
EOF

EXTRALIBS=
SUFFIX=
DEVSUFFIX=
TRANSITIONSUFFIX=

DOIT=no
DEVUNVERSIONED=no
IGNORELIBDEP=no
INCLUDEA=yes
INCLUDELA=yes
MULTIARCH=no
while [ -n "$1" ]; do
	case $1 in
	  --moveshl)
		echo "$2 $3" >> "${INSTALLFILE_SHLPKG}"
		shift; shift; shift;
		;;
	  --movedev)
		echo "$2 $3" >> "${INSTALLFILE_DEVPKG}"
		shift; shift; shift;
		;;
	  --movedevdoc)
		echo "$2 usr/share/doc/\${PKGDEV}" >> "${INSTALLFILE_DEVPKG}"
		shift; shift;
		;;
	  --commit)
		DOIT=yes
		shift;
		;;
	  --multiarch)
		MULTIARCH=yes
		shift;
		;;
	  --extralib)
		EXTRALIBS="${EXTRALIBS} $2"
		shift; shift;
		;;
	  --shlibs-local)
		shift;
		SHLIBSLOCALVER="$1";
		shift;
		;;
	  --suffix)
		shift;
		SUFFIX="$1";
		shift;
		;;
	  --devsuffix)
		shift;
		DEVSUFFIX="$1";
		shift;
		;;
	  --devunversioned)
		DEVUNVERSIONED=yes
		shift;;
	  --ignorelibdep)
		IGNORELIBDEP=yes
		shift;;
	  --c102)
		TRANSITIONSUFFIX="c102"
		shift;;
	  --ldbl)
		TRANSITIONSUFFIX="ldbl"
		shift;;
	  --include-a)
		INCLUDEA=yes
		shift;;
	  --exclude-a)
		INCLUDEA=no
		shift;;
	  --include-la)
		INCLUDELA=yes
		shift;;
	  --exclude-la)
		INCLUDELA=no
		shift;;
	  --override)
		OVERRIDE[${#OVERRIDE[@]}]="$2"
		shift; shift;;
	  --|*)
		break;
		;;
	esac
done

# path/libxxxx.so.yyy.zz.zz
# ------------------------- REALSO (actual .so filename that is linked to)
#      -------------- SONAME
#      -------    --- SONAMEPKGNAME (lowercased for package name)
# --------------- $1
#      ---------- PK
#      ---------- PK_LOWER (lowercased for package name)

DEVLIB_TO_CHECK=
for extralib in $EXTRALIBS; do
	readlibnameinfo "$extralib"
	DEVLIB_TO_CHECK="${DEVLIB_TO_CHECK} $extralib"
	if [ "${INCLUDEA}" = "yes" ]; then
		echo "$(dirname $extralib)/${PK}.a usr/lib"  >> "${INSTALLFILE_DEVPKG}"
	fi
	if [ "${INCLUDELA}" = "yes" ]; then
		echo "$(dirname $extralib)/${PK}.la usr/lib || true"  >> "${INSTALLFILE_DEVPKG}"
	fi
	echo "$(dirname $extralib)/${PK}.so usr/lib"  >> "${INSTALLFILE_DEVPKG}"
	echo "$(dirname ${REALSO})/${SONAME}  usr/lib"  >> "${INSTALLFILE_SHLPKG}"
	echo "${REALSO} usr/lib" >> "${INSTALLFILE_SHLPKG}"
done

DEVLIB_TO_CHECK="${DEVLIB_TO_CHECK} $1"
readlibnameinfo "$1"
if [ "${DEVUNVERSIONED}" = "yes" ]; then
	PKGDEV="${PK_LOWER}${DEVSUFFIX}-dev"
else
	PKGDEV="${SONAMEPKGNAME}${DEVSUFFIX}-dev"
fi
PKGSHL="${SONAMEPKGNAME}${SUFFIX}${TRANSITIONSUFFIX}"

INSTALLDIR="install -d -m 755 "
echo "${INSTALLDIR} debian/${PKGDEV}/usr/lib" >> "$execscript"
echo "${INSTALLDIR} debian/${PKGSHL}/usr/lib"  >> "$execscript"
if [ "${INCLUDEA}" = "yes" ]; then
	echo "mv $(dirname $1)/${PK}.a debian/${PKGDEV}/usr/lib"  >> "$execscript"
fi
if [ "${INCLUDELA}" = "yes" ]; then
	echo "mv $(dirname $1)/${PK}.la debian/${PKGDEV}/usr/lib || true"  >> "$execscript"
fi
echo "mv $(dirname $1)/${PK}.so debian/${PKGDEV}/usr/lib"  >> "$execscript"
echo "mv $(dirname ${REALSO})/${SONAME} debian/${PKGSHL}/usr/lib"  >> "$execscript"
if [ "$(dirname ${REALSO})/${SONAME}" != "${REALSO}" ] ; then
	echo "mv ${REALSO} debian/${PKGSHL}/usr/lib"  >> "$execscript"
fi
if [ -n "${SHLIBSLOCALVER}" ]; then
	echo "echo \"${SONAMELIBNAME} ${SONAMEVERSION} ${PKGSHL} (>= ${SHLIBSLOCALVER})\" >> debian/shlibs.local" >> "$execscript"
fi

d-devlibdeps "${OVERRIDE[@]/#/--override=}"  debian/"${PKGDEV}".substvars "${DEVLIB_TO_CHECK}"

#do some definition for the file.
echo "PKGDEV=${PKGDEV}" >> "${execscript}"
echo "PKGSHL=${PKGSHL}" >> "${execscript}"

#do the extra files
cat "${INSTALLFILE_SHLPKG}" | while read A B; do
	echo "${INSTALLDIR} debian/${PKGSHL}/${B}" >> "${execscript}"
	echo "mv ${A} debian/${PKGSHL}/${B}" >> "${execscript}"
done
if [ "${INCLUDELA}" = "no" ]; then
	sed -i -e "/^.*\.la usr\/lib || true$/d" "${INSTALLFILE_DEVPKG}"
fi
cat "${INSTALLFILE_DEVPKG}" | while read A B; do
	echo "${INSTALLDIR} debian/${PKGDEV}/${B}" >> "${execscript}"
	echo "mv ${A} debian/${PKGDEV}/${B}" >> "${execscript}"
done

if [ "${MULTIARCH}" = "yes" ]; then
	sed -i -e "s/usr\/lib\( || true\)\?$/usr\/lib\/$(dpkg-architecture -qDEB_HOST_MULTIARCH)\1/" "${execscript}"
fi

cat "${execscript}"

# check the syntax of the control file.
CHECK_ERROR=false

if ! [ "${DEVUNVERSIONED}" = "yes" ]; then
	check_line "${PKGDEV}" "Provides:.*${PK_LOWER}-dev"
	check_line "${PKGDEV}" "Conflicts:.*${PK_LOWER}-dev"
fi
check_line "${PKGSHL}" "Section: libs"
if [ -n "${SUFFIX}" ]; then
	check_line "${PKGSHL}" "Conflicts: ${SONAMEPKGNAME}"
fi
if [ -n "${TRANSITIONSUFFIX}" ]; then
	check_line "${PKGSHL}" "Conflicts: ${SONAMEPKGNAME}${SUFFIX}"
fi
check_line "${PKGDEV}" "Section: \(devel\|libdevel\)"
if ! [ "${IGNORELIBDEP}" = "yes" ]; then
	check_line "${PKGDEV}" "Depends:.*${PKGSHL}"
fi
check_line "${PKGSHL}" "Depends:.*[$]{shlibs:Depends}"

if [ "${CHECK_ERROR}" = "true" ]; then
	echo "Error occurred, aborting" >&2
	exit 1
fi

if [ "${DOIT}" = "yes" ]; then
	sh "${execscript}"
else
	echo "Dry-run. If you are satisfied, run with --commit"
	exit 2
fi
rm -f "${execscript}" "${INSTALLFILE_DEVPKG}"" ${INSTALLFILE_SHLPKG}"

exit 0
