#!/bin/bash
#
# Copyright (C) 2011 Christian Dietrich <christian.dietrich@informatik.uni-erlangen.de>
# Copyright (C) 2009-2012 Reinhard Tartler <tartler@informatik.uni-erlangen.de>
#
# 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 3 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, see <http://www.gnu.org/licenses/>.
#

#
# This script is intended to be used in automatic cronjobs for
# scanning the linux git tree for dead blocks and do coverage analysis
# on it.
#

set -e
set -o pipefail

giturl="git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git"

function usage() {
    echo "usage: ${0##*/} <-d DIR> [-c REV] [-t PROCS]"
    echo " -d   directory the linux tree will be cloned to"
    echo " -t   undertaker processes to be run"
    echo "      default: _NPROCESSORS_ONLN"
    echo " -c   commit (revspec) to be used"
    echo "      default: master (but can also be a tag like refs/tags/v3.1)"
    exit 2
}

while getopts ":d:t:c:" OPT; do
    case $OPT in
        d)
            GIT_DIRECTORY="$OPTARG"
            ;;
        t)
            PROCESSORS="$OPTARG"
            ;;
        c)
            COMMIT="$OPTARG"
            ;;
        *)
           usage
           ;;
    esac
done
shift $(( OPTIND - 1 ))
OPTIND=1

PROCESSORS=${PROCESSORS:-$(getconf _NPROCESSORS_ONLN)}
COMMIT=${COMMIT:-master}
TIME="$(type -P time)"

if [ -z "$GIT_DIRECTORY" ]; then
    echo "Error: No directory for the linux tree was given."
    echo
    usage
fi

if ! type -p undertaker-kconfigdump >/dev/null; then
    echo "No undertaker-kconfigdump executable found."
    exit 1
fi

if ! type -p undertaker-linux-tree >/dev/null; then
    echo "No undertaker-linux-tree executable found."
    exit 1
fi

if [ ! -d "$GIT_DIRECTORY" ]; then
    if ! git clone "$giturl" "$GIT_DIRECTORY"; then
        echo "Repository on kernel.org failed, fetching sources from github instead"
        if ! git fetch -q --tags git://github.com/torvalds/linux.git "$COMMIT"; then
            echo "Failed to clone the linux kernel."
            exit 1
        fi
    fi
fi

resultdir="$GIT_DIRECTORY"/results
cd "$GIT_DIRECTORY"
mkdir -p "$resultdir"

if ! git fetch -q --tags "$giturl" "$COMMIT"; then
    echo "Repository on kernel.org failed, fetching sources from github instead"
    if ! git fetch -q --tags git://github.com/torvalds/linux.git "$COMMIT"; then
        echo "Failed to update the kernel sources, but continuing anyways"
    fi
fi

if ! git reset --hard FETCH_HEAD; then
    echo "Failed to set requested revision, aborting"
    exit 1
fi

echo "Running on Linux Version $(git describe || echo '(no git)')"
echo "Using $(undertaker -V)"

if ! git clean -fxq; then
    echo "git clean failed - check for write permissions in $GIT_DIRECTORY"
    exit 1
fi

version="$(git describe || date +%Y-%m-%d-%H:%M)"
report="${resultdir}/${version}-report.txt"
deadlist="${resultdir}/${version}-deads.txt"

echo "Scanning version ${version}, logging to ${report}"


echo "Step 0: Extract Kconfig feature dependencies"
echo "     -> General constraints from all architectures"
if $TIME -v -o kconfigdump.stats -- undertaker-kconfigdump  >"$report" \
      2>kconfigdump-error-output.txt; then
    cat kconfigdump.stats
else
    echo "Failed to dump models. Check your installation"
    cat kconfigdump-error-output.txt
    exit 1
fi
if ! test -s kconfigdump-error-output.txt; then
    rm -f kconfigdump-error-output.txt
fi
echo "     -> From Makefiles for x86"
if $TIME -v -o inference.stats -- undertaker-linux-tree -i -t ${PROCESSORS} >>"$report" \
      2>inference-errors.txt; then
    cat inference.stats
    echo "Extracted $(grep -c ^FILE_ models/x86.makefile-constraints) source file implications for arch-x86."
    echo "Used $(grep -c "partial configuartion" models/x86.makefile-constraints) partial configurations"
    grep "^FILE_" models/x86.makefile-constraints >> models/x86.model
else
    echo "Dependency extraction from makefiles failed."
    cat inference-errors.txt
fi
if ! test -s inference.errors; then
    rm -f inference-errors.txt
fi

echo "Step 1: Dead/Undead analysis"
if $TIME -v -o undertaker.stats -- undertaker-linux-tree -t ${PROCESSORS} >>"$report" \
      2>undertaker-errors.txt; then
    cat undertaker.stats
    find . -name '*dead' -ls > "$deadlist"
    echo "Found $(grep globally $deadlist | wc -l) globally dead blocks"
else
    echo "Scanning for Dead features failed, check the error logfiles!"
    cat undertaker-errors.txt
fi
if ! test -s undertaker-errors.txt; then
    rm -f kconfigdump-error-output.txt
fi


echo "Step 2: Coverage analysis"
if $TIME -v -o undertaker-coverage.stats -- undertaker-linux-tree -t ${PROCESSORS} -c \
      2>undertaker-coverage-errors.txt; then
    cat undertaker-coverage.stats
    found_configs=`grep -c ^CONFIG undertaker-calc-coverage.output`
    processed_files=`grep -c ^RESULT undertaker-calc-coverage.output`
    echo "Processed $found_configs (partial) configurations on $processed_files files"
else
    echo "Coverage analysis failed with exit code $?, check the error logfiles!"
    cat undertaker-coverage-errors.txt
fi
if ! test -s undertaker-coverage-errors.txt; then
    rm -f undertaker-coverage-errors.txt
fi


echo "Step 3: CPP symbol statistics"
if $TIME -v -o undertaker-cppsym.stats -- undertaker-linux-tree -t ${PROCESSORS} -s \
      2>undertaker-cppsym-stat-errors.txt; then
    cat undertaker-cppsym.stats
    echo "CPP symbols statistics done, check undertaker-stat/*"
else
    echo "CPP symbols statistics failed with exit code $?. check the error logfiles."
    cat undertaker-cppsym-stat-errors.txt
fi
if ! test -s undertaker-cppsym-stat-errors.txt; then
    rm -rf undertaker-cppsym-stat-errors.txt
fi

exit 0
