#!/bin/sh -e

# generate debug symbol package for a given binary package within a built
# debian source tree.
#
# Author: Martin Pitt <martin.pitt@ubuntu.com>
# (C) 2006 Canonical Ltd.
#
#
# 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA

# evaluate options
blacklist=""
add_to_files=0

for p; do
    case $p in
        -X*)
            blacklist=`/bin/echo -e "${p#-X}\n$blacklist"`
            shift
            ;;
        -a)
            add_to_files=1
            shift
            ;;
        *)
            break
            ;;
    esac
done

pkgname="$1"
pkgpath="$2"
nodebuglink="$3"

[ -n "$pkgpath" ] || pkgpath="debian/$pkgname"

[ -d "$pkgpath" ] || {
    if [ -z "$pkgname" ]; then
	echo "Usage: $0 [-Xitem] [-n] <binary package name> [<package path>] [nodebuglink]"
    else
	echo "Directory $pkgpath does not exist, aborting" >&2
    fi
    exit 1
}

p=`readlink -f "$pkgpath"` # original package path
dp="debian/${pkgname}-dbgsym" # debug package path
dp=`readlink -f "$dp"` # debug package path

# find all ELF files and extract their debug symbols; also add debug links
# to original files; if we do not find any unstripped files, then a likely
# cause is that we already ran this program on the current package, in which
# case we must not run it again to not destroy debug link CRC sums and produce
# empty ddebs
unset any_unstripped
origdir=`pwd`
cd $p
find -type f | ( while read f; do
    # ignore static libraries
    if echo "$f" | grep -q '\.[ao]$'; then continue; fi
    # ignore non-ELF files
    readelf -h "$f" > /dev/null 2>&1 || continue
    # check blacklist
    if [ -n "$blacklist" ]; then
        if echo "$f" | fgrep -q "$blacklist"; then continue; fi
    fi
    if ! readelf -S "$f" | grep -q ' .debug_'; then
	# no debug information
	continue
    fi
    any_unstripped=1

    mkdir -p $dp/usr/lib/debug/`dirname "$f"`
    objcopy --only-keep-debug "$f" "$dp/usr/lib/debug/$f" || {
	echo "objcopy --only-keep-debug failed on `readlink -f $f`" >&2
	exit 1
    }	
    [ -n "$nodebuglink" ] || objcopy -R .gnu_debuglink --add-gnu-debuglink="$dp/usr/lib/debug/$f" "$f" || {
	echo "objcopy --add-gnu-debuglink failed on `readlink -f $f`" >&2
	exit 1
    }
done
if [ -z "$any_unstripped" ]; then
    echo "$pkgname is already stripped, ignoring" >&2
    rm -rf $dp
    exit 0
fi
)
cd $origdir

if [ ! -d "$dp" ] || [ -z "`find $dp -type f`" ]; then
    rm -rf $dp
    exit 0
fi

mkdir -p $dp/DEBIAN

# determine set of -dbg packages, which we need to conflict to
conflicts=
for p in `grep '^Package:.*-dbg' debian/control | cut -f 2 -d\ `; do
    # do not conflict to python dbg packages
    [ "$p" = "${p#python-}" ] || continue
    if [ -z "$conflicts" ]; then
        conflicts="$p"
    else
        conflicts="$conflicts, $p"
    fi
done
[ -z "$conflicts" ] || conflicts="\nConflicts: $conflicts"

# generate a control file for current package (since it is usually not yet
# existing) and adapt it to be suitable for the dbgsym package
perl -p000 -e 's/^(?:Pre-Depends|Depends|Recommends|Suggests|Conflicts|Provides|Replaces|Breaks|Essential):.*?\n(?![ \t])//msg' debian/control |
    dpkg-gencontrol -c- -fdhstrip-dummy-debian-files -p$pkgname -is -ip -Pdebian/$pkgname-dbgsym -O | 
    sed "s/^Priority:.*$/Priority: extra/;
    s/^Version: \(.*\)$/&\nDepends: $pkgname (= \1)$conflicts/;
    s/^Package:.*$/&-dbgsym/;
    s/^Description:.*$/Description: debug symbols for package $pkgname/" \
    > $dp/DEBIAN/control
rm -f dhstrip-dummy-debian-files

# binaries named the same as the source will lack a Source field.
# since we are renaming binaries, we might need to add one.
if [ -z "`grep ^Source: $dp/DEBIAN/control`" ]; then
    sed -i "s/^Package:.*$/&\nSource: $pkgname/" $dp/DEBIAN/control
fi

# extract package name, version, architecture
ddebname=${pkgname}-dbgsym
ddebversion=`grep '^Version:' $dp/DEBIAN/control | cut -f2- -d\ `
ddebversion=${ddebversion#*:} # strip off epoch
ddebarch=`grep '^Architecture:' $dp/DEBIAN/control | cut -f2- -d\ `
ddebsection=`grep '^Section:' $dp/DEBIAN/control | cut -f2- -d\ `
ddebpriority=`grep '^Priority:' $dp/DEBIAN/control | cut -f2- -d\ `

[ -n "$ddebsection" -a -n "$ddebpriority" ] || {
    echo "Error: parsed ddeb section or priority is empty" >&2
    exit 1
}
ddeb="${ddebname}_${ddebversion}_${ddebarch}.ddeb"

# build .ddeb and add it to debian/files
NO_PKG_MANGLE=1 dpkg-deb --build $dp ../$ddeb
if [ "$add_to_files" = "1" ]; then
    dpkg-distaddfile "$ddeb" "$ddebsection" "$ddebpriority"
fi

# clean up, since this package does not appear in debian/control
rm -rf $dp
