Add kernel send patches script
authorHugo Villeneuve <hvilleneuve@dimonoff.com>
Wed, 14 Dec 2022 15:06:21 +0000 (10:06 -0500)
committerHugo Villeneuve <hugo@hugovil.com>
Thu, 22 Dec 2022 17:01:09 +0000 (12:01 -0500)
scripts/Makefile.am
scripts/kernel-send-patches.sh [new file with mode: 0755]

index 0be64ab..543edfa 100644 (file)
@@ -13,6 +13,7 @@ dist_bin_SCRIPTS = \
     hv-backup \
     hv-video-dvd \
     iso8859-to-utf8.sh \
+    kernel-send-patches.sh \
     mail-files mail-if-fail mail-statistics \
     replace.pl \
     rotatelogs \
diff --git a/scripts/kernel-send-patches.sh b/scripts/kernel-send-patches.sh
new file mode 100755 (executable)
index 0000000..091dfa8
--- /dev/null
@@ -0,0 +1,251 @@
+#!/bin/bash
+
+# Send a patch series with a cover letter.
+
+# Example usage (dry-run, no emails are sent):
+#    kernel-send-patches.sh -f rtc -s "Add PCF2131 patches infos" -e "dt-bindings: rtc: pcf2127: add PCF2131"
+#
+# Example usage (emails are sent):
+#    add "-r" option
+
+set -e
+
+PROG_NAME=$(basename $0)
+
+trap 'catch $?' EXIT
+
+catch()
+{
+    if [ "$1" != "0" ]; then
+        # Error handling goes here
+        echo "Error $1 occurred"
+
+        if [ x"${orig_branch}" != x"" ]; then
+            git checkout ${orig_branch}
+            git rebase --abort
+        fi
+    fi
+
+    # Cleanup for both normal exit and error:
+    rm -f /tmp/all.patch
+    rm -f ${compile_script}
+}
+
+# --non: do not print name for each email address
+TO_CMD="`pwd`/scripts/get_maintainer.pl --nogit --nogit-fallback --norolestats --non --nol"
+CC_CMD="`pwd`/scripts/get_maintainer.pl --nogit --nogit-fallback --norolestats --non --nom"
+
+# Set default values
+commit_start=""
+commit_end=""
+DRY_RUN="--dry-run"
+orig_branch=""
+srcdir=""
+compile_cmd="make"
+compile_script=/tmp/kernel-compile-script.sh
+
+print_usage()
+{
+    echo "${PROG_NAME} -- Envoi de patches linux kernel"
+    echo "Usage: ${PROG_NAME} [OPTIONS...] COMMIT_START COMMIT_END"
+    echo
+    echo "Options:"
+    echo "  -e   end commit (string)"
+    echo "  -f   folder containing patch infos"
+    echo "  -h   display this help and exit"
+    echo "  -r   really send emails (default = dry-run)"
+    echo "  -s   start commit (string)"
+    echo
+}
+
+while getopts "e:f:hrs:" flag ;do
+    case ${flag} in
+        e)
+            commit_end="${OPTARG}"
+            ;;
+        f)
+            srcdir="${OPTARG}"
+            ;;
+       h)
+           print_usage
+            exit 0
+            ;;
+        r)
+            DRY_RUN=""
+            ;;
+        s)
+            commit_start="${OPTARG}"
+            ;;
+        ?)
+            echo "${PROG_NAME}: Option invalide: ${OPTARG}."
+            echo "Essayez \`${PROG_NAME} -h' pour plus d'informations."
+            exit 1
+            ;;
+    esac
+done
+shift `expr "${OPTIND}" - 1`
+
+# `$#' now represents the number of arguments after the options.
+# `$1' is the first argument, etc.
+if [ $# -ne 0 ]; then
+    echo "${PROG_NAME}: Too many arguments."
+    echo "Essayez \`${PROG_NAME} -h' pour plus d'informations."
+    exit 1
+fi
+
+if [ x"${srcdir}" = x"" ]; then
+    echo "Missing source directory"
+    exit 1
+fi
+
+if [ ! -d ${srcdir} ]; then
+    echo "Source directory not found"
+    exit 1
+fi
+
+if [ ! -f ${srcdir}/cover-letter.txt ]; then
+    echo "Missing cover letter template"
+    exit 1
+fi
+
+if [ ! -f ${srcdir}/infos.sh ]; then
+    echo "Missing patch infos file \"${srcdir}/infos.sh\""
+    exit 1
+fi
+
+source ${srcdir}/infos.sh
+
+if [ x"${commit_start}" = x"" ]; then
+    echo "Missing start commit message"
+    exit 1
+fi
+
+if [ x"${commit_end}" = x"" ]; then
+    echo "Missing end commit message"
+    exit 1
+fi
+
+
+if [ x"${series}" = x"" ]; then
+    echo "Missing series shell variable"
+    exit 1
+fi
+
+if [ x"${subject}" = x"" ]; then
+    echo "Missing subject shell variable"
+    exit 1
+fi
+
+if [ x"${cc_list}" = x"" ]; then
+    echo "Missing cc_list shell variable"
+    exit 1
+fi
+
+patches_branch="kernel_send_patches_v${series}_$(basename ${srcdir})"
+
+# First arg: commit message
+find_commit_by_log()
+{
+    echo $(git log --oneline HEAD~100..HEAD | grep "${1}" | awk {'print $1'})
+}
+
+# Because the cover letter is a special case and not a real patch, running
+# get_maintainer.pl on it would not return any TO or CC addresses.
+# Therefore, manually run get_maintainer.pl on the concatenation of all the
+# patches to build a list of TO and CC addresses, and use these for sending
+# all emails, including cover letter and actual patches.
+collect_email_addresses()
+{
+    cat ${srcdir}/v${series}-*.patch > /tmp/all.patch
+
+    # These variables will have one email address per line"
+    TO_MAIL="$(${TO_CMD} /tmp/all.patch)"
+    CC_MAIL="$(${CC_CMD} /tmp/all.patch)"
+
+    while IFS= read -r line; do
+        TO_OPTS="${TO_OPTS} --to ${line}"
+    done <<< "${TO_MAIL}"
+
+    while IFS= read -r line; do
+        CC_OPTS="${CC_OPTS} --cc ${line}"
+    done <<< "${CC_MAIL}"
+
+    for address in ${cc_list}; do
+        CC_OPTS="${CC_OPTS} --cc ${address}"
+    done
+}
+
+COMMIT_START_SHA1=$(find_commit_by_log "${commit_start}")
+
+if [ x"${COMMIT_START_SHA1}" = x"" ]; then
+    echo "Cannot find start commit identified by: \"${commit_start}\""
+    exit 1
+fi
+
+COMMIT_END_SHA1=$(find_commit_by_log "${commit_end}")
+
+if [ x"${COMMIT_END_SHA1}" = x"" ]; then
+    echo "Cannot find end commit identified by: \"${commit_end}\""
+    exit 1
+fi
+
+rm -rf ${srcdir}/*.patch
+
+git format-patch -v ${series} --output-directory=${srcdir} --cover-letter ${COMMIT_START_SHA1}..${COMMIT_END_SHA1}
+
+# Replace subject line in cover letter:
+sed -i -e "s/\*\*\* SUB.*/${subject}/" ${srcdir}/v${series}-0000-cover-letter.patch
+
+# Replace blurb line in cover letter:
+sed -i -e "/.*BLURB.*/{r ${srcdir}/cover-letter.txt" -e 'd}' ${srcdir}/v${series}-0000-cover-letter.patch
+
+collect_email_addresses
+
+# Check patches (except special case of cover letter patch):
+for p in ${srcdir}/*.patch; do
+    if [ x"$(basename ${p})" != x"v${series}-0000-cover-letter.patch" ]; then
+        if [ x"${ignore_checkpatch_errors}" != x"" ]; then
+            set +e
+            CHECKPATCH_OPS="--ignore ${ignore_checkpatch_errors}"
+        fi
+
+        scripts/checkpatch.pl ${CHECKPATCH_OPS} ${p}
+
+        if [ x"${ignore_checkpatch_errors}" != x"" ]; then
+            set -e
+        fi
+    fi
+done
+
+orig_branch=$(git branch --show-current)
+
+if [ x"${orig_branch}" = x"" ]; then
+    echo "Error: unable to determine current branch"
+    exit 1
+fi
+
+cat > ${compile_script} << "EOF"
+#!/bin/bash
+# Do not edit, auto-generated script
+echo
+echo "Testing commit: $(git log --oneline | head -n 1)"
+COMPILE_CMD
+EOF
+
+sed -i -e "s@COMPILE_CMD@${compile_cmd}@" ${compile_script}
+chmod u+x ${compile_script}
+
+# Compile each commit. Create branch to avoid "detached HEAD" state, and also to
+# keep a record of what was sent:
+if git branch | grep -q ${patches_branch}; then
+    git branch -D ${patches_branch}
+fi
+git checkout -b ${patches_branch} ${COMMIT_END_SHA1}
+git rebase --exec=${compile_script} ${COMMIT_START_SHA1}
+git checkout ${orig_branch}
+
+# Send email(s)
+git send-email ${DRY_RUN} --annotate --thread --no-chain-reply-to \
+    ${TO_OPTS} ${CC_OPTS} \
+    --8bit-encoding=UTF-8 \
+    ${srcdir}/*.patch