1#!/bin/bash
2#
3# Copyright (c) 2010-2011,  Intel Corporation.
4#
5# SPDX-License-Identifier: GPL-2.0-or-later
6#
7
8#
9# This script is intended to be used to send a patch series prepared by the
10# create-pull-request script to Open Embedded and The Yocto Project, as well
11# as to related projects and layers.
12#
13
14AUTO=0
15AUTO_CL=0
16GITSOBCC="--suppress-cc=all"
17
18# Prevent environment leakage to these vars.
19unset TO
20unset CC
21unset AUTO_CC
22unset EXTRA_CC
23
24usage()
25{
26cat <<EOM
27Usage: $(basename $0) [-h] [-a] [-c] [[-t email]...] -p pull-dir 
28  -a           Send the cover letter to every recipient listed in Cc and
29               Signed-off-by lines found in the cover letter and the patches.
30	       This option implies -c.
31  -c           Expand the Cc list for the individual patches using the Cc and
32               Signed-off-by lines from the same patch.
33  -C           Add extra CC to each email sent.
34  -p pull-dir  Directory containing summary and patch files
35  -t email     Explicitly add email to the recipients
36EOM
37}
38
39# Collect addresses from a patch into AUTO_CC
40# $1: a patch file
41harvest_recipients()
42{
43	PATCH=$1
44	export IFS=$',\n'
45	for REGX in "^[Cc][Cc]: *" "^[Ss]igned-[Oo]ff-[Bb]y: *"; do
46		for EMAIL in $(sed '/^---$/q' $PATCH | grep -e "$REGX" | sed "s/$REGX//"); do
47			if [ "${AUTO_CC/$EMAIL/}" == "$AUTO_CC" ] && [ -n "$EMAIL" ]; then
48				if [ -z "$AUTO_CC" ]; then
49					AUTO_CC=$EMAIL;
50				else
51					AUTO_CC="$AUTO_CC,$EMAIL";
52				fi
53			fi
54		done
55	done
56	unset IFS
57}
58
59# Parse and verify arguments
60while getopts "acC:hp:t:" OPT; do
61	case $OPT in
62	a)
63		AUTO=1
64		GITSOBCC="--signed-off-by-cc"
65		AUTO_CL=1
66		;;
67	c)
68		AUTO=1
69		GITSOBCC="--signed-off-by-cc"
70		;;
71	C)
72		EXTRA_CC="$OPTARG"
73		;;
74	h)
75		usage
76		exit 0
77		;;
78	p)
79		PDIR=${OPTARG%/}
80		if [ ! -d $PDIR ]; then
81			echo "ERROR: pull-dir \"$PDIR\" does not exist."
82			usage
83			exit 1
84		fi
85		;;
86	t)
87		if [ -n "$TO" ]; then
88			TO="$TO,$OPTARG"
89		else
90			TO="$OPTARG"
91		fi
92		;;
93	esac
94done
95
96if [ -z "$PDIR" ]; then
97	echo "ERROR: you must specify a pull-dir."
98	usage
99	exit 1
100fi
101
102
103# Verify the cover letter is complete and free of tokens
104if [ -e $PDIR/0000-cover-letter.patch ]; then
105	CL="$PDIR/0000-cover-letter.patch"
106	for TOKEN in SUBJECT BLURB; do
107		grep -q "*** $TOKEN HERE ***" "$CL"
108		if [ $? -eq 0 ]; then
109			echo "ERROR: Please edit $CL and try again (Look for '*** $TOKEN HERE ***')."
110			exit 1
111		fi
112	done
113else
114	echo "WARNING: No cover letter will be sent."
115fi
116
117# Harvest emails from the generated patches and populate AUTO_CC.
118if [ $AUTO_CL -eq 1 ]; then
119	for PATCH in $PDIR/*.patch; do
120		harvest_recipients $PATCH
121	done
122fi
123
124AUTO_TO="$(git config sendemail.to)"
125if [ -n "$AUTO_TO" ]; then
126	if [ -n "$TO" ]; then
127		TO="$TO,$AUTO_TO"
128	else
129		TO="$AUTO_TO"
130	fi
131fi
132
133if [ -z "$TO" ] && [ -z "$AUTO_CC" ]; then
134	echo "ERROR: you have not specified any recipients."
135	usage
136	exit 1
137fi
138
139
140# Convert the collected addresses into git-send-email argument strings
141export IFS=$','
142GIT_TO=$(for R in $TO; do echo -n "--to='$R' "; done)
143GIT_CC=$(for R in $AUTO_CC; do echo -n "--cc='$R' "; done)
144GIT_EXTRA_CC=$(for R in $EXTRA_CC; do echo -n "--cc='$R' "; done)
145unset IFS
146
147# Handoff to git-send-email. It will perform the send confirmation.
148# Mail threading was already handled by git-format-patch in
149# create-pull-request, so we must not allow git-send-email to
150# add In-Reply-To and References headers again.
151PATCHES=$(echo $PDIR/*.patch)
152if [ $AUTO_CL -eq 1 ]; then
153	# Send the cover letter to every recipient, both specified as well as
154	# harvested. Then remove it from the patches list.
155	# --no-thread is redundant here (only sending a single message) and
156	# merely added for the sake of consistency.
157	eval "git send-email $GIT_TO $GIT_CC $GIT_EXTRA_CC --confirm=always --no-thread --suppress-cc=all $CL"
158	if [ $? -eq 1 ]; then
159		echo "ERROR: failed to send cover-letter with automatic recipients."
160		exit 1
161	fi
162	PATCHES=${PATCHES/"$CL"/}
163fi
164
165# Send the patch to the specified recipients and, if -c was specified, those git
166# finds in this specific patch.
167eval "git send-email $GIT_TO $GIT_EXTRA_CC --confirm=always --no-thread $GITSOBCC $PATCHES"
168if [ $? -eq 1 ]; then
169	echo "ERROR: failed to send patches."
170	exit 1
171fi
172