Blob Blame History Raw
#!/bin/bash
#############################################################################
# Copyright (c) 2009 Novell, Inc.
# All Rights Reserved.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of version 2 of the GNU General Public License as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.   See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, contact Novell, Inc.
#
# To contact Novell about this file by physical or electronic mail,
# you may find current contact information at www.novell.com
#############################################################################
#
# Apply the patch series to a linux git repository. Note that the generated
# branch will differ each time, it is only meant as an alternative to quilt
# annotate and friends, it should not be pushed anywhere.

usage()
{
	echo "Usage: $0 -g <mainline kernel git> [-b <branch>] [-v] [-f] [-s|-n] [-a] [-X]"
	echo "branch is $branch by default"
}

die()
{
	echo "$@" >&2
	exit 1
}

# perform a git command in linux-2.6 git tree
l_git()
{
	(cd "$git"; command git "$@")
}

. scripts/wd-functions.sh
branch="suse/$(get_branch_name)"
if test "$branch" = "suse/"; then
	branch="suse/unknown"
fi
git=
verbose=false
force=false
skip=true
use_applied=false
skip_xen=false
last_patch=
. rpm/config.sh
# sles10 doesn't use pristine stable patches
case "$IBS_PROJECT" in
SUSE:SLE-10*)
	skip=false
esac
options=$(getopt -n "$0" -o ab:g:vsnS:Xfh --long branch:,git:,verbose,use-applied,force,skip,no-skip,no-xen,symbols:,help -- "$@")
if test $? != 0; then
	usage >&2
	exit 1
fi
eval set -- "$options"
while test $# -gt 0; do
	case "$1" in
	-b | --branch)
		branch=$2
		shift 2
		;;
	-g | --git)
		git=$2
		shift 2
		;;
	-v | --verbose)
		verbose=true
		shift
		;;
	-f | --force)
		force=true
		shift
		;;
	-a | --use-applied)
		use_applied=true
		shift
		;;
	-s | --skip)
		skip=true
		shift
		;;
	-n | --no-skip)
		skip=false
		shift
		;;
	-X | --no-xen)
		skip_xen=true
		shift
		;;
	-S | --symbols)
		EXTRA_SYMBOLS=$2
		shift 2
		;;
	-h | --help)
		usage
		exit 0
		;;
	--)
		shift
		break
		;;
	esac
done
if test $# -gt 0; then
	echo "$0: too many arguments"
	usage >&2
	exit 1
fi
if test -z "$git"; then
	usage >&2
	exit 1
fi
if [ -s extra-symbols ] ; then
	EXTRA_SYMBOLS="$EXTRA_SYMBOLS $(cat extra-symbols)"
fi

if ! $skip; then
	base="$SRCVERSION"
else
	if test -x rpm/compute-PATCHVERSION.sh; then
		base=$("$_")
	else
		base=$(scripts/compute-PATCHVERSION.sh)
	fi
fi
if $use_applied ; then
	cur_branch=$(l_git branch | sed -n 's/^\* //p')
	if test "$cur_branch" != "$branch"; then
		echo "branch is $cur_branch, cannot use current branch"
		use_applied=false
	fi
fi
if $use_applied ; then
	last_patch=$(l_git show | sed -n 's/^ *Patch-name: //p')
	if $force ; then
		l_git reset --hard
	fi
else
	args=(--git "$git")
	$verbose && args[${#args[@]}]="--verbose"
	$force   && args[${#args[@]}]="--force"
	base_id=$("${0%/*}"/mainline-commit "${args[@]}" "$base") || exit
	echo "base is $base (${base_id:0:7})"

	# workaround "cannot delete branch which you are currently on" errors
	l_git checkout -q HEAD^0 || exit
	l_git branch -f "$branch" "$base_id" || exit
	l_git checkout "$branch" || exit
fi
tmp=$(mktemp -d /dev/shm/series2git.XXXXXXXX) || exit
trap 'rm -rf "$tmp"' EXIT

ex_hdr()
{
	local header=$1
	shift
	sed -n "s/^$header:  *//p; T; q" "$@"
}

apply_patch()
{
	local patch=$1

	rm -rf "$tmp/backup"
	mkdir "$tmp/backup"
	patch -d "$git" -s --backup --prefix="$tmp/backup/" -p1 --force -i "$PWD/$patch" || return
	l_git add $(find "$tmp/backup" -type f -printf '%P\n')

	local from=$(ex_hdr From "$patch")
	if test -z "$from"; then
		from=$(ex_hdr Author "$patch")
	fi
	if test -z "$from"; then
		from="Unknown Hero <unknown@example.com>"
	fi
	case "$from" in
	*"<"*@*">")
		GIT_AUTHOR_NAME=${from% <*}
		GIT_AUTHOR_EMAIL="<${from##*<}"
		;;
	*@*)
		GIT_AUTHOR_NAME=${from%%@*}
		GIT_AUTHOR_NAME=${GIT_AUTHOR_NAME#<}
		GIT_AUTHOR_EMAIL=$from
		;;
	*)
		GIT_AUTHOR_NAME=$from
		GIT_AUTHOR_EMAIL=
		;;
	esac
	local subject=$(ex_hdr Subject "$patch" | sed -es'/\[[^]]*\] //')
	GIT_AUTHOR_DATE=$(ex_hdr Date "$patch")
	GIT_AUTHOR_DATE=$(ex_hdr Date "$patch" \
	    | perl -p -e 's/(\d\d:\d\d:\d\d) (\d{4})/$2 $1/;s/:$//')
	if test -n "$GIT_AUTHOR_DATE"; then
		GIT_AUTHOR_DATE=$(date -R -d"$GIT_AUTHOR_DATE" 2>/dev/null)
	fi
	export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_AUTHOR_DATE
	(
		echo "$subject"
		echo
		sed -r '/^(Subject|From|Date):/d; /^(---$|--- |diff |Index:)/ Q' "$patch"
		echo
		echo "Patch-name: $patch"
	) | git stripspace | l_git commit -n -q -F -
}

scripts/guards $EXTRA_SYMBOLS < series.conf | while read patch; do
	case "$patch" in
	patches.kernel.org/patch-2.6.*.*-rc*)
		;;
	patches.kernel.org/*)
		if $skip; then
			echo "skipping $patch"
			continue
		fi
		;;
	patches.xen/*)
		if $skip_xen; then
			echo "skipping remaining Xen patches"
			break
		fi
		;;
	esac
	if test -n "$last_patch"; then
	    if test "$patch" != "$last_patch" ; then
		echo "skipping $patch"
		continue
	    fi
	    echo "skipping $patch"
	    last_patch=
	    continue
	fi
	if $verbose; then
		echo "[ $patch ]"
	fi
	apply_patch "$patch" || die "*** $patch failed ***"
	if ! $verbose; then
		echo -n "."
	fi
done
echo
l_git checkout -f