1#! /bin/sh -e 2# SPDX-License-Identifier: BSD-3-Clause 3# Copyright 2016 6WIND S.A. 4 5print_usage () 6{ 7 echo "usage: $(basename $0) [-h] <git_range>" 8} 9 10print_help () 11{ 12 print_usage 13 cat <<- END_OF_HELP 14 15 Find fixes to backport on previous versions. 16 It looks for the word "fix" in the headline or a tag "Fixes" or "Reverts". 17 The oldest bug origin is printed as well as partially fixed versions. 18 END_OF_HELP 19} 20 21usage_error () # <message> 22{ 23 echo "$*" >&2 24 print_usage >&2 25 exit 1 26} 27 28while getopts h ARG ; do 29 case $ARG in 30 h ) print_help ; exit 0 ;; 31 ? ) print_usage >&2 ; exit 1 ;; 32 esac 33done 34shift $(($OPTIND - 1)) 35[ $# -ge 1 ] || usage_error 'range argument required' 36range="$*" 37 38# get major release version of a commit 39commit_version () # <hash> 40{ 41 # use current branch as history reference 42 local refbranch=$(git rev-parse --abbrev-ref HEAD) 43 local tag=$( (git tag -l --contains $1 --merged $refbranch 2>&- || 44 # tag --merged option has been introduced in git 2.7.0 45 # below is a fallback in case of old git version 46 for t in $(git tag -l --contains $1) ; do 47 git branch $refbranch --contains $t | 48 sed "s,.\+,$t," 49 done) | 50 head -n1) 51 if [ -z "$tag" ] ; then 52 # before -rc1 tag of release in progress 53 cat VERSION | cut -d'.' -f-2 54 else 55 echo $tag | sed 's,^v,,' | sed 's,-rc.*,,' 56 fi 57} 58 59# get bug origin hashes of a fix 60origin_filter () # <hash> 61{ 62 git log --format='%b' -1 $1 | 63 sed -n 's,^ *\([Ff]ixes\|[Rr]everts\): *\([0-9a-f]*\).*,\2,p' 64} 65 66# get oldest major release version of bug origins 67origin_version () # <origin_hash> ... 68{ 69 for origin in $* ; do 70 # check hash is valid 71 git rev-parse -q --verify $1 >&- || continue 72 # get version of this bug origin 73 local origver=$(commit_version $origin) 74 local roothashes="$(origin_filter $origin)" 75 if [ -n "$roothashes" ] ; then 76 # look chained fix of fix recursively 77 local rootver="$(origin_version $roothashes)" 78 [ -n "$rootver" ] || continue 79 echo "$rootver (partially fixed in $origver)" 80 else 81 echo "$origver" 82 fi 83 # filter the oldest origin 84 done | sort -uV | head -n1 85} 86 87# print a marker for stable tag presence 88stable_tag () # <hash> 89{ 90 if git log --format='%b' -1 $1 | grep -qi '^Cc: *stable@dpdk.org' ; then 91 echo 'S' 92 else 93 echo '-' 94 fi 95} 96 97# print a marker for fixes tag presence 98fixes_tag () # <hash> 99{ 100 if git log --format='%b' -1 $1 | grep -qi '^Fixes: *' ; then 101 echo 'F' 102 else 103 echo '-' 104 fi 105} 106 107git log --oneline --reverse $range | 108while read id headline ; do 109 origins=$(origin_filter $id) 110 stable=$(stable_tag $id) 111 fixes=$(fixes_tag $id) 112 [ "$stable" = "S" ] || [ "$fixes" = "F" ] || [ -n "$origins" ] || \ 113 echo "$headline" | grep -q fix || continue 114 version=$(commit_version $id) 115 if [ -n "$origins" ] ; then 116 origver="$(origin_version $origins)" 117 [ -n "$origver" ] || continue 118 # ignore fix of bug introduced in the same release 119 ! echo "$origver" | grep -q "^$version" || continue 120 else 121 origver='N/A' 122 fi 123 printf '%s %7s %s %s %s (%s)\n' $version $id $stable $fixes "$headline" "$origver" 124done 125