#! /bin/bash
#   pbuilder -- personal Debian package builder
#   Copyright © 2001-2007 Junichi Uekawa <dancer@debian.org>
#
#   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
###############################################################################

# The original pbuilder-satisfydepends code, which is now called 'classic'

set -e

export PBUILDER_PKGLIBDIR="${PBUILDER_PKGLIBDIR:-$PBUILDER_ROOT/usr/lib/pbuilder}"

. "$PBUILDER_PKGLIBDIR"/pbuilder-satisfydepends-funcs

# splits lines of deps (possibly with alternates) separated by commas into one
# dep (possibly with alternates) per line; also changes all spaces to slashes
# first as to iterate on deps with "for"; e.g. "foo, bar | baz", "foobar (>=
# 2)"  becomes "foo", "bar/|/baz", "foobar/(>=/2)"
split_deps() {
    sed 's#, *#\n#g; s# #/#g'
}
# and build-conflicts

# splits build-dep with alternates into one alternate per line; e.g. "foo|bar"
# becomes "foo", "bar"
split_alternates() {
    echo "$*" | sed 's/ *| */\n/g'
}

# filters package name out of a "/" escaped simple build-dep, possibly with
# architecture or version specifier; e.g. "/foo/(>=/2)/[i386/amd64]" becomes
# "foo"
get_pkg_name() {
    echo "$*" | sed 's#^/*##; s#[[/(<].*##'
}

# filter operator and version of a "/" escaped versioned build-dep; e.g.
# "foo/(>=/2)" becomes ">= 2"
get_dep_op_and_ver() {
    echo "$*" | sed -n 's#/# #g; s/.*( *\(<<\|<=\|>=\|=\|<\|>>\|>\) *\([^ )]*\) *).*/\1 \2/p'
}

# call apt-get in chroot in simulate mode
apt_sim() {
    $CHROOTEXEC apt-get -s install "$@"
}

# Use this function to fulfill the dependency (almost)
checkbuilddep_internal() {
    local ARCH=$($CHROOTEXEC dpkg-architecture -qDEB_HOST_ARCH)
    local INSTALLPKG
    local INSTALLPKGLIST
    local INSTALLPKGMULTI
    local CURRENTREALPKGNAME
    local SATISFIED
    local APTFLAG="-o APT::Install-Recommends=false"
    echo " -> Attempting to parse the build-deps "
    for INSTALLPKGMULTI in $(get_build_deps | split_deps); do
        echo " -> Considering build-dep $(echo "$INSTALLPKGMULTI" | tr "/" " ")"
        SATISFIED="no"
        for INSTALLPKG in $(split_alternates "$INSTALLPKGMULTI"); do
            CURRENTREALPKGNAME=$(get_pkg_name "$INSTALLPKG")
            if echo "$INSTALLPKG" | grep -q '\['; then
                if checkbuilddep_archdeps "$INSTALLPKG" "$ARCH"; then
                    SATISFIED="yes"
                    echo "   -> This package is not for this architecture"
                    continue
                fi
            fi
            if echo "$INSTALLPKG" | grep -q '<'; then
                if checkbuilddep_restrictiondeps "$INSTALLPKG" "$DEB_BUILD_PROFILES"; then
                    SATISFIED="yes"
                    echo "   -> This package is not for the current build profiles"
                    continue
                fi
            fi
            if echo "$INSTALLPKG" | grep -q '('; then
                #echo "Debug: $INSTALLPKG"
                if ! checkbuilddep_versiondeps "$CURRENTREALPKGNAME" $(get_dep_op_and_ver "$INSTALLPKG"); then
                  echo "   -> Does not satisfy version, not trying"
                  continue
                fi
            fi
            echo "   -> Trying $CURRENTREALPKGNAME"

            if apt_sim $APTFLAG $INSTALLPKGLIST $CURRENTREALPKGNAME >& /dev/null; then
                SATISFIED="yes"
                INSTALLPKGLIST="$INSTALLPKGLIST $CURRENTREALPKGNAME"
            else
                echo "       -> Cannot install $CURRENTREALPKGNAME; apt errors follow:"
                if apt_sim $APTFLAG $INSTALLPKGLIST "$CURRENTREALPKGNAME"; then
                    :
                fi
                # package could not be found. -- looking for alternative.
                PROVIDED=""
                checkbuilddep_provides "$CURRENTREALPKGNAME"
                if [ -n "$PROVIDED" ]; then
                    # something provides this package
                    echo "     -> Considering $PROVIDED to satisfy the dependency "
                    if apt_sim $APTFLAG $INSTALLPKGLIST $PROVIDED >& /dev/null; then
                        SATISFIED="yes";
                        INSTALLPKGLIST="$INSTALLPKGLIST $PROVIDED"
                    else
                        # show the error for diagnostic purposes
                        echo "       -> Cannot install $PROVIDED; apt errors follow:"
                        apt_sim $APTFLAG $INSTALLPKGLIST $PROVIDED || true
                    fi
                fi
            fi
            if [ "$SATISFIED" = "yes" ]; then
                break;
            fi
        done;
    if [ "$SATISFIED" = "no" ]; then
        echo "E: Could not satisfy build-dependency." >&2
        if [ "$CONTINUE_FAIL" != "yes" ]; then
            exit 2
        fi
    fi
    done;

    # now actually install the packages
    echo " -> Installing $INSTALLPKGLIST"
    if ! $CHROOTEXEC apt-get -q -y "${APTGETOPT[@]}" install $APTFLAG $INSTALLPKGLIST; then
        echo " -> Trying to fix apt error"
        # Work around an apt bug which causes configure to fail.
        if $CHROOTEXEC dpkg --configure --pending && $CHROOTEXEC apt-get -q -y "${APTGETOPT[@]}" install $APTFLAG $INSTALLPKGLIST; then
            echo " -> Apt bug workaround succeeded"
        elif [ "$CONTINUE_FAIL" != "yes" ]; then
            echo "E: Unrecoverable error installing build-dependencies." >&2
            exit 1
        fi
    fi

    # start processing build-conflicts.
    for INSTALLPKG in $(get_build_conflicts | split_deps); do
        CURRENTREALPKGNAME=$(get_pkg_name "$INSTALLPKG")
        echo " -> Considering $CURRENTREALPKGNAME"

        if echo "$INSTALLPKG" | grep -q '\['; then
            # this package has arch-conflicts.
            if checkbuilddep_archdeps "$INSTALLPKG" "$ARCH"; then
                echo "I: Ignoring other-arch"
                continue
            fi
        fi
        if echo "$INSTALLPKG" | grep -q '<'; then
            # this package has build-profiles-conflicts.
            if checkbuilddep_restrictiondeps "$INSTALLPKG" "$DEB_BUILD_PROFILES"; then
                echo "I: Ignoring other-buildprofiles"
                continue
            fi
        fi
        if echo "$INSTALLPKG" | grep -q '('; then
            # this package has version-conflicts
            if ! checkbuilddep_versiondeps "$CURRENTREALPKGNAME" $(get_dep_op_and_ver "$INSTALLPKG"); then
                echo "I: Satisfies version, not trying"
                continue
            fi
        fi

        # if package exists, remove it.
        if $CHROOTEXEC dpkg -s "$CURRENTREALPKGNAME" 2>&1 | grep -q ^Package:; then
            if ! $CHROOTEXEC apt-get -q -y remove "$CURRENTREALPKGNAME" ; then
                echo "E: Could not satisfy build-conflicts" >&2
                exit 1
            fi
        else
            echo "I: $CURRENTREALPKGNAME package is not installed, no need to remove"
        fi
    done
    echo " -> Finished parsing the build-deps"
}


print_help() {
    # print out help message
    cat <<EOF
pbuilder-satisfydepends -- satisfy dependencies
Copyright 2002-2007  Junichi Uekawa <dancer@debian.org>

--help:        give help
--control:     specify control file (debian/control, *.dsc)
--chroot:      operate inside chroot
--binary-all:  include binary-all
--binary-arch: include binary-arch only
--echo:        echo mode, do nothing. (--force-version required for most operation)
--force-version: skip version check.
--continue-fail: continue even when failed.

EOF
}

. "$PBUILDER_PKGLIBDIR"/pbuilder-satisfydepends-checkparams

