xref: /f-stack/dpdk/devtools/git-log-fixes.sh (revision 2d9fd380)
12bfe3f2eSlogwang#! /bin/sh -e
2d30ea906Sjfb8856606# SPDX-License-Identifier: BSD-3-Clause
32bfe3f2eSlogwang# Copyright 2016 6WIND S.A.
42bfe3f2eSlogwang
52bfe3f2eSlogwangprint_usage ()
62bfe3f2eSlogwang{
72bfe3f2eSlogwang	echo "usage: $(basename $0) [-h] <git_range>"
82bfe3f2eSlogwang}
92bfe3f2eSlogwang
102bfe3f2eSlogwangprint_help ()
112bfe3f2eSlogwang{
122bfe3f2eSlogwang	print_usage
132bfe3f2eSlogwang	cat <<- END_OF_HELP
142bfe3f2eSlogwang
152bfe3f2eSlogwang	Find fixes to backport on previous versions.
162bfe3f2eSlogwang	It looks for the word "fix" in the headline or a tag "Fixes" or "Reverts".
172bfe3f2eSlogwang	The oldest bug origin is printed as well as partially fixed versions.
182bfe3f2eSlogwang	END_OF_HELP
192bfe3f2eSlogwang}
202bfe3f2eSlogwang
212bfe3f2eSlogwangusage_error () # <message>
222bfe3f2eSlogwang{
232bfe3f2eSlogwang	echo "$*" >&2
242bfe3f2eSlogwang	print_usage >&2
252bfe3f2eSlogwang	exit 1
262bfe3f2eSlogwang}
272bfe3f2eSlogwang
282bfe3f2eSlogwangwhile getopts h ARG ; do
292bfe3f2eSlogwang	case $ARG in
302bfe3f2eSlogwang		h ) print_help ; exit 0 ;;
312bfe3f2eSlogwang		? ) print_usage >&2 ; exit 1 ;;
322bfe3f2eSlogwang	esac
332bfe3f2eSlogwangdone
342bfe3f2eSlogwangshift $(($OPTIND - 1))
352bfe3f2eSlogwang[ $# -ge 1 ] || usage_error 'range argument required'
362bfe3f2eSlogwangrange="$*"
372bfe3f2eSlogwang
382bfe3f2eSlogwang# get major release version of a commit
392bfe3f2eSlogwangcommit_version () # <hash>
402bfe3f2eSlogwang{
412bfe3f2eSlogwang	# use current branch as history reference
422bfe3f2eSlogwang	local refbranch=$(git rev-parse --abbrev-ref HEAD)
432bfe3f2eSlogwang	local tag=$( (git tag -l --contains $1 --merged $refbranch 2>&- ||
442bfe3f2eSlogwang		# tag --merged option has been introduced in git 2.7.0
452bfe3f2eSlogwang		# below is a fallback in case of old git version
462bfe3f2eSlogwang		for t in $(git tag -l --contains $1) ; do
472bfe3f2eSlogwang			git branch $refbranch --contains $t |
482bfe3f2eSlogwang			sed "s,.\+,$t,"
492bfe3f2eSlogwang		done) |
502bfe3f2eSlogwang		head -n1)
512bfe3f2eSlogwang	if [ -z "$tag" ] ; then
522bfe3f2eSlogwang		# before -rc1 tag of release in progress
53*2d9fd380Sjfb8856606		cat VERSION | cut -d'.' -f-2
542bfe3f2eSlogwang	else
552bfe3f2eSlogwang		echo $tag | sed 's,^v,,' | sed 's,-rc.*,,'
562bfe3f2eSlogwang	fi
572bfe3f2eSlogwang}
582bfe3f2eSlogwang
592bfe3f2eSlogwang# get bug origin hashes of a fix
602bfe3f2eSlogwangorigin_filter () # <hash>
612bfe3f2eSlogwang{
622bfe3f2eSlogwang	git log --format='%b' -1 $1 |
632bfe3f2eSlogwang	sed -n 's,^ *\([Ff]ixes\|[Rr]everts\): *\([0-9a-f]*\).*,\2,p'
642bfe3f2eSlogwang}
652bfe3f2eSlogwang
662bfe3f2eSlogwang# get oldest major release version of bug origins
672bfe3f2eSlogwangorigin_version () # <origin_hash> ...
682bfe3f2eSlogwang{
692bfe3f2eSlogwang	for origin in $* ; do
702bfe3f2eSlogwang		# check hash is valid
712bfe3f2eSlogwang		git rev-parse -q --verify $1 >&- || continue
722bfe3f2eSlogwang		# get version of this bug origin
732bfe3f2eSlogwang		local origver=$(commit_version $origin)
742bfe3f2eSlogwang		local roothashes="$(origin_filter $origin)"
752bfe3f2eSlogwang		if [ -n "$roothashes" ] ; then
762bfe3f2eSlogwang			# look chained fix of fix recursively
772bfe3f2eSlogwang			local rootver="$(origin_version $roothashes)"
782bfe3f2eSlogwang			[ -n "$rootver" ] || continue
792bfe3f2eSlogwang			echo "$rootver (partially fixed in $origver)"
802bfe3f2eSlogwang		else
812bfe3f2eSlogwang			echo "$origver"
822bfe3f2eSlogwang		fi
832bfe3f2eSlogwang	# filter the oldest origin
842bfe3f2eSlogwang	done | sort -uV | head -n1
852bfe3f2eSlogwang}
862bfe3f2eSlogwang
872bfe3f2eSlogwang# print a marker for stable tag presence
882bfe3f2eSlogwangstable_tag () # <hash>
892bfe3f2eSlogwang{
902bfe3f2eSlogwang	if git log --format='%b' -1 $1 | grep -qi '^Cc: *[email protected]' ; then
912bfe3f2eSlogwang		echo 'S'
922bfe3f2eSlogwang	else
932bfe3f2eSlogwang		echo '-'
942bfe3f2eSlogwang	fi
952bfe3f2eSlogwang}
962bfe3f2eSlogwang
974418919fSjohnjiang# print a marker for fixes tag presence
984418919fSjohnjiangfixes_tag () # <hash>
994418919fSjohnjiang{
1004418919fSjohnjiang        if git log --format='%b' -1 $1 | grep -qi '^Fixes: *' ; then
1014418919fSjohnjiang                echo 'F'
1024418919fSjohnjiang        else
1034418919fSjohnjiang                echo '-'
1044418919fSjohnjiang        fi
1054418919fSjohnjiang}
1064418919fSjohnjiang
1072bfe3f2eSlogwanggit log --oneline --reverse $range |
1082bfe3f2eSlogwangwhile read id headline ; do
1092bfe3f2eSlogwang	origins=$(origin_filter $id)
1102bfe3f2eSlogwang	stable=$(stable_tag $id)
1114418919fSjohnjiang	fixes=$(fixes_tag $id)
1124418919fSjohnjiang	[ "$stable" = "S" ] || [ "$fixes" = "F" ] || [ -n "$origins" ] || \
1134418919fSjohnjiang		echo "$headline" | grep -q fix || continue
1142bfe3f2eSlogwang	version=$(commit_version $id)
1152bfe3f2eSlogwang	if [ -n "$origins" ] ; then
1162bfe3f2eSlogwang		origver="$(origin_version $origins)"
1172bfe3f2eSlogwang		[ -n "$origver" ] || continue
1182bfe3f2eSlogwang		# ignore fix of bug introduced in the same release
1192bfe3f2eSlogwang		! echo "$origver" | grep -q "^$version" || continue
1202bfe3f2eSlogwang	else
1212bfe3f2eSlogwang		origver='N/A'
1222bfe3f2eSlogwang	fi
1234418919fSjohnjiang	printf '%s %7s %s %s %s (%s)\n' $version $id $stable $fixes "$headline" "$origver"
1242bfe3f2eSlogwangdone
125