From 67b23c7bde37d4b4e49619d2a88afabec501bf72 Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Mon, 8 Jul 2024 08:30:49 -0400 Subject: [PATCH] Add a check-format-commit.sh script Add a wrapper script to check-format.pl, which is capable of analyzing commits rather than just a file. for a provided commit this script: 1) runs check-format.pl on the files changed in the provided commit 2) filters the output of check-format.pl, only producing lines that match ranges of changed lines in those files Reviewed-by: Tomas Mraz Reviewed-by: Tom Cosgrove (Merged from https://github.com/openssl/openssl/pull/24806) (cherry picked from commit acae12eb781658479b4fb3fee6334fd14a3c2739) --- util/check-format-commit.sh | 171 ++++++++++++++++++++++++++++++++++++ 1 file changed, 171 insertions(+) create mode 100755 util/check-format-commit.sh diff --git a/util/check-format-commit.sh b/util/check-format-commit.sh new file mode 100755 index 00000000000..7e712dc48cf --- /dev/null +++ b/util/check-format-commit.sh @@ -0,0 +1,171 @@ +#!/bin/bash +# Copyright 2020-2024 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the Apache License 2.0 (the "License"). +# You may not use this file except in compliance with the License. +# You can obtain a copy in the file LICENSE in the source distribution +# or at https://www.openssl.org/source/license.html +# +# This script is a wrapper around check-format.pl. It accepts a commit sha +# value as input, and uses it to identify the files and ranges that were +# changed in that commit, filtering check-format.pl output only to lines that +# fall into the commits change ranges. +# + + +# List of Regexes to use when running check-format.pl. +# Style checks don't apply to any of these +EXCLUDED_FILE_REGEX=("\.pod" \ + "\.pl" \ + "\.pm" \ + "\.t" \ + "\.yml" \ + "\.sh") + +# Exit code for the script +EXIT_CODE=0 + +# Global vars + +# TEMPDIR is used to hold any files this script creates +# And is cleaned on EXIT with a trap function +TEMPDIR=$(mktemp -d /tmp/checkformat.XXXXXX) + +# TOPDIR always points to the root of the git tree we are working in +# used to locate the check-format.pl script +TOPDIR=$(git rev-parse --show-toplevel) + + +# cleanup handler function, returns us to the root of the git tree +# and erases our temp directory +cleanup() { + rm -rf $TEMPDIR + cd $TOPDIR +} + +trap cleanup EXIT + +# Get the canonical sha256 sum for the commit we are checking +# This lets us pass in symbolic ref names like master/etc and +# resolve them to sha256 sums easily +COMMIT=$(git rev-parse $1) + +# Fail gracefully if git rev-parse doesn't produce a valid +# commit +if [ $? -ne 0 ] +then + echo "$1 is not a valid revision" + exit 1 +fi + +# Create a iteratable list of files to check for a +# given commit. It produces output of the format +# , +touch $TEMPDIR/ranges.txt +git show $COMMIT | awk -v mycmt=$COMMIT ' + BEGIN {myfile=""} + /+{3}/ { + gsub(/b\//,"",$2); + myfile=$2 + } + /@@/ { + gsub(/+/,"",$3); + printf mycmt " " myfile " " $3 "\n" + }' >> $TEMPDIR/ranges.txt || true + +# filter out anything that matches on a filter regex +for i in ${EXCLUDED_FILE_REGEX[@]} +do + touch $TEMPDIR/ranges.filter + grep -v "$i" $TEMPDIR/ranges.txt >> $TEMPDIR/ranges.filter || true + REMAINING_FILES=$(wc -l $TEMPDIR/ranges.filter | awk '{print $1}') + if [ $REMAINING_FILES -eq 0 ] + then + echo "This commit has no files that require checking" + exit 0 + fi + mv $TEMPDIR/ranges.filter $TEMPDIR/ranges.txt +done + +# check out the files from the commit level. +# For each file name in ranges, we show that file at the commit +# level we are checking, and redirect it to the same path, relative +# to $TEMPDIR/check-format. This give us the full file to run +# check-format.pl on with line numbers matching the ranges in the +# $TEMPDIR/ranges.txt file +for j in $(grep $COMMIT $TEMPDIR/ranges.txt | awk '{print $2}') +do + FDIR=$(dirname $j) + mkdir -p $TEMPDIR/check-format/$FDIR + git show $COMMIT:$j > $TEMPDIR/check-format/$j +done + +# Now for each file in $TEMPDIR/check-format run check-format.pl +# Note that we use the %P formatter in the find utilty. This strips +# off the $TEMPDIR/check-format path prefix, leaving $j with the +# path to the file relative to the root of the source dir, so that +# output from check-format.pl looks correct, relative to the root +# of the git tree. +for j in $(find $TEMPDIR/check-format -type f -printf "%P\n") +do + range_start=() + range_end=() + + # Get the ranges for this file. Create 2 arrays. range_start contains + # the start lines for valid ranges from the commit. the range_end array + # contains the corresponding end line (note, since diff output gives us + # a line count for a change, the range_end[k] entry is actually + # range_start[k]+line count + for k in $(grep $COMMIT $TEMPDIR/ranges.txt | grep $j | awk '{print $3}') + do + RANGE=$k + RSTART=$(echo $RANGE | awk -F',' '{print $1}') + RLEN=$(echo $RANGE | awk -F',' '{print $2}') + let REND=$RSTART+$RLEN + range_start+=($RSTART) + range_end+=($REND) + done + + # Go to our checked out tree + cd $TEMPDIR/check-format + + # Actually run check-format.pl on the file, capturing the output + # in a temporary file. Note the format of check-patch.pl output is + # ::: + $TOPDIR/util/check-format.pl $j > $TEMPDIR/format-results.txt + + # Now we filter the check-format.pl output based on the changed lines + # captured in the range_start/end arrays + let maxidx=${#range_start[@]}-1 + for k in $(seq 0 1 $maxidx) + do + RSTART=${range_start[$k]} + REND=${range_end[$k]} + + # field 2 of check-format.pl output is the offending line number + # Check here if any line in that output falls between any of the + # start/end ranges defined in the range_start/range_end array. + # If it does fall in that range, print the entire line to stdout + # If anything is printed, have awk exit with a non-zero exit code + awk -v rstart=$RSTART -v rend=$REND -F':' ' + BEGIN {rc=0} + /:/ { + if (($2 >= rstart) && ($2 <= rend)) { + print $0; + rc=1 + } + } + END {exit rc;} + ' $TEMPDIR/format-results.txt + + # If awk exited with a non-zero code, this script will also exit + # with a non-zero code + if [ $? -ne 0 ] + then + EXIT_CODE=1 + fi + done +done + +# Exit with the recorded exit code above +exit $EXIT_CODE -- 2.47.2