xref: /f-stack/dpdk/devtools/git-log-fixes.sh (revision 2bfe3f2e)
1*2bfe3f2eSlogwang#! /bin/sh -e
2*2bfe3f2eSlogwang
3*2bfe3f2eSlogwang# BSD LICENSE
4*2bfe3f2eSlogwang#
5*2bfe3f2eSlogwang# Copyright 2016 6WIND S.A.
6*2bfe3f2eSlogwang#
7*2bfe3f2eSlogwang# Redistribution and use in source and binary forms, with or without
8*2bfe3f2eSlogwang# modification, are permitted provided that the following conditions
9*2bfe3f2eSlogwang# are met:
10*2bfe3f2eSlogwang#
11*2bfe3f2eSlogwang#   * Redistributions of source code must retain the above copyright
12*2bfe3f2eSlogwang#     notice, this list of conditions and the following disclaimer.
13*2bfe3f2eSlogwang#   * Redistributions in binary form must reproduce the above copyright
14*2bfe3f2eSlogwang#     notice, this list of conditions and the following disclaimer in
15*2bfe3f2eSlogwang#     the documentation and/or other materials provided with the
16*2bfe3f2eSlogwang#     distribution.
17*2bfe3f2eSlogwang#   * Neither the name of 6WIND S.A. nor the names of its
18*2bfe3f2eSlogwang#     contributors may be used to endorse or promote products derived
19*2bfe3f2eSlogwang#     from this software without specific prior written permission.
20*2bfe3f2eSlogwang#
21*2bfe3f2eSlogwang# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22*2bfe3f2eSlogwang# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23*2bfe3f2eSlogwang# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24*2bfe3f2eSlogwang# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25*2bfe3f2eSlogwang# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26*2bfe3f2eSlogwang# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27*2bfe3f2eSlogwang# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28*2bfe3f2eSlogwang# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29*2bfe3f2eSlogwang# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30*2bfe3f2eSlogwang# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31*2bfe3f2eSlogwang# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32*2bfe3f2eSlogwang
33*2bfe3f2eSlogwangprint_usage ()
34*2bfe3f2eSlogwang{
35*2bfe3f2eSlogwang	echo "usage: $(basename $0) [-h] <git_range>"
36*2bfe3f2eSlogwang}
37*2bfe3f2eSlogwang
38*2bfe3f2eSlogwangprint_help ()
39*2bfe3f2eSlogwang{
40*2bfe3f2eSlogwang	print_usage
41*2bfe3f2eSlogwang	cat <<- END_OF_HELP
42*2bfe3f2eSlogwang
43*2bfe3f2eSlogwang	Find fixes to backport on previous versions.
44*2bfe3f2eSlogwang	It looks for the word "fix" in the headline or a tag "Fixes" or "Reverts".
45*2bfe3f2eSlogwang	The oldest bug origin is printed as well as partially fixed versions.
46*2bfe3f2eSlogwang	END_OF_HELP
47*2bfe3f2eSlogwang}
48*2bfe3f2eSlogwang
49*2bfe3f2eSlogwangusage_error () # <message>
50*2bfe3f2eSlogwang{
51*2bfe3f2eSlogwang	echo "$*" >&2
52*2bfe3f2eSlogwang	print_usage >&2
53*2bfe3f2eSlogwang	exit 1
54*2bfe3f2eSlogwang}
55*2bfe3f2eSlogwang
56*2bfe3f2eSlogwangwhile getopts h ARG ; do
57*2bfe3f2eSlogwang	case $ARG in
58*2bfe3f2eSlogwang		h ) print_help ; exit 0 ;;
59*2bfe3f2eSlogwang		? ) print_usage >&2 ; exit 1 ;;
60*2bfe3f2eSlogwang	esac
61*2bfe3f2eSlogwangdone
62*2bfe3f2eSlogwangshift $(($OPTIND - 1))
63*2bfe3f2eSlogwang[ $# -ge 1 ] || usage_error 'range argument required'
64*2bfe3f2eSlogwangrange="$*"
65*2bfe3f2eSlogwang
66*2bfe3f2eSlogwang# get major release version of a commit
67*2bfe3f2eSlogwangcommit_version () # <hash>
68*2bfe3f2eSlogwang{
69*2bfe3f2eSlogwang	# use current branch as history reference
70*2bfe3f2eSlogwang	local refbranch=$(git rev-parse --abbrev-ref HEAD)
71*2bfe3f2eSlogwang	local tag=$( (git tag -l --contains $1 --merged $refbranch 2>&- ||
72*2bfe3f2eSlogwang		# tag --merged option has been introduced in git 2.7.0
73*2bfe3f2eSlogwang		# below is a fallback in case of old git version
74*2bfe3f2eSlogwang		for t in $(git tag -l --contains $1) ; do
75*2bfe3f2eSlogwang			git branch $refbranch --contains $t |
76*2bfe3f2eSlogwang			sed "s,.\+,$t,"
77*2bfe3f2eSlogwang		done) |
78*2bfe3f2eSlogwang		head -n1)
79*2bfe3f2eSlogwang	if [ -z "$tag" ] ; then
80*2bfe3f2eSlogwang		# before -rc1 tag of release in progress
81*2bfe3f2eSlogwang		make showversion | cut -d'.' -f-2
82*2bfe3f2eSlogwang	else
83*2bfe3f2eSlogwang		echo $tag | sed 's,^v,,' | sed 's,-rc.*,,'
84*2bfe3f2eSlogwang	fi
85*2bfe3f2eSlogwang}
86*2bfe3f2eSlogwang
87*2bfe3f2eSlogwang# get bug origin hashes of a fix
88*2bfe3f2eSlogwangorigin_filter () # <hash>
89*2bfe3f2eSlogwang{
90*2bfe3f2eSlogwang	git log --format='%b' -1 $1 |
91*2bfe3f2eSlogwang	sed -n 's,^ *\([Ff]ixes\|[Rr]everts\): *\([0-9a-f]*\).*,\2,p'
92*2bfe3f2eSlogwang}
93*2bfe3f2eSlogwang
94*2bfe3f2eSlogwang# get oldest major release version of bug origins
95*2bfe3f2eSlogwangorigin_version () # <origin_hash> ...
96*2bfe3f2eSlogwang{
97*2bfe3f2eSlogwang	for origin in $* ; do
98*2bfe3f2eSlogwang		# check hash is valid
99*2bfe3f2eSlogwang		git rev-parse -q --verify $1 >&- || continue
100*2bfe3f2eSlogwang		# get version of this bug origin
101*2bfe3f2eSlogwang		local origver=$(commit_version $origin)
102*2bfe3f2eSlogwang		local roothashes="$(origin_filter $origin)"
103*2bfe3f2eSlogwang		if [ -n "$roothashes" ] ; then
104*2bfe3f2eSlogwang			# look chained fix of fix recursively
105*2bfe3f2eSlogwang			local rootver="$(origin_version $roothashes)"
106*2bfe3f2eSlogwang			[ -n "$rootver" ] || continue
107*2bfe3f2eSlogwang			echo "$rootver (partially fixed in $origver)"
108*2bfe3f2eSlogwang		else
109*2bfe3f2eSlogwang			echo "$origver"
110*2bfe3f2eSlogwang		fi
111*2bfe3f2eSlogwang	# filter the oldest origin
112*2bfe3f2eSlogwang	done | sort -uV | head -n1
113*2bfe3f2eSlogwang}
114*2bfe3f2eSlogwang
115*2bfe3f2eSlogwang# print a marker for stable tag presence
116*2bfe3f2eSlogwangstable_tag () # <hash>
117*2bfe3f2eSlogwang{
118*2bfe3f2eSlogwang	if git log --format='%b' -1 $1 | grep -qi '^Cc: *[email protected]' ; then
119*2bfe3f2eSlogwang		echo 'S'
120*2bfe3f2eSlogwang	else
121*2bfe3f2eSlogwang		echo '-'
122*2bfe3f2eSlogwang	fi
123*2bfe3f2eSlogwang}
124*2bfe3f2eSlogwang
125*2bfe3f2eSlogwanggit log --oneline --reverse $range |
126*2bfe3f2eSlogwangwhile read id headline ; do
127*2bfe3f2eSlogwang	origins=$(origin_filter $id)
128*2bfe3f2eSlogwang	stable=$(stable_tag $id)
129*2bfe3f2eSlogwang	[ "$stable" = "S" ] || [ -n "$origins" ] || echo "$headline" | grep -q fix || continue
130*2bfe3f2eSlogwang	version=$(commit_version $id)
131*2bfe3f2eSlogwang	if [ -n "$origins" ] ; then
132*2bfe3f2eSlogwang		origver="$(origin_version $origins)"
133*2bfe3f2eSlogwang		[ -n "$origver" ] || continue
134*2bfe3f2eSlogwang		# ignore fix of bug introduced in the same release
135*2bfe3f2eSlogwang		! echo "$origver" | grep -q "^$version" || continue
136*2bfe3f2eSlogwang	else
137*2bfe3f2eSlogwang		origver='N/A'
138*2bfe3f2eSlogwang	fi
139*2bfe3f2eSlogwang	printf '%s %7s %s %s (%s)\n' $version $id $stable "$headline" "$origver"
140*2bfe3f2eSlogwangdone
141