From 1e9871f06a50adb529695ec7c4e3b7311c4c3f53 Mon Sep 17 00:00:00 2001 From: Hugo Villeneuve Date: Wed, 14 Dec 2022 10:06:21 -0500 Subject: [PATCH] Add kernel send patches script --- scripts/Makefile.am | 1 + scripts/kernel-send-patches.sh | 251 +++++++++++++++++++++++++++++++++ 2 files changed, 252 insertions(+) create mode 100755 scripts/kernel-send-patches.sh diff --git a/scripts/Makefile.am b/scripts/Makefile.am index 0be64ab..543edfa 100644 --- a/scripts/Makefile.am +++ b/scripts/Makefile.am @@ -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 index 0000000..091dfa8 --- /dev/null +++ b/scripts/kernel-send-patches.sh @@ -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 -- 2.20.1