#!/bin/bash
#
# Runs pep8 on files changed from parent branch.

# Fail if any of the required tools are not installed.
if ! which pep8 >/dev/null; then
    echo "Error: pep8 is not installed."
    echo "    Install the pep8 package."
    exit 1
fi

EXIT=0

if [ -z "$1" ]; then
    bzr diff > /dev/null
    diff_status=$?
    if [ $diff_status -eq 0 ] ; then
        # No uncommitted changes in the tree.
        bzr status | grep "^Current thread:" > /dev/null
        if [ $? -eq 0 ] ; then
            # This is a loom, lint changes relative to the lower thread.
            rev_option="-r thread:"
        else
            # Lint changes relative to the parent.
            rev=`bzr info | sed \
                '/parent branch:/!d; s/ *parent branch: /ancestor:/'`
            rev_option="-r $rev"
        fi
    elif [ $diff_status -eq 1 ] ; then
        # Uncommitted changes in the tree, return those files.
        rev_option=""
    else
        # bzr diff failed
        exit 1
    fi
    # Extract filename from status line.  Strip the @ that mark symlinks.
    files=`bzr st --short $rev_option |
        sed -e '/^.[MN]/!d; s/.* //' -e 's/@$//'`
else
    # Add newlines so grep filters out pyfiles correctly later.
    files=`echo $* | tr " " "\n"`
fi

echo "= lint ="
echo
echo "Checking for conflicts and issues in changed files."

if [ -z "$files" ]; then
    echo "No changed files detected."
    exit 0
else
    echo
    echo "Linting changed files:"
    for file in $files; do
        echo "  $file"
    done
fi

pep8_header=0
pep8_notices() {
    if [ $pep8_header -eq 0 ]; then
        pep8_header=1
        echo
        echo
        echo "== pep8 notices =="
    fi

    # Format file:line:message output as lines grouped by file.
    file_name=""
    echo "$1" | sed 's,\(^[^ :<>=+]*:\),~~\1\n,' | while read line; do
        current=`echo $line | sed '/^~~/!d; s/^~~\(.*\):$/\1/;'`
        if [ -z "$current" ]; then
            echo "    $line"
        elif [ "$file_name" != "$current" ]; then
            file_name="$current"
            echo
            echo "$file_name"
        fi
    done
}

conflicts=""
for file in $files; do
    # NB. Odd syntax on following line to stop lint.sh detecting conflict
    # markers in itself.
    if [ ! -f "$file" ]; then
        continue
    fi
    if grep -q -e '<<<''<<<<' -e '>>>''>>>>' $file; then
        conflicts="$conflicts $file"
    fi
done

if [ "$conflicts" ]; then
    echo
    echo
    echo "== conflict notices =="
    echo
    for conflict in $conflicts; do
        echo "$conflict"
    done
    EXIT=1
fi

pyfiles=`echo "$files" | egrep '^scripts|\.py$'`
if [ ! -z "$pyfiles" ]; then
    # The grep pattern must be generated from the pep8.py file in the
    # pep8 package of the latest stable release:
    #
    # dpkg -L pep8 \
    #   | grep pep8.py \
    #   | head -n 1 \
    #   | xargs cat \
    #   | sed -n 's/.*\<\(E[[:digit:]][[:digit:]][[:digit:]]\)\>.*/\1/p' \
    #   | sort -u \
    #   | tr '\n' '|'
    grep_pattern="\
(E101|E111|E112|E113|E201|E202|E203|E211|E221|E222|E223|E224|E225|E231\
|E241|E242|E251|E261|E262|E301|E302|E303|E304|E401|E501|E701|E702)"

    # Source files
    srcfiles=`echo "$pyfiles" | egrep '\.py$'`
    if [ ! -z "$srcfiles" ]; then
        result=`pep8 $srcfiles | egrep "$grep_pattern"`
        if [ ! -z "$result" ]; then
            pep8_notices "$result"
            EXIT=1
        fi
    fi

    # Script files
    scriptfiles=`echo "$pyfiles" | egrep '^scripts'`
    if [ ! -z "$scriptfiles" ]; then
        for file in $scriptfiles; do
            if file "$file" | grep -q "python"; then
                result=`pep8 $file | egrep "$grep_pattern"`
                if [ ! -z "$result" ]; then
                    pep8_notices "$result"
                    EXIT=1
                fi
            fi
        done
    fi
fi

exit $EXIT
