1#!/bin/sh
2
3# Usage: Run 'contrib/coverage-diff.sh <version1> <version2>' from source-root
4# after running
5#
6# make coverage-test
7# make coverage-report
8#
9# while checked out at <version2>. This script combines the *.gcov files
10# generated by the 'make' commands above with 'git diff <version1> <version2>'
11# to report new lines that are not covered by the test suite.
12
13V1=$1
14V2=$2
15
16diff_lines () {
17 perl -e '
18 my $line_num;
19 while (<>) {
20 # Hunk header? Grab the beginning in postimage.
21 if (/^@@ -\d+(?:,\d+)? \+(\d+)(?:,\d+)? @@/) {
22 $line_num = $1;
23 next;
24 }
25
26 # Have we seen a hunk? Ignore "diff --git" etc.
27 next unless defined $line_num;
28
29 # Deleted line? Ignore.
30 if (/^-/) {
31 next;
32 }
33
34 # Show only the line number of added lines.
35 if (/^\+/) {
36 print "$line_num\n";
37 }
38 # Either common context or added line appear in
39 # the postimage. Count it.
40 $line_num++;
41 }
42 '
43}
44
45files=$(git diff --name-only "$V1" "$V2" -- \*.c)
46
47# create empty file
48>coverage-data.txt
49
50for file in $files
51do
52 git diff "$V1" "$V2" -- "$file" |
53 diff_lines |
54 sort >new_lines.txt
55
56 if ! test -s new_lines.txt
57 then
58 continue
59 fi
60
61 hash_file=$(echo $file | sed "s/\//\#/")
62
63 if ! test -s "$hash_file.gcov"
64 then
65 continue
66 fi
67
68 sed -ne '/#####:/{
69 s/ #####://
70 s/:.*//
71 s/ //g
72 p
73 }' "$hash_file.gcov" |
74 sort >uncovered_lines.txt
75
76 comm -12 uncovered_lines.txt new_lines.txt |
77 sed -e 's/$/\)/' |
78 sed -e 's/^/ /' >uncovered_new_lines.txt
79
80 grep -q '[^[:space:]]' <uncovered_new_lines.txt &&
81 echo $file >>coverage-data.txt &&
82 git blame -s "$V2" -- "$file" |
83 sed 's/\t//g' |
84 grep -f uncovered_new_lines.txt >>coverage-data.txt &&
85 echo >>coverage-data.txt
86
87 rm -f new_lines.txt uncovered_lines.txt uncovered_new_lines.txt
88done
89
90cat coverage-data.txt
91
92echo "Commits introducing uncovered code:"
93
94commit_list=$(cat coverage-data.txt |
95 grep -E '^[0-9a-f]{7,} ' |
96 awk '{print $1;}' |
97 sort |
98 uniq)
99
100(
101 for commit in $commit_list
102 do
103 git log --no-decorate --pretty=format:'%an %h: %s' -1 $commit
104 echo
105 done
106) | sort
107
108rm coverage-data.txt