Blob Blame History Raw
#! /bin/sh

#############################################################################
# Copyright (c) 2008,2009 Novell, Inc.
# All Rights Reserved.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of version 2 of the GNU General Public License as
# published by the Free Software Foundation.
#
# 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, contact Novell, Inc.
#
# To contact Novell about this file by physical or electronic mail,
# you may find current contact information at www.novell.com
#############################################################################

# Make sure we have a properly formatted patch header

set -e

usage()
{
    echo "Usage:"
    echo "  $0 [--relaxed] file.."
    echo "  $0 --stdin [--relaxed] [name]"
}

# Extract the header of a patch
patch_header()
{
    local patch_file=$1

    /usr/bin/gawk '
    /^--- / { exit }
    /^Index:[ \t]|^diff[ \t]|^==*$|^RCS file: |^retrieving revision [0-9]+(\.[0-9]+)*$/ \
        { eat = eat $0 "\n"
          next }
        { print eat $0
          eat = "" }
    ' "$patch_file"
}


moan()
{
    echo "$*" >&2
    bad=1
}

check_patch()
{
    local filename=$1 content=$2
    local header="$(patch_header "$content")"
    local required_headers="Subject From"

    if ! $relaxed; then
        required_headers="$required_headers Patch-mainline"
    fi
    for tag in $required_headers; do
        if ! echo "$header" | grep -iq "^$tag:.*[[:alnum:]]"; then
            moan "$filename: No $tag header"
        fi
    done

    # Allow patches without a suse signoff in private clones
    suse_domains_re='(suse\.(de|com|cz)|novell\.com)'
    if ! git var GIT_COMMITTER_IDENT | grep -Eiq "@$suse_domains_re>"; then
        return
    fi
    if ! echo "$header" | \
        grep -Eiqe "^(From|Signed-off-by|Acked-by):.*@(suse\.(de|com|cz)|novell\.com)\>"; then
        moan "$filename: An email address with @suse.de," \
             "@suse.com, @suse.cz, or @novell.com in the From," \
             "Signed-off-by, or Acked-by headers is required"
    fi

    if grep -HEn '^(---|\+\+\+) .*//' --label "$filename" <"$content" >&2; then
        moan "Please avoid double-slashes in filenames, it breaks series2git"
    fi
}


options=$(getopt -o h --long help,stdin,relaxed -- "$@")
if test $? -ne 0; then
    usage >&2
    exit 1
fi
eval set -- "$options"
stdin=false
relaxed=false
while :; do
    case "$1" in
    --stdin)
        stdin=true
        shift
        ;;
    --relaxed)
        relaxed=true
        shift
        ;;
    -h|--help)
        usage
        exit 0
        ;;
    --)
        shift
        break;
    esac
done

bad=0
if $stdin; then
    case $# in
    0)
        filename="<stdin>"
        ;;
    1)
        filename=$1
        ;;
    *)
        echo "--stdin only works with a single filename" >&2
        usage >&2
        exit 1
    esac
    content=$(mktemp /tmp/check-patch.XXXXXXXXXX)
    trap "rm -f $content" EXIT
    cat >"$content"
    check_patch "$filename" "$content"
else
    if test $# -eq 0; then
        echo "No patches given" >&2
        usage >&2
        exit 1
    fi
    for filename in "$@"; do
        check_patch "$filename" "$filename"
    done
fi

if test $bad -gt 0; then
    echo "For more information, see the Patch Headers chapter in the README file." >&2
fi

exit $bad