blob: e12f17055e41725ad6b3f427a029090fc12f2307 [file] [log] [blame]
#!/bin/sh -efu
# Copyright 2014 Intel Corporation
# Author: Jacob Keller
# License: GPLv2
srcdir="$(readlink -ev -- ${0%/*})"
PATH="$srcdir:$srcdir/..:$srcdir/../helpers:$srcdir/../helpers/libshell:$PATH"
. shell-error
. shell-args
. shell-signal
. aiaiai-sh-functions
. aiaiai-email-sh-functions
PROG="${0##*/}"
export message_time="yes"
# This is a small trick to make sure the script is portable - check if 'dash'
# is present, and if yes - use it.
if can_switch_to_dash; then
exec dash -euf -- "$srcdir/$PROG" "$@"
exit $?
fi
show_usage()
{
cat <<-EOF
Usage: $PROG [options] <cfgfile.ini> <mbox>
This is an example hook used by aiaiai to automatically determine the project
that the commit applies to, by using the index information from the first patch
in the series, and checking each project for information about where patches
apply. It depends on git-find-base which is included in the helpers folder.
<cfgfile.ini> - the configuration file.
<mbox> - the mbox file containing the patch series
EOF
}
fail_usage()
{
[ -z "$1" ] || printf "%s\n" "$1"
show_usage
exit 1
}
verbose=-v
tmpdir=
cleanup_handler()
{
if [ "$cfg_preserve_files" = "1" ]; then
verbose "Preserved tmpdir: $tmpdir"
else
[ -z "$tmpdir" ] || verbose "Removing $tmpdir";
rm -rf -- "$tmpdir" >&2
fi
}
set_cleanup_handler cleanup_handler
[ "$#" -eq 2 ] || fail_usage "Insufficient or too many arguments"
cfgfile="$(readlink -fv -- "$1")"; shift
mbox="$(readlink -fv -- "$1")"; shift
commit=
# Parse the configuration file early
parse_config "$cfgfile"
# Create a temporary directory for storage of any files we might need
tmpdir="$(mktemp --tmpdir="$cfg_workdir" -dt "$PROG.XXXX")"
tmp_find_base="$tmpdir/git-find-base.out"
# Get the expected project from the patch email
to="$(fetch_header "To" < "$mbox")"
cc="$(fetch_header "Cc" < "$mbox")"
list="$(merge_addresses "$to" "$cc")"
expected_prj="$(fetch_project_name "$list" "cfg_ownmail")"
# Get the patch-id for this mbox
patchid="$(git patch-id --stable < "$mbox" | awk '{print $1}')"
# Loop through every project and check if we can find a base commit. If we're
# given an expected project in the email address, try it first, so that we
# don't accidentally land on the wrong one.
for prj in $expected_prj $(get_cfgfile_projects_list "$cfgfile"); do
# First to be safe, unset the project config variables that we use
unset pcfg_branch pcfg_path pcfg_name branch_base
# Now, parse the (new) project for pcfg variables
parse_prj_config "$cfgfile" "$prj"
# Skip non-existent projects
if [ -z "$pcfg_name" ]; then
verbose "Could not find $prj project"
continue
fi
# We set our own project variable called branch_base
branch_base="$(ini_config_get "$cfgfile" "prj_$prj" "branch_base")"
# use git-patch-id to check if the patch has already been applied the
# branch_base and reject the patch in this case.
for rev in $(git --git-dir="$(git_dir "$pcfg_path")" rev-list "$branch_base"); do
revid="$(git --git-dir="$(git_dir "$pcfg_path")" show $rev | git patch-id --stable | awk '{print $1}')"
shortname="$(git --git-dir="$(git_dir "$pcfg_path")" log -1 --pretty="%h (\"%s\")" $rev)"
# if we find a patch-id equivalent commit, exit and skip the patch with a warning to the user.
if [ "$patchid" = "$revid" ]; then
cat <<EOF
Aiaiai found an equivalent commit for this patch already applied to the branch base
${prj} : ${branch_base} -> ${shortname}
It is likely that the maintainer applied your patch before Aiaiai got around to
testing it. No further testing will be performed for your patch, as Aiaiai
would not be able to apply it cleanly.
EOF
exit 127
fi
done
# Use git-find-base with the mbox file as input, and check to see if we
# can find a commit in this project. Use the branch_base if it's
# supplied, otherwise use the parent(s) of pcfg_branch as the limiter.
# This enables only checking a small range instead of having to check
# the full history.
commit="$(git --git-dir="$(git_dir "$pcfg_path")" find-base "$pcfg_branch" "${branch_base:-$pcfg_branch}^!" 2>>"$tmp_find_base" < "$mbox" \
|| verbose "No matching base commit in project $prj" )"
# Break out of loop once we find a base
[ -z "$commit" ] || break;
done
if [ -n "$commit" ]; then
if [ -n "$expected_prj" ] && [ "$expected_prj" != "$prj" ]; then
verbose "Expected project $expected_prj but got $prj"
printf "%s\n" "X-Aiaiai-Expected-Project: $expected_prj"
fi
# We found a commit, so insert proper headers
printf "%s\n" "X-Aiaiai-Project: $prj"
printf "%s\n" "X-Aiaiai-Commit: $commit"
else
if [ -z "$expected_prj" ]; then
verbose "No project found. Output of git-find-base:"
cat "$tmp_find_base" 1>&2
cat <<EOF
Aiaiai was not able to automatically determine the project for your patch
submission using the index information provided by git-diff. This can be caused
because your patch is based on work which is not yet applied to the queue, or
if your patch is based on a really old version of the queue. You might try to
rebase your submission and re-submit against the current development
queue.
EOF
exit 127
fi
fi