Justin Vreeland 794355
#!/bin/bash
Justin Vreeland 794355
#
Justin Vreeland 794355
# This script takes the merged config files and processes them through oldconfig
Justin Vreeland 794355
# and listnewconfig
Justin Vreeland 794355
#
Justin Vreeland 794355
# Globally disable suggestion of appending '|| exit' or '|| return' to cd/pushd/popd commands
Justin Vreeland 794355
# shellcheck disable=SC2164
Justin Vreeland 794355
Justin Vreeland 794355
usage()
Justin Vreeland 794355
{
Justin Vreeland 794355
	# alphabetical order please
Justin Vreeland 794355
	echo "process_configs.sh [ options ] package_name kernel_version"
Justin Vreeland 794355
	echo "     -a: report all errors, equivalent to [-c -n -w -i]"
Justin Vreeland 794355
	echo "     -c: error on mismatched config options"
Justin Vreeland 794355
	echo "     -i: continue on error"
Justin Vreeland 794355
	echo "     -n: error on unset config options"
Justin Vreeland 794355
	echo "     -t: test run, do not overwrite original config"
Justin Vreeland 794355
	echo "     -w: error on misconfigured config options"
Justin Vreeland 794355
	echo "     -z: commit new configs to pending directory"
Justin Vreeland 794355
	echo ""
Justin Vreeland 794355
	echo "     A special CONFIG file tag, process_configs_known_broken can be added as a"
Justin Vreeland 794355
	echo "     comment to any CONFIG file.  This tag indicates that there is no way to "
Justin Vreeland 794355
	echo "     fix a CONFIG's entry.  This tag should only be used in extreme cases"
Justin Vreeland 794355
	echo "     and is not to be used as a workaround to solve CONFIG problems."
Justin Vreeland 794355
	exit 1
Justin Vreeland 794355
}
Justin Vreeland 794355
Justin Vreeland 794355
die()
Justin Vreeland 794355
{
Justin Vreeland 794355
	echo "$1"
Justin Vreeland 794355
	exit 1
Justin Vreeland 794355
}
Justin Vreeland 794355
Justin Vreeland 794355
get_cross_compile()
Justin Vreeland 794355
{
Justin Vreeland 794355
	arch=$1
Justin Vreeland 794355
	if [[ "$CC_IS_CLANG" -eq 1 ]]; then
Justin Vreeland 794355
		echo "$arch"
Justin Vreeland 794355
	else
Justin Vreeland 794355
		echo "scripts/dummy-tools/"
Justin Vreeland 794355
	fi
Justin Vreeland 794355
}
Justin Vreeland 794355
Justin Vreeland 794355
# stupid function to find top of tree to do kernel make configs
Justin Vreeland 794355
switch_to_toplevel()
Justin Vreeland 794355
{
Justin Vreeland 794355
	path="$(pwd)"
Justin Vreeland 794355
	while test -n "$path"
Justin Vreeland 794355
	do
Justin Vreeland 794355
		test -e "$path"/MAINTAINERS && \
Justin Vreeland 794355
			test -d "$path"/drivers && \
Justin Vreeland 794355
			break
Justin Vreeland 794355
Justin Vreeland 794355
		path=$(dirname "$path")
Justin Vreeland 794355
	done
Justin Vreeland 794355
Justin Vreeland 794355
	test -n "$path"  || die "Can't find toplevel"
Justin Vreeland 794355
	echo "$path"
Justin Vreeland 794355
}
Justin Vreeland 794355
Justin Vreeland 794355
checkoptions()
Justin Vreeland 794355
{
Justin Vreeland 794355
	/usr/bin/awk '
Justin Vreeland 794355
Justin Vreeland 794355
		/is not set/ {
Justin Vreeland 794355
			split ($0, a, "#");
Justin Vreeland 794355
			split(a[2], b);
Justin Vreeland 794355
			if (NR==FNR) {
Justin Vreeland 794355
				configs[b[1]]="is not set";
Justin Vreeland 794355
			} else {
Justin Vreeland 794355
				if (configs[b[1]] != "" && configs[b[1]] != "is not set")
Justin Vreeland 794355
					 print "Found # "b[1] " is not set, after generation, had " b[1] " " configs[b[1]] " in Source tree";
Justin Vreeland 794355
			}
Justin Vreeland 794355
		}
Justin Vreeland 794355
Justin Vreeland 794355
		/=/     {
Justin Vreeland 794355
			split ($0, a, "=");
Justin Vreeland 794355
			if (NR==FNR) {
Justin Vreeland 794355
				configs[a[1]]=a[2];
Justin Vreeland 794355
			} else {
Justin Vreeland 794355
				if (configs[a[1]] != "" && configs[a[1]] != a[2])
Justin Vreeland 794355
					 print "Found "a[1]"="a[2]" after generation, had " a[1]"="configs[a[1]]" in Source tree";
Justin Vreeland 794355
			}
Justin Vreeland 794355
		}
Justin Vreeland 794355
	' "$1" "$2" > .mismatches
Justin Vreeland 794355
Justin Vreeland 794355
	checkoptions_error=false
Justin Vreeland 794355
	if test -s .mismatches
Justin Vreeland 794355
	then
Justin Vreeland 794355
		while read -r LINE
Justin Vreeland 794355
		do
Justin Vreeland 794355
			if find ./ -name "$(echo "$LINE" | awk -F "=" ' { print $1 } ' | awk ' { print $2 }')" -print0 | xargs -0 grep ^ | grep -q "process_configs_known_broken"; then
Justin Vreeland 794355
				# This is a known broken config.
Justin Vreeland 794355
				# See script help warning.
Justin Vreeland 794355
				checkoptions_error=false
Justin Vreeland 794355
			else
Justin Vreeland 794355
				checkoptions_error=true
Justin Vreeland 794355
				break
Justin Vreeland 794355
			fi
Justin Vreeland 794355
		done < .mismatches
Justin Vreeland 794355
Justin Vreeland 794355
		! $checkoptions_error && return
Justin Vreeland 794355
Justin Vreeland 794355
		echo "Error: Mismatches found in configuration files"
Justin Vreeland 794355
		cat .mismatches
Justin Vreeland 794355
		RETURNCODE=1
Justin Vreeland 794355
		[ "$CONTINUEONERROR" ] || exit 1
Justin Vreeland 794355
	fi
Justin Vreeland 794355
}
Justin Vreeland 794355
Justin Vreeland 794355
parsenewconfigs()
Justin Vreeland 794355
{
Justin Vreeland 794355
	tmpdir=$(mktemp -d)
Justin Vreeland 794355
Justin Vreeland 794355
	# This awk script reads the output of make listnewconfig
Justin Vreeland 794355
	# and puts it into CONFIG_FOO files. Using the output of
Justin Vreeland 794355
	# listnewconfig is much easier to ensure we get the default
Justin Vreeland 794355
	# output.
Justin Vreeland 794355
        /usr/bin/awk -v BASE="$tmpdir" '
Justin Vreeland 794355
                /is not set/ {
Justin Vreeland 794355
                        split ($0, a, "#");
Justin Vreeland 794355
                        split(a[2], b);
Justin Vreeland 794355
                        OUT_FILE=BASE"/"b[1];
Justin Vreeland 794355
                        print $0 >> OUT_FILE;
Justin Vreeland 794355
                }
Justin Vreeland 794355
Justin Vreeland 794355
                /=/     {
Justin Vreeland 794355
                        split ($0, a, "=");
Justin Vreeland 794355
                        OUT_FILE=BASE"/"a[1];
Justin Vreeland 794355
                        if (a[2] == "n")
Justin Vreeland 794355
                                print "# " a[1] " is not set" >> OUT_FILE;
Justin Vreeland 794355
                        else
Justin Vreeland 794355
                                print $0 >> OUT_FILE;
Justin Vreeland 794355
                }
Justin Vreeland 794355
Justin Vreeland 794355
        ' .newoptions
Justin Vreeland 794355
Justin Vreeland 794355
	# This awk script parses the output of helpnewconfig.
Justin Vreeland 794355
	# Each option is separated between ----- markers
Justin Vreeland 794355
	# The goal is to put all the help text as a comment in
Justin Vreeland 794355
	# each CONFIG_FOO file. Because of how awk works
Justin Vreeland 794355
	# there's a lot of moving files around and catting to
Justin Vreeland 794355
	# get what we need.
Justin Vreeland 794355
        /usr/bin/awk -v BASE="$tmpdir" '
Justin Vreeland 794355
                BEGIN { inpatch=0;
Justin Vreeland 794355
			outfile="none";
Justin Vreeland 794355
                        symbol="none"; }
Justin Vreeland 794355
                /^Symbol: .*$/ {
Justin Vreeland 794355
                        split($0, a, " ");
Justin Vreeland 794355
                        symbol="CONFIG_"a[2];
Justin Vreeland 794355
                        outfile=BASE "/fake_"symbol
Justin Vreeland 794355
                }
Justin Vreeland 794355
                /-----/ {
Justin Vreeland 794355
			if (inpatch == 0) {
Justin Vreeland 794355
				inpatch = 1;
Justin Vreeland 794355
			}
Justin Vreeland 794355
                        else {
Justin Vreeland 794355
                                if (symbol != "none") {
Justin Vreeland 794355
                                    system("cat " outfile " " BASE "/" symbol " > " BASE "/tmpf");
Justin Vreeland 794355
                                    system("mv " BASE "/tmpf " BASE "/" symbol);
Justin Vreeland 794355
                                    symbol="none"
Justin Vreeland 794355
				}
Justin Vreeland 794355
                                outfile="none"
Justin Vreeland 794355
				inpatch = 0;
Justin Vreeland 794355
                        }
Justin Vreeland 794355
                }
Justin Vreeland 794355
                !/-----/ {
Justin Vreeland 794355
                        if (inpatch == 1 && outfile != "none") {
Justin Vreeland 794355
                                print "# "$0 >> outfile;
Justin Vreeland 794355
                        }
Justin Vreeland 794355
                }
Justin Vreeland 794355
Justin Vreeland 794355
Justin Vreeland 794355
        ' .helpnewconfig
Justin Vreeland 794355
Justin Vreeland 794355
	pushd "$tmpdir" &> /dev/null
Justin Vreeland 794355
	rm fake_*
Justin Vreeland 794355
	popd &> /dev/null
Justin Vreeland 794355
	for f in "$tmpdir"/*; do
Justin Vreeland 794355
		[[ -e "$f" ]] || break
Justin Vreeland 794355
		cp "$f" "$SCRIPT_DIR/pending$FLAVOR/generic/"
Justin Vreeland 794355
	done
Justin Vreeland 794355
Justin Vreeland 794355
	rm -rf "$tmpdir"
Justin Vreeland 794355
}
Justin Vreeland 794355
Justin Vreeland 794355
function commit_new_configs()
Justin Vreeland 794355
{
Justin Vreeland 794355
	# assume we are in $source_tree/configs, need to get to top level
Justin Vreeland 794355
	pushd "$(switch_to_toplevel)" &>/dev/null
Justin Vreeland 794355
Justin Vreeland 794355
	for cfg in "$SCRIPT_DIR/${PACKAGE_NAME}${KVERREL}${SUBARCH}"*.config
Justin Vreeland 794355
	do
Justin Vreeland 794355
		arch=$(head -1 "$cfg" | cut -b 3-)
Justin Vreeland 794355
		cfgtmp="${cfg}.tmp"
Justin Vreeland 794355
		cfgorig="${cfg}.orig"
Justin Vreeland 794355
		cat "$cfg" > "$cfgorig"
Justin Vreeland 794355
Justin Vreeland 794355
		if [ "$arch" = "EMPTY" ]
Justin Vreeland 794355
		then
Justin Vreeland 794355
			# This arch is intentionally left blank
Justin Vreeland 794355
			continue
Justin Vreeland 794355
		fi
Justin Vreeland 794355
		echo -n "Checking for new configs in $cfg ... "
Justin Vreeland 794355
Justin Vreeland 794355
		make ${MAKEOPTS} ARCH="$arch" CROSS_COMPILE=$(get_cross_compile $arch) KCONFIG_CONFIG="$cfgorig" listnewconfig >& .listnewconfig
Justin Vreeland 794355
		grep -E 'CONFIG_' .listnewconfig > .newoptions
Justin Vreeland 794355
		if test -s .newoptions
Justin Vreeland 794355
		then
Justin Vreeland 794355
			make ${MAKEOPTS} ARCH="$arch" CROSS_COMPILE=$(get_cross_compile $arch) KCONFIG_CONFIG="$cfgorig" helpnewconfig >& .helpnewconfig
Justin Vreeland 794355
			parsenewconfigs
Justin Vreeland 794355
		fi
Justin Vreeland 794355
		rm .newoptions
Justin Vreeland 794355
		echo "done"
Justin Vreeland 794355
	done
Justin Vreeland 794355
Justin Vreeland 794355
	git add "$SCRIPT_DIR/pending$FLAVOR"
Justin Vreeland 794355
	git commit -m "[redhat] AUTOMATIC: New configs"
Justin Vreeland 794355
}
Justin Vreeland 794355
Justin Vreeland 794355
function process_configs()
Justin Vreeland 794355
{
Justin Vreeland 794355
	# assume we are in $source_tree/configs, need to get to top level
Justin Vreeland 794355
	pushd "$(switch_to_toplevel)" &>/dev/null
Justin Vreeland 794355
Justin Vreeland 794355
	for cfg in "$SCRIPT_DIR/${PACKAGE_NAME}${KVERREL}${SUBARCH}"*.config
Justin Vreeland 794355
	do
Justin Vreeland 794355
		arch=$(head -1 "$cfg" | cut -b 3-)
Justin Vreeland 794355
		cfgtmp="${cfg}.tmp"
Justin Vreeland 794355
		cfgorig="${cfg}.orig"
Justin Vreeland 794355
		cat "$cfg" > "$cfgorig"
Justin Vreeland 794355
Justin Vreeland 794355
		if [ "$arch" = "EMPTY" ]
Justin Vreeland 794355
		then
Justin Vreeland 794355
			# This arch is intentionally left blank
Justin Vreeland 794355
			continue
Justin Vreeland 794355
		fi
Justin Vreeland 794355
		echo -n "Processing $cfg ... "
Justin Vreeland 794355
Justin Vreeland 794355
		make ${MAKEOPTS} ARCH="$arch" CROSS_COMPILE=$(get_cross_compile $arch) KCONFIG_CONFIG="$cfgorig" listnewconfig >& .listnewconfig
Justin Vreeland 794355
		grep -E 'CONFIG_' .listnewconfig > .newoptions
Justin Vreeland 794355
		if test -n "$NEWOPTIONS" && test -s .newoptions
Justin Vreeland 794355
		then
Justin Vreeland 794355
			echo "Found unset config items, please set them to an appropriate value"
Justin Vreeland 794355
			cat .newoptions
Justin Vreeland 794355
			rm .newoptions
Justin Vreeland 794355
			RETURNCODE=1
Justin Vreeland 794355
			[ "$CONTINUEONERROR" ] || exit 1
Justin Vreeland 794355
		fi
Justin Vreeland 794355
		rm .newoptions
Justin Vreeland 794355
Justin Vreeland 794355
		grep -E 'config.*warning' .listnewconfig > .warnings
Justin Vreeland 794355
		if test -n "$CHECKWARNINGS" && test -s .warnings
Justin Vreeland 794355
		then
Justin Vreeland 794355
			echo "Found misconfigured config items, please set them to an appropriate value"
Justin Vreeland 794355
			cat .warnings
Justin Vreeland 794355
			rm .warnings
Justin Vreeland 794355
			RETURNCODE=1
Justin Vreeland 794355
			[ "$CONTINUEONERROR" ] || exit 1
Justin Vreeland 794355
		fi
Justin Vreeland 794355
		rm .warnings
Justin Vreeland 794355
Justin Vreeland 794355
		rm .listnewconfig
Justin Vreeland 794355
Justin Vreeland 794355
		make ${MAKEOPTS} ARCH="$arch" CROSS_COMPILE=$(get_cross_compile $arch) KCONFIG_CONFIG="$cfgorig" olddefconfig > /dev/null || exit 1
Justin Vreeland 794355
		echo "# $arch" > "$cfgtmp"
Justin Vreeland 794355
		cat "$cfgorig" >> "$cfgtmp"
Justin Vreeland 794355
		if test -n "$CHECKOPTIONS"
Justin Vreeland 794355
		then
Justin Vreeland 794355
			checkoptions "$cfg" "$cfgtmp"
Justin Vreeland 794355
		fi
Justin Vreeland 794355
		# if test run, don't overwrite original
Justin Vreeland 794355
		if test -n "$TESTRUN"
Justin Vreeland 794355
		then
Justin Vreeland 794355
			rm -f "$cfgtmp"
Justin Vreeland 794355
		else
Justin Vreeland 794355
			mv "$cfgtmp" "$cfg"
Justin Vreeland 794355
		fi
Justin Vreeland 794355
		rm -f "$cfgorig"
Justin Vreeland 794355
		echo "done"
Justin Vreeland 794355
	done
Justin Vreeland 794355
	rm "$SCRIPT_DIR"/*.config*.old
Justin Vreeland 794355
	popd > /dev/null
Justin Vreeland 794355
Justin Vreeland 794355
	echo "Processed config files are in $SCRIPT_DIR"
Justin Vreeland 794355
}
Justin Vreeland 794355
Justin Vreeland 794355
CHECKOPTIONS=""
Justin Vreeland 794355
CONTINUEONERROR=""
Justin Vreeland 794355
NEWOPTIONS=""
Justin Vreeland 794355
TESTRUN=""
Justin Vreeland 794355
CHECKWARNINGS=""
Justin Vreeland 794355
MAKEOPTS=""
Justin Vreeland 794355
CC_IS_CLANG=0
Justin Vreeland 794355
Justin Vreeland 794355
RETURNCODE=0
Justin Vreeland 794355
Justin Vreeland 794355
while [[ $# -gt 0 ]]
Justin Vreeland 794355
do
Justin Vreeland 794355
	key="$1"
Justin Vreeland 794355
	case $key in
Justin Vreeland 794355
		-a)
Justin Vreeland 794355
			CHECKOPTIONS="x"
Justin Vreeland 794355
			CONTINUEONERROR="x"
Justin Vreeland 794355
			NEWOPTIONS="x"
Justin Vreeland 794355
			CHECKWARNINGS="x"
Justin Vreeland 794355
			;;
Justin Vreeland 794355
		-c)
Justin Vreeland 794355
			CHECKOPTIONS="x"
Justin Vreeland 794355
			;;
Justin Vreeland 794355
		-h)
Justin Vreeland 794355
			usage
Justin Vreeland 794355
			;;
Justin Vreeland 794355
		-i)
Justin Vreeland 794355
			CONTINUEONERROR="x"
Justin Vreeland 794355
			;;
Justin Vreeland 794355
		-n)
Justin Vreeland 794355
			NEWOPTIONS="x"
Justin Vreeland 794355
			;;
Justin Vreeland 794355
		-t)
Justin Vreeland 794355
			TESTRUN="x"
Justin Vreeland 794355
			;;
Justin Vreeland 794355
		-w)
Justin Vreeland 794355
			CHECKWARNINGS="x"
Justin Vreeland 794355
			;;
Justin Vreeland 794355
		-z)
Justin Vreeland 794355
			COMMITNEWCONFIGS="x"
Justin Vreeland 794355
			;;
Justin Vreeland 794355
		-m)
Justin Vreeland 794355
			shift
Justin Vreeland 794355
			if [ "$1" = "CC=clang" -o "$1" = "LLVM=1" ]; then
Justin Vreeland 794355
				CC_IS_CLANG=1
Justin Vreeland 794355
			fi
Justin Vreeland 794355
			MAKEOPTS="$MAKEOPTS $1"
Justin Vreeland 794355
			;;
Justin Vreeland 794355
		*)
Justin Vreeland 794355
			break;;
Justin Vreeland 794355
	esac
Justin Vreeland 794355
	shift
Justin Vreeland 794355
done
Justin Vreeland 794355
Justin Vreeland 794355
PACKAGE_NAME="${1:-kernel}" # defines the package name used
Justin Vreeland 794355
KVERREL="$(test -n "$2" && echo "-$2" || echo "")"
Justin Vreeland 794355
SUBARCH="$(test -n "$3" && echo "-$3" || echo "")"
Justin Vreeland 794355
FLAVOR="$(test -n "$4" && echo "-$4" || echo "-common")"
Justin Vreeland 794355
SCRIPT=$(readlink -f "$0")
Justin Vreeland 794355
SCRIPT_DIR=$(dirname "$SCRIPT")
Justin Vreeland 794355
Justin Vreeland 794355
# Most RHEL options are options we want in Fedora so RHEL pending settings head
Justin Vreeland 794355
# to common/
Justin Vreeland 794355
if [ "$FLAVOR" = "-rhel" ]
Justin Vreeland 794355
then
Justin Vreeland 794355
	FLAVOR="-common"
Justin Vreeland 794355
fi
Justin Vreeland 794355
Justin Vreeland 794355
# to handle this script being a symlink
Justin Vreeland 794355
cd "$SCRIPT_DIR"
Justin Vreeland 794355
Justin Vreeland 794355
if test -n "$COMMITNEWCONFIGS"; then
Justin Vreeland 794355
	commit_new_configs
Justin Vreeland 794355
else
Justin Vreeland 794355
	process_configs
Justin Vreeland 794355
fi
Justin Vreeland 794355
Justin Vreeland 794355
exit $RETURNCODE