From e7164ad87748f9098f366e4c2deb3008549b6c1b Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Thu, 27 Mar 2014 11:40:08 -0700 Subject: [PATCH] email: example hook for aiaiai-email-test-patchset This commit introduces an example hook which uses git-find-base to determine what project (and even what commit inside that project!) the patch is based on. This can be used so that patches automatically go to the correct project, without having to specify the project in the email address. Signed-off-by: Jacob Keller Signed-off-by: Artem Bityutskiy --- email/aiaiai-email-autodetect-project | 153 ++++++++++++++++++++++++++ 1 file changed, 153 insertions(+) create mode 100755 email/aiaiai-email-autodetect-project diff --git a/email/aiaiai-email-autodetect-project b/email/aiaiai-email-autodetect-project new file mode 100755 index 0000000..93a33fe --- /dev/null +++ b/email/aiaiai-email-autodetect-project @@ -0,0 +1,153 @@ +#!/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] + +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. + + - the configuration file. + - the mbox file containing the patch series + +Options: + -v, --verbose be verbose; + -h, --help show this text and exit. +EOF +} + +fail_usage() +{ + [ -z "$1" ] || printf "%s\n" "$1" + show_usage + exit 1 +} + +verbose= +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 + +TEMP=`getopt -n $PROG -o i:,C:,p,v,h --long input:,verbose,help -- "$@"` || + fail_usage "" +eval set -- "$TEMP" + +while true; do + case "$1" in + -v|--verbose) verbose=-v + ;; + -h|--help) + show_usage + exit 0 + ;; + --) shift; break + ;; + *) fail_usage "Unrecognized option: $1" + ;; + esac + shift +done + +[ "$#" -eq 2 ] || die "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")" + +# 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")" + +# 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 $(parse_config_supported_projects "$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-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}^!" < "$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 + cat <