aboutsummaryrefslogtreecommitdiff
path: root/tools/coverage-diff.sh
diff options
context:
space:
mode:
authorPatrick Steinhardt <ps@pks.im>2026-03-19 06:33:22 +0100
committerJunio C Hamano <gitster@pobox.com>2026-03-19 06:40:08 -0700
commitfe309664ea804d17812bab22927756dc35e5e955 (patch)
tree30a5c0fa7a0a35ce604a3fc88c85e6800b28a8aa /tools/coverage-diff.sh
parent8ca1b4472ce97ae1d120608f9f02a86fa33d4187 (diff)
downloadgit-fe309664ea804d17812bab22927756dc35e5e955.tar.xz
contrib: move "coverage-diff.sh" script into "tools/"
The "coverage-diff.sh" script can be used to get information about test coverage fro the Git codebase. It is thus rather specific to our build and test infrastructure and part of the developer-facing tooling. The fact that this script is part of "contrib/" is thus rather misleading and a historic wart. Promote the tool into the new "tools/" directory. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'tools/coverage-diff.sh')
-rwxr-xr-xtools/coverage-diff.sh103
1 files changed, 103 insertions, 0 deletions
diff --git a/tools/coverage-diff.sh b/tools/coverage-diff.sh
new file mode 100755
index 0000000000..6ce9603568
--- /dev/null
+++ b/tools/coverage-diff.sh
@@ -0,0 +1,103 @@
+#!/bin/sh
+
+# Usage: Run 'contrib/coverage-diff.sh <version1> <version2>' from source-root
+# after running
+#
+# make coverage-test
+# make coverage-report
+#
+# while checked out at <version2>. This script combines the *.gcov files
+# generated by the 'make' commands above with 'git diff <version1> <version2>'
+# to report new lines that are not covered by the test suite.
+
+V1=$1
+V2=$2
+
+diff_lines () {
+ perl -e '
+ my $line_num;
+ while (<>) {
+ # Hunk header? Grab the beginning in postimage.
+ if (/^@@ -\d+(?:,\d+)? \+(\d+)(?:,\d+)? @@/) {
+ $line_num = $1;
+ next;
+ }
+
+ # Have we seen a hunk? Ignore "diff --git" etc.
+ next unless defined $line_num;
+
+ # Deleted line? Ignore.
+ if (/^-/) {
+ next;
+ }
+
+ # Show only the line number of added lines.
+ if (/^\+/) {
+ print "$line_num\n";
+ }
+ # Either common context or added line appear in
+ # the postimage. Count it.
+ $line_num++;
+ }
+ '
+}
+
+files=$(git diff --name-only "$V1" "$V2" -- \*.c)
+
+# create empty file
+>coverage-data.txt
+
+for file in $files
+do
+ git diff "$V1" "$V2" -- "$file" |
+ diff_lines |
+ sort >new_lines.txt
+
+ if ! test -s new_lines.txt
+ then
+ continue
+ fi
+
+ hash_file=$(echo $file | sed "s/\//\#/")
+
+ if ! test -s "$hash_file.gcov"
+ then
+ continue
+ fi
+
+ sed -ne '/#####:/{
+ s/ #####://
+ s/:.*//
+ s/ //g
+ p
+ }' "$hash_file.gcov" |
+ sort >uncovered_lines.txt
+
+ comm -12 uncovered_lines.txt new_lines.txt |
+ sed -e 's/$/\)/' -e 's/^/ /' >uncovered_new_lines.txt
+
+ grep -q '[^[:space:]]' <uncovered_new_lines.txt &&
+ echo $file >>coverage-data.txt &&
+ git blame -s "$V2" -- "$file" |
+ sed 's/\t//g' |
+ grep -f uncovered_new_lines.txt >>coverage-data.txt &&
+ echo >>coverage-data.txt
+
+ rm -f new_lines.txt uncovered_lines.txt uncovered_new_lines.txt
+done
+
+cat coverage-data.txt
+
+echo "Commits introducing uncovered code:"
+
+commit_list=$(awk '/^[0-9a-f]{7,}/ { print $1 }' coverage-data.txt | sort -u)
+
+(
+ for commit in $commit_list
+ do
+ git log --no-decorate --pretty=format:'%an %h: %s' -1 $commit
+ echo
+ done
+) | sort
+
+rm coverage-data.txt