From 7e811c0a1bb8a05ceaa51c31f128b5b05ff93cb6 Mon Sep 17 00:00:00 2001 From: "Kelly (KT) Thompson" Date: Thu, 5 Aug 2021 07:36:32 -0600 Subject: [PATCH] Switch F90 format checker to fprettify. + Update CI and git hook scripts. + Remvoe old emacs-based checker. --- .fprettify.rc | 2 + .github/PULL_REQUEST_TEMPLATE | 3 +- environment/git/f90-format.el | 78 --------- environment/git/install-hooks.sh | 2 +- environment/git/pre-commit | 4 +- environment/git/pre-commit-f90-format | 218 -------------------------- environment/git/pre-commit-fprettify | 170 ++++++++++++++++++++ src/c4/ftest/fc4_test.f90 | 18 +-- src/ds++/path.cc | 5 +- tools/check_style.sh | 145 +++++++---------- 10 files changed, 242 insertions(+), 403 deletions(-) delete mode 100644 environment/git/f90-format.el delete mode 100755 environment/git/pre-commit-f90-format create mode 100755 environment/git/pre-commit-fprettify diff --git a/.fprettify.rc b/.fprettify.rc index 920da066e1..a206bc5a51 100644 --- a/.fprettify.rc +++ b/.fprettify.rc @@ -10,3 +10,5 @@ whitespace-multdiv = true whitespace-print = true whitespace-type = true whitespace-intrinsics = true +enable-replacements = true +c-relations = true diff --git a/.github/PULL_REQUEST_TEMPLATE b/.github/PULL_REQUEST_TEMPLATE index a54d4de64d..a93bccda87 100644 --- a/.github/PULL_REQUEST_TEMPLATE +++ b/.github/PULL_REQUEST_TEMPLATE @@ -5,7 +5,6 @@ ### Purpose of Pull Request * detail 1, refs #2 (github number) -* detail 2 * [Fixes re-git issue #3](https://re-git.lanl.gov/draco/draco/-/issues/3) ### Description of changes @@ -16,7 +15,7 @@ * Reference: * [Pre-Merge Code Review](https://github.com/lanl/Draco/wiki/Style-Guide) - * [CDash Status](https://rtt.lanl.gov/cdash/index.php?project=Draco&filtercount=1&showfilters=1&field1=buildname&compare1=63&value1=-pr) + * [CDash Status](https://rtt.lanl.gov/cdash3/index.php?project=Draco&filtercount=1&showfilters=1&field1=buildname&compare1=63&value1=-pr) * Checks * [ ] Travis/Appveyor CI checks pass * [ ] Code coverage does not decrease diff --git a/environment/git/f90-format.el b/environment/git/f90-format.el deleted file mode 100644 index 1b2cd3c9d5..0000000000 --- a/environment/git/f90-format.el +++ /dev/null @@ -1,78 +0,0 @@ -; -*- Mode: emacs -*- -;-------------------------------------------------------------------------------------------------; -; File: f90-format.el -; Date: Wednesday, Nov 07, 2018, 11:11 am -; Author: Kelly Thompson -; Note: Copyright (C) 2016-2019, Triad National Security, LLC., All rights are reserved. -;-------------------------------------------------------------------------------------------------; -; If emacs is available, enforce f90 formatting (indentation, etc) rules. -;-------------------------------------------------------------------------------------------------; - -(defun collapse-blank-lines - (start end) - (interactive "r") - (replace-regexp "^\n\\{2,\\}" "\n" nil start end) -) - -; C-u 81 M-x goto-long-line -; C-e -; -; [repeat] -(defun goto-long-line (len) - "Go to the first line that is at least LEN characters long. -Use a prefix arg to provide LEN. -Plain `C-u' (no number) uses `fill-column' as LEN." - (interactive "P") - (setq len (if (consp len) fill-column (prefix-numeric-value len))) - (let ((start-line (line-number-at-pos)) - (len-found 0) - (found nil) - (inhibit-field-text-motion t)) - (while (and (not found) (not (eobp))) - (forward-line 1) - (setq found (< len (setq len-found (- (line-end-position) (point)))))) - (if found - (when (interactive-p) - (message "Line %d: %d chars" (line-number-at-pos) len-found)) - (goto-line start-line) - (message "Not found")))) - -;; (defun wrap-long-lines () -;; "Find all lines > 100 columns in the current buffer and wrap them." -;; (interactive "p") -;; (set-fill-column 100) -;; (goto-long-line) -;; foob -;; (end-of-line) -;; (f90-do-auto-fill) -;; ) - -(defun emacs-format-f90-sources () - "Format the whole buffer accourding to Draco F90 rules." - ;; For more information about f90-mode settins in Emacs: - ;; 1. M-x f90-mode - ;; 2. C-h m - (set-fill-column 100) - (turn-on-auto-fill) - (setq f90-beginning-ampersand nil) - (setq f90-associate-indent 0) - ;; (setq f90-do-indent 3) - ;; (setq f90-if-indent 3) - ;; (setq f90-type-indent 3) - ;; (setq f90-program-indent 2) - ;; (setq f90-critical-indent 2) - ;; (setq f90-continuation-indent 5) - ;; (setq f90-indented-comment-re "!") - ;; (setq f90-break-delimiters "[-+*/><=,% \t]") - ;; (setq f90-break-before-delimiters t) - ;; (setq f90-auto-keyword-case 'downcase-word) - (untabify (point-min) (point-max)) - (delete-trailing-whitespace) - (indent-region (point-min) (point-max) nil) - (collapse-blank-lines (point-min) (point-max)) - (save-buffer) -) - -;-------------------------------------------------------------------------------------------------; -; end f90-format.el -;-------------------------------------------------------------------------------------------------; diff --git a/environment/git/install-hooks.sh b/environment/git/install-hooks.sh index 05c34774f0..2db431b630 100755 --- a/environment/git/install-hooks.sh +++ b/environment/git/install-hooks.sh @@ -13,7 +13,7 @@ ########################################################### # CONFIGURATION: # select which pre-commit hooks are going to be installed -HOOKS="pre-commit pre-commit-clang-format pre-commit-flake8 pre-commit-f90-format f90-format.el " +HOOKS="pre-commit pre-commit-clang-format pre-commit-flake8 pre-commit-fprettify" HOOKS="$HOOKS pre-commit-cmake-format pre-commit-cmake-lint" TOOLS="common.sh" ########################################################### diff --git a/environment/git/pre-commit b/environment/git/pre-commit index db72d11f98..2494e2cea4 100755 --- a/environment/git/pre-commit +++ b/environment/git/pre-commit @@ -14,7 +14,7 @@ # pre-commit hooks to be executed. They should be in the same .git/hooks/ folder as this # script. Hooks should return 0 if successful and nonzero to cancel the commit. They are executed in # the order in which they are listed. -HOOKS="pre-commit-clang-format pre-commit-f90-format" +HOOKS="pre-commit-clang-format" # only run flake8 if the tool is available. [[ $(which flake8 2> /dev/null | wc -w) -gt 0 ]] && HOOKS+=" pre-commit-flake8" @@ -22,6 +22,8 @@ HOOKS="pre-commit-clang-format pre-commit-f90-format" [[ $(which cmake-format 2> /dev/null | wc -w) -gt 0 ]] && HOOKS+=" pre-commit-cmake-format" # only run cmake-lint if the tool is available. [[ $(which cmake-lint 2> /dev/null | wc -w) -gt 0 ]] && HOOKS+=" pre-commit-cmake-lint" +# only run fprettify if the tool is available. +[[ $(which fprettify 2> /dev/null | wc -w) -gt 0 ]] && HOOKS+=" pre-commit-fprettify" #--------------------------------------------------------------------------------------------------# diff --git a/environment/git/pre-commit-f90-format b/environment/git/pre-commit-f90-format deleted file mode 100755 index 58d4733d5a..0000000000 --- a/environment/git/pre-commit-f90-format +++ /dev/null @@ -1,218 +0,0 @@ -#!/bin/bash - -# git pre-commit hook that runs a f90-format stylecheck. -# Features: -# - abort commit when commit does not comply with the style guidelines - -#--------------------------------------------------------------------------------------------------# -# SETTINGS -# -# set path to f90-format binary. If f90-format is not available, then don't run this hook. Style -# issues will be caught during by the pull request process. -#--------------------------------------------------------------------------------------------------# - -# make tmp file readable only by owner -umask 0077 - -debug=off -function debugprint() -{ - if [[ "$debug" == "on" ]]; then echo "$@"; fi -} - -# Allow developers to opt-out -auto_apply=false -if [[ ${DRACO_AUTO_CLANG_FORMAT:-YES} ]]; then - case $DRACO_AUTO_CLANG_FORMAT in - NO | OFF | FALSE | no | off | false ) exit 0 ;; - YES | ON | TRUE | yes | on | true) auto_apply=true ;; - DIFF | diff) auto_apply=false ;; - esac -fi - -# remove any older patches from previous commits. Set to true or false. -DELETE_OLD_PATCHES=true - -# file types to parse. -FILE_EXTS=".f90 .F90" -#FILE_ENDINGS_INCLUDE="_f.h _f77.h _f90.h" -FILE_ENDINGS_EXCLUDE="_f.h _f77.h _f90.h" -export FILE_EXTS FILE_ENDINGS_EXCLUDE - -################################################################## -# There should be no need to change anything below this line. -# shellcheck source=environment/git/canonicalize_filename.sh -source "$(dirname -- "$0")/canonicalize_filename.sh" - -# shellcheck source=tools/common.sh -source "$(dirname -- "$0")/common.sh" - -# exit on error -# set -e - -unalias emacs 2> /dev/null -EMACS=$(which emacs 2> /dev/null) -if [[ -x "$EMACS" ]]; then - EMACSVER=$("$EMACS" --version | head -n 1 | sed -e 's/.*Emacs //') - if [[ $(version_gt "24.0.0" "${EMACSVER}") ]]; then - echo "ERROR: Your version of emacs is too old. Expecting v 24.0+. Pre-commit-hook partially" - echo " disabled (f90 indentation)" - unset EMACS - fi -else - unset EMACS -fi - -# Absolute path this script is in, thus /home/user/bin -SCRIPT="$(canonicalize_filename "$0")" -SCRIPTPATH="$(dirname -- "$SCRIPT")" - -# necessary check for initial commit -if git rev-parse --verify HEAD >/dev/null 2>&1 ; then - against=HEAD -else - # Initial commit: diff against an empty tree object - against=4b825dc642cb6eb9a060e54bf8d69288fbee4904 -fi - -if [ ! -x "$EMACS" ] ; then - printf "Error: emacs executable not found.\n" - printf " skipping f90 format check. To enable this check\n" - printf " set the correct path in %s.\n" "$(canonicalize_filename "$0")" - exit 0 -fi - -# create a random filename to store our generated patch -prefix="pre-commit-f90-format" -suffix="$(date +%s)" - -# clean up any older f90-format patches -$DELETE_OLD_PATCHES && rm -f /tmp/$prefix-*.patch.* &> /dev/null -$DELETE_OLD_PATCHES && rm -f /tmp/f90-format-* &> /dev/null - -patch=$(mktemp "/tmp/${prefix}-${suffix}.patch.XXXXXXXX") - -# create one patch containing all changes to the files -# shellcheck disable=SC2162 -git diff-index --cached --diff-filter=ACMR --name-only $against -- | while read file; -do - # only process f90 files. - if ! matches_extension "$file"; then continue; fi - - file_nameonly=$(basename "${file}") - tmpfile1=/tmp/f90-format-$file_nameonly - debugprint "cp -f $file $tmpfile1" - cp -f "${file}" "${tmpfile1}" - debugprint "$EMACS -batch ${tmpfile1} --no-site-file -q -l ${SCRIPTPATH}/f90-format.el " \ - "-f emacs-format-f90-sources" - $EMACS -batch "${tmpfile1}" --no-site-file -q -l "${SCRIPTPATH}/f90-format.el" \ - -f emacs-format-f90-sources - diff -u "${file}" "${tmpfile1}" | \ - sed -e "1s|--- |--- a/|" -e "2s|+++ ${tmpfile1}|+++ b/${file}|" >> "$patch" - debugprint "rm $tmpfile1" - rm "${tmpfile1}" - -done - -# if no patch has been generated all is ok, clean up the file stub and exit -found_issue=1 -if [ ! -s "$patch" ] ; then - printf "Files in this commit comply with the emacs-based f90-format rules.\n" - rm -f "$patch" - found_issue=0 -fi - -if [[ $found_issue == 0 ]]; then - - # Check file lengths - printf "Now, checking file lengths...\n" - - filelist=$(git diff-index --cached --diff-filter=ACMR --name-only $against --) - tmpfile2=$(mktemp /tmp/pre-commit-f90-format-line-len.XXXXXXXX) - - for file in $filelist; do - - # ignore file if we do check for file extensions and the file does not match any of the - # extensions specified in $FILE_EXTS - if ! matches_extension "$file"; then - continue; - fi - - header_printed=0 - - # reading from $file (see end of while loop) - # shellcheck disable=SC2162 - while read line; do - (( lineno++ )) - # Exceptions: - # - Long URLs - exception=$(echo "${line}" | grep -i -c http) - if [[ "${#line}" -gt 100 && "${exception}" == 0 ]]; then - if [[ "${header_printed}" == 0 ]]; then - { - echo -e "\nFile: ${file} [code line too long]\n"; - echo " line length content"; - echo -n " ------ ------ -------------------------------------------------------------" - echo "-------------------" - } >> "${tmpfile2}" - header_printed=1 - fi - printf " %-6s %-6s %s\n" "${lineno}" "${#line}" "${line}" >> "${tmpfile2}" - fi - # reset exception flag - exception=0 - done < "${file}" - done - - len_issue=$(wc -l < "${tmpfile2}") - if [[ $len_issue -gt 0 ]]; then - echo -e "\nError: Found source code lines that are longer than 100 columns!" - cat "${tmpfile2}" - echo -ne "\nPlease reformat lines listed above to fit into 100 columns and attempt your\n" - echo -e "commit again.\n" - found_issue=$len_issue - fi - - if [[ -f "${tmpfile2}" ]]; then - rm "${tmpfile2}" - fi - - if [[ $found_issue != 0 ]]; then - exit "${found_issue}" - fi -fi - -if [[ $found_issue == 0 ]]; then - exit 0 -fi - -# There are files that don't comply... - -# If user wants to automatically apply these changes, then do it, otherwise, print the diffs and -# reject the commit. -if test $auto_apply = true; then - debugprint "git apply $patch" - git apply "$patch" - printf "\nFiles in this commit were updated to comply with the f90-format rules.\n" - printf "You must check and test these changes and then stage these updates to\n" - printf "be part of your current change set and retry the commit.\n\n" - git status - printf "The following changes were applied:\n\n" - cat "$patch" - rm -f "$patch" - exit 1 -fi - -# a patch has been created, notify the user and exit -printf "\nThe following differences were found between the code to commit " -printf "and the f90-format rules:\n\n" -cat "$patch" - -printf "\nYou can apply these changes with:\n git apply %s\n" "${patch}" -printf "(may need to be called from the root directory of your repository)\n" -printf "Aborting commit. Apply changes and commit again or skip checking with" -printf " --no-verify (not recommended).\n" -printf "\nYou can also manually update format by running\n" -printf " emacs -batch -l %s/f90-format.el -f emacs-format-f90-sources\n" "${SCRIPTPATH}" - -exit 1 diff --git a/environment/git/pre-commit-fprettify b/environment/git/pre-commit-fprettify new file mode 100755 index 0000000000..4ebfc3b405 --- /dev/null +++ b/environment/git/pre-commit-fprettify @@ -0,0 +1,170 @@ +#!/bin/bash + +# git pre-commit hook that runs a fprettify stylecheck. +# Features: +# - abort commit when commit does not comply with the style guidelines + +#--------------------------------------------------------------------------------------------------# +# SETTINGS +# +# set path to fprettify binary. If fprettify is not available, then don't run this hook. Style +# issues will be caught during by the pull request process. +#--------------------------------------------------------------------------------------------------# + +# make tmp file readable only by owner +umask 0077 + +debug=off +function debugprint() +{ + if [[ "$debug" == "on" ]]; then echo "$@"; fi +} + +# Allow developers to opt-out +auto_apply=false +if [[ ${DRACO_AUTO_CLANG_FORMAT:-YES} ]]; then + case $DRACO_AUTO_CLANG_FORMAT in + NO | OFF | FALSE | no | off | false ) exit 0 ;; + YES | ON | TRUE | yes | on | true) auto_apply=true ;; + DIFF | diff) auto_apply=false ;; + esac +fi + +# remove any older patches from previous commits. Set to true or false. +DELETE_OLD_PATCHES=true + +# file types to parse. +FILE_EXTS=".f90 .F90 .f .F" +#FILE_ENDINGS_INCLUDE="_f.h _f77.h _f90.h" +FILE_ENDINGS_EXCLUDE="_f.h _f77.h _f90.h" +export FILE_EXTS FILE_ENDINGS_EXCLUDE + +################################################################## +# There should be no need to change anything below this line. +# shellcheck source=environment/git/canonicalize_filename.sh +source "$(dirname -- "$0")/canonicalize_filename.sh" + +# shellcheck source=tools/common.sh +source "$(dirname -- "$0")/common.sh" + +# exit on error +# set -e + +FPY=$(which fprettify 2> /dev/null) +if [[ -x "$FPY" ]]; then + FPYVER=$("$FPY" --version | tail -n 1 | sed -e 's/.*fprettify //') + if [[ $(version_gt "0.3.5" "${FPYVER}") ]]; then + echo "ERROR: Your version of fpy is too old. Expecting v 0.3.6+. Pre-commit-hook" + echo " for f90 indentation will be disabled." + unset FPY + fi +else + unset FPY +fi + +# necessary check for initial commit +if git rev-parse --verify HEAD >/dev/null 2>&1 ; then + against=HEAD +else + # Initial commit: diff against an empty tree object + against=4b825dc642cb6eb9a060e54bf8d69288fbee4904 +fi + +if [ ! -x "$FPY" ] ; then + printf "Error: fprettify executable not found.\n" + printf " skipping f90 format check. To enable this check\n" + printf " set the correct path in %s.\n" "$(canonicalize_filename "$0")" + exit 0 +fi + +# create a random filename to store our generated patch +prefix="pre-commit-fprettify" +suffix="$(date +%s)" + +# clean up any older fprettify patches +$DELETE_OLD_PATCHES && rm -f /tmp/$prefix-*.patch.* &> /dev/null +$DELETE_OLD_PATCHES && rm -f /tmp/$prefix-*.lint.* &> /dev/null +$DELETE_OLD_PATCHES && rm -f /tmp/fprettify-* &> /dev/null + +patchfile=$(mktemp "/tmp/$USER/${prefix}-${suffix}.patch.XXXXXXXX") +lintfile=$(mktemp "/tmp/$USER/${prefix}-${suffix}.lint.XXXXXXXX") + +# create one patch containing all changes to the files +# shellcheck disable=SC2162 +git diff-index --cached --diff-filter=ACMR --name-only $against -- | while read file; +do + # only process f90 files. + if ! matches_extension "$file"; then continue; fi + + # If file is added to commit but still has local modifications, abort + if [[ $(git diff "${file}" | wc -l) != 0 ]]; then + echo -e "\nERROR: File ${file} has local edits that are not staged. Stash modifications or add " + echo -e " changes to this commit.\n\n" + exit 1 + fi + + file_nameonly=$(basename "${file}") + tmpfile1="/tmp/fprettify-$file_nameonly" + + # 1. These issues can be fixed automatically. + debugprint "$FPY -sS $file --> $tmpfile1" + "$FPY" -sS "${file}" &> "${tmpfile1}" + diff -u "${file}" "${tmpfile1}" | \ + sed -e "1s|--- |--- a/|" -e "2s|+++ ${tmpfile1}|+++ b/${file}|" >> "$patchfile" + rm "${tmpfile1}" + + # 2. These issues can not be fixed automatically. + debugprint "cp $file $tmpfile1" + cp "${file}" "${tmpfile1}" + debugprint "$FPY -S $tmpfile1" + "$FPY" -S "${tmpfile1}" + debugprint "$FPY $tmpfile1 --> $lintfile" + "$FPY" "${tmpfile1}" >> "${lintfile}" 2>&1 + # Fix paths in the log file + sed -i "s%${tmpfile1}%${file}%" "${lintfile}" +done + +# if no patch has been generated all is ok, clean up the file stub and exit +if ! [[ -s "$patchfile" ]] && ! [[ -s "$lintfile" ]] ; then + printf "Files in this commit comply with the fpy-based fprettify rules.\n" + rm -f "$patchfile" "$lintfile" + exit 0 +fi + +# If we get here, there are files that don't comply... + +# If user wants to automatically apply these changes, then do it, otherwise, print the diffs and +# reject the commit. +if [[ -s "$patchfile" ]]; then + if [[ $auto_apply == true ]]; then + debugprint "git apply $patchfile" + git apply "$patchfile" + printf "\nFiles in this commit were updated to comply with the fprettify rules.\n" + printf "You must check and test these changes and then stage these updates to\n" + printf "be part of your current change set and retry the commit.\n\n" + git status + # printf "The following changes were applied:\n\n" + # cat "$patchfile" + rm -f "$patchfile" + exit 1 + else + # a patch has been created, notify the user and exit + printf "\nThe following differences were found between the code to commit " + printf "and the fprettify rules:\n\n" + cat "$patchfile" + printf "\nYou can apply these changes with:\n git apply %s\n" "${patchfile}" + printf "(may need to be called from the root directory of your repository)\n" + printf "Aborting commit. Apply changes and commit again or skip checking with" + printf " --no-verify (not recommended).\n" + printf "\nYou can also manually update format by running fprettify \n" + exit 1 + fi +fi + +if [[ -s "$lintfile" ]] ; then + printf "\nSome files in this commit do not conform to the Fortran coding standard.\n" + printf "You must fix these manually and add them to your commit.\n\n" + cat "$lintfile" + rm -f "$lintfile" + exit 1 +fi diff --git a/src/c4/ftest/fc4_test.f90 b/src/c4/ftest/fc4_test.f90 index 6abe03566b..6e6e606a18 100644 --- a/src/c4/ftest/fc4_test.f90 +++ b/src/c4/ftest/fc4_test.f90 @@ -1,14 +1,14 @@ -!----------------------------------*-F90-*------------------------------------- +!---------------------------------------------*-F90-*---------------------------------------------! ! ! \file c4/fc4/fc4_test.f90 ! \author Allan Wollaber, Kelly Thompson ! \date Mon Jul 30 07:06:24 MDT 2012 ! \brief Helper functions for the F90 Draco tests -! \note Copyright (c) 2016-2020 Triad National Security, LLC. -! All rights reserved. +! \note Copyright (c) 2016-2021 Triad National Security, LLC., All rights reserved. ! ! This is a modified version of jayenne/src/api/ftest/API_Test.F90. -!------------------------------------------------------------------------------ +!-------------------------------------------------------------------------------------------------! + module fc4_test use iso_c_binding, only: c_double implicit none @@ -25,9 +25,9 @@ subroutine check_fail(ierr, rank) integer, intent(in) :: ierr integer, intent(in) :: rank - if (ierr .ne. 0) then - write (*, '("**** Test: FAILED on ", I3, " with error ", I3)') rank, ierr - f90_num_failures = f90_num_failures + 1 + if (ierr /= 0) then + write (*, '("**** Test: FAILED on ", I3, " with error ", I3)') rank, ierr + f90_num_failures = f90_num_failures + 1 end if end subroutine check_fail @@ -59,6 +59,6 @@ end subroutine pass_msg end module fc4_test -! --------------------------------------------------------------------------- +!-------------------------------------------------------------------------------------------------! ! End fc4_test.f90 -! --------------------------------------------------------------------------- +!-------------------------------------------------------------------------------------------------! diff --git a/src/ds++/path.cc b/src/ds++/path.cc index fb2c09c411..f5f5b434d2 100644 --- a/src/ds++/path.cc +++ b/src/ds++/path.cc @@ -2,7 +2,7 @@ /*! * \file ds++/path.cc * \brief Encapsulate path information (path separator, etc.) - * \note Copyright (C) 2016-2020 Triad National Security, LLC., All rights reserved. */ + * \note Copyright (C) 2016-2021 Triad National Security, LLC., All rights reserved. */ //------------------------------------------------------------------------------------------------// #include "path.hh" @@ -10,9 +10,6 @@ #include // realpath #include // strerror #include // stat -#ifdef UNIX -#include // struct DIR -#endif namespace rtt_dsxx { diff --git a/tools/check_style.sh b/tools/check_style.sh index 0df21e8e01..fdf58d0a75 100755 --- a/tools/check_style.sh +++ b/tools/check_style.sh @@ -9,9 +9,9 @@ # # Runs various lint programs in the current directory and list locally modified files that are not # compliant with the current coding standard (see .clang_format in the top level source directory.) -# - clang-format for C and C++ code. -# - emacs for Fortran90 -# - cmake-format and cmake-tidy for CMake scripts. +# - clang-format for C and C++ code. (.clang-format) +# - fprettify for Fortran90 (.fprettify.rc) +# - cmake-format and cmake-tidy for CMake scripts (.cmake-format.py) # ------------------------------------------------------------------------------------------------ # #--------------------------------------------------------------------------------------------------# @@ -40,8 +40,7 @@ if [[ -f "${rscriptdir}/common.sh" ]]; then else echo " " echo "FATAL ERROR: Unable to locate Draco's bash functions: " - echo " looking for .../tools/common.sh" - echo " searched rscriptdir = $rscriptdir" + echo " looking for .../tools/common.sh, searched rscriptdir = $rscriptdir" exit 1 fi export rscriptdir @@ -51,14 +50,11 @@ export rscriptdir #--------------------------------------------------------------------------------------------------# print_use() { - echo " " - echo "Usage: ${0##*/} -f -t" - echo " " + echo -e "\nUsage: ${0##*/} -f -t\n" echo "All arguments are optional." echo " -f Show diff and fix files (when possible)." echo -n " -t Run as a pre-commit check, print list of non-conformant files and return with" - echo " exit code = 1 (implies -d)." - echo " " + echo -e " exit code = 1 (implies -d).\n" } #--------------------------------------------------------------------------------------------------# @@ -250,6 +246,8 @@ if [[ -x $CMF ]]; then fi rm -f "${patchfile_cmf}" +else + echo -ne "\n==> Skipping cmake-format checks\n\n" fi #--------------------------------------------------------------------------------------------------# @@ -303,34 +301,38 @@ if [[ -x $CML ]]; then echo "PASS: Changes to CMake sources conform to this project's style requirements." fi +else + echo -ne "\n==> Skipping cmake-lint checks\n\n" fi #--------------------------------------------------------------------------------------------------# -# Check mode (Test F90 code indentation with emacs and bash) +# Check mode (Test F90 code indentation with fprettify) #--------------------------------------------------------------------------------------------------# # Defaults ---------------------------------------- -EMACS=$(which emacs) -if [[ $EMACS ]]; then - EMACSVER=$("$EMACS" --version | head -n 1 | sed -e 's/.*Emacs //') - if [[ $(version_gt "24.0.0" "${EMACSVER}") ]]; then - echo "WARNING: Your version of emacs is too old. Expecting v 24.0+. Pre-commit-hook partially" - echo " disabled (f90 indentation)" - unset EMACS +FPY=$(which fprettify) +if [[ $FPY ]]; then + FPYVER=$("$FPY" --version | tail -n 1 | sed -e 's/.*fprettify //') + if [[ $(version_gt "0.3.5" "${FPYVER}") ]]; then + echo "WARNING: Your version of fprettify is too old. Expecting v 0.3.6+. Pre-commit-hook" + echo " for f90 indentation will be disabled." + unset FPY fi fi -if [[ -x "$EMACS" ]]; then +if [[ -x "$FPY" ]]; then echo -ne "\n--------------------------------------------------------------------------------\n" - echo -e "Checking modified F90 code for style conformance (indentation).\n" + echo -e "Checking modified F90 code for style conformance.\n" - patchfile_f90=$(mktemp /tmp/emf90.patch.XXXXXXXX) + patchfile_f90=$(mktemp /tmp/fpy.patch.XXXXXXXX) + lintfile_f90=$(mktemp /tmp/fpy.lint.XXXXXXXX) # file types to parse. FILE_EXTS=".f90 .F90 .f .F" # FILE_ENDINGS_INCLUDE="CMakeLists.txt" # FILE_ENDINGS_EXLCUDE=".cmake.in" + export FILE_EXTS # Loop over all modified F90 files. Create one patch containing all changes to these files for file in $modifiedfiles; do @@ -341,95 +343,58 @@ if [[ -x "$EMACS" ]]; then file_nameonly=$(basename "${file}") tmpfile1="/tmp/f90-format-${file_nameonly}" - cp -f "${file}" "${tmpfile1}" - "$EMACS" -batch "${tmpfile1}" -l "${rscriptdir}/../environment/git/f90-format.el" \ - -f emacs-format-f90-sources &> /dev/null - # color output is possible if diff -version >= 3.4 with option `--color` - diff ${DIFFCOLOR} -u "${file}" "${tmpfile1}" | \ + + # 1. These issues can be fixed automatically. + "$FPY" -sS "${file}" &> "${tmpfile1}" + diff -u "${file}" "${tmpfile1}" | \ sed -e "1s|--- |--- a/|" -e "2s|+++ ${tmpfile1}|+++ b/${file}|" >> "$patchfile_f90" rm "${tmpfile1}" + # 2. These issues can not be fixed automatically. + cp "${file}" "${tmpfile1}" + "$FPY" -S "${tmpfile1}" + "$FPY" "${tmpfile1}" >> "${lintfile_f90}" 2>&1 + done # If the patch file is size 0, then no changes are needed. - if [[ -s "$patchfile_f90" ]]; then + if [[ -s "$patchfile_f90" ]] || [[ -s "$lintfile_f90" ]]; then foundissues=1 - echo -n "FAIL: some F90 files do not conform to this project's style requirements:" + echo -ne "FAIL: some F90 files do not conform to this project's style requirements:\n" # Modify files, if requested - if [[ "${fix_mode}" == 1 ]]; then - echo -e " The following patch has been applied to your file.\n" - run "git apply $patchfile_f90" - cat "$patchfile_f90" - else - echo -ne " run ${0##*/} with option -f to automatically apply this patch.\n" - cat "$patchfile_f90" + if [[ -s "$patchfile_f90" ]]; then + if [[ "${fix_mode}" == 1 ]]; then + run "git apply $patchfile_f90" + echo -ne "\n Changes have been made to your F90 files to meet style guidelines." + echo -ne "\n Please check the updated files and add them to your commit.\n" + else + echo -ne " run ${0##*/} with option -f to automatically apply this patch.\n" + cat "$patchfile_f90" + fi + fi + if [[ -s "$lintfile_f90" ]]; then + + echo -e " The following F90 style errors must be fixed.\n" + cat "${lintfile_f90}" + echo -ne "\n Please reformat lines listed above and attempt running\n" + echo -ne " ${0##*/} again. These issues cannot be fixed with the -f option." fi else echo -n "PASS: Changes to F90 sources conform to this project's style requirements." fi rm -f "${patchfile_f90}" + rm -f "${lintfile_f90}" fi -#--------------------------------------------------------------------------------------------------# -# Check mode (Test F90 code line length with bash) -#--------------------------------------------------------------------------------------------------# - -echo -ne "\n--------------------------------------------------------------------------------" -echo -e "\nChecking modified F90 code for style conformance (line length)..\n" - -tmpfile2=$(mktemp /tmp/f90-format-line-len.XXXXXXXX) - -# Loop over all modified F90 files. Create one patch containing all changes to these files -for file in $modifiedfiles; do - - # ignore file if we do check for file extensions and the file does not match any of the extensions - # specified in $FILE_EXTS - if ! matches_extension "$file"; then continue; fi - - header_printed=0 - lineno=0 - - # shellcheck disable=SC2162 - while read line; do - (( lineno++ )) - # Exceptions: - # - Long URLs - exception=$(echo "${line}" | grep -i -c http) - if [[ ${#line} -gt 100 && ${exception} == 0 ]]; then - if [[ ${header_printed} == 0 ]]; then - { - echo -e "\nFile: ${file} [code line too long]\n"; - echo " line length content"; - echo -n " ------ ------ -------------------------------------------------------------"; - echo "-------------------" - } >> "${tmpfile2}" - header_printed=1 - fi - printf " %-6s %-6s %s\n" "${lineno}" "${#line}" "${line}" >> "${tmpfile2}" - fi - # reset exception flag - exception=0 - done < "${file}" -done - -unset FILE_EXTS -unset FILE_ENDINGS_INCLUDE -unset FILE_ENDINGS_EXCLUDE - -# If there are issues, report them -if [[ $(wc -l < "${tmpfile2}") -gt 0 ]]; then - foundissues=1 - echo -ne "FAIL: some F90 files do not conform to this project's style requirements:\n" - cat "$tmpfile2" - echo -ne "\nPlease reformat lines listed above to fit into 80 columns and attempt running\n" - echo -ne "${0##*/} again. These issues cannot be fixed with the -f option." -fi - #--------------------------------------------------------------------------------------------------# # Done #--------------------------------------------------------------------------------------------------# +echo -ne "\n--------------------------------------------------------------------------------\n" +echo "Done" +echo -ne "\n--------------------------------------------------------------------------------\n" + # Return code: 0==ok,1==bad exit $foundissues