summaryrefslogtreecommitdiff
path: root/misc/hooks
diff options
context:
space:
mode:
Diffstat (limited to 'misc/hooks')
-rw-r--r--misc/hooks/README.md37
-rwxr-xr-xmisc/hooks/pre-commit2
-rwxr-xr-xmisc/hooks/pre-commit-black202
-rwxr-xr-xmisc/hooks/pre-commit-clang-format96
-rwxr-xr-xmisc/hooks/pre-commit-makerst9
-rwxr-xr-xmisc/hooks/winmessage.ps1103
6 files changed, 424 insertions, 25 deletions
diff --git a/misc/hooks/README.md b/misc/hooks/README.md
index b18ba7df38..5661c239ed 100644
--- a/misc/hooks/README.md
+++ b/misc/hooks/README.md
@@ -5,16 +5,33 @@ contributors to make sure they comply with our requirements.
## List of hooks
-- Pre-commit hook for clang-format: Applies clang-format to the staged files
- before accepting a commit; blocks the commit and generates a patch if the
- style is not respected.
- Should work on Linux and macOS. You may need to edit the file if your
- clang-format binary is not in the `$PATH`, or if you want to enable colored
- output with pygmentize.
-- Pre-commit hook for makerst: Checks the class reference syntax using `makerst.py`.
- Should work on Linux and macOS.
+- Pre-commit hook for `clang-format`: Applies `clang-format` to the staged
+ files before accepting a commit; blocks the commit and generates a patch if
+ the style is not respected.
+ You may need to edit the file if your `clang-format` binary is not in the
+ `PATH`, or if you want to enable colored output with `pygmentize`.
+- Pre-commit hook for `black`: Applies `black` to the staged Python files
+ before accepting a commit.
+- Pre-commit hook for `makerst`: Checks the class reference syntax using
+ `makerst.py`.
## Installation
-Copy all the files from this folder into your `.git/hooks` folder, and make sure
-the hooks and helper scripts are executable.
+Copy all the files from this folder into your `.git/hooks` folder, and make
+sure the hooks and helper scripts are executable.
+
+#### Linux/MacOS
+
+The hooks rely on bash scripts and tools which should be in the system `PATH`,
+so they should work out of the box on Linux/macOS.
+
+#### Windows
+
+##### clang-format
+- Download LLVM for Windows (version 8 or later) from
+ <https://releases.llvm.org/download.html>
+- Make sure LLVM is added to the `PATH` during installation
+
+##### black
+- Python installation: make sure Python is added to the `PATH`
+- Install `black` - in any console: `pip3 install black`
diff --git a/misc/hooks/pre-commit b/misc/hooks/pre-commit
index 36e9935785..40cb00253b 100755
--- a/misc/hooks/pre-commit
+++ b/misc/hooks/pre-commit
@@ -14,7 +14,7 @@
# 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-compile pre-commit-uncrustify"
-HOOKS="pre-commit-clang-format pre-commit-makerst"
+HOOKS="pre-commit-clang-format pre-commit-black pre-commit-makerst"
###########################################################
# There should be no need to change anything below this line.
diff --git a/misc/hooks/pre-commit-black b/misc/hooks/pre-commit-black
new file mode 100755
index 0000000000..76d97294da
--- /dev/null
+++ b/misc/hooks/pre-commit-black
@@ -0,0 +1,202 @@
+#!/usr/bin/env bash
+
+# git pre-commit hook that runs a black stylecheck.
+# Based on pre-commit-clang-format.
+
+##################################################################
+# SETTINGS
+# Set path to black binary.
+BLACK=`which black 2>/dev/null`
+BLACK_OPTIONS="-l 120"
+
+# Remove any older patches from previous commits. Set to true or false.
+DELETE_OLD_PATCHES=false
+
+# File types to parse.
+FILE_NAMES="SConstruct SCsub"
+FILE_EXTS="py"
+
+# Use pygmentize instead of cat to parse diff with highlighting.
+# Install it with `pip install pygments` (Linux) or `easy_install Pygments` (Mac)
+PYGMENTIZE=`which pygmentize 2>/dev/null`
+if [ ! -z "$PYGMENTIZE" ]; then
+ READER="pygmentize -l diff"
+else
+ READER=cat
+fi
+
+# Path to zenity
+ZENITY=`which zenity 2>/dev/null`
+
+# Path to xmessage
+XMSG=`which xmessage 2>/dev/null`
+
+# Path to powershell (Windows only)
+PWSH=`which powershell 2>/dev/null`
+
+##################################################################
+# There should be no need to change anything below this line.
+
+. "$(dirname -- "$0")/canonicalize_filename.sh"
+
+# exit on error
+set -e
+
+# check whether the given file matches any of the set extensions
+matches_name_or_extension() {
+ local filename=$(basename "$1")
+ local extension=".${filename##*.}"
+
+ for name in $FILE_NAMES; do [[ "$name" == "$filename" ]] && return 0; done
+ for ext in $FILE_EXTS; do [[ "$ext" == "$extension" ]] && return 0; done
+
+ return 1
+}
+
+# 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 "$BLACK" ] ; then
+ if [ ! -t 1 ] ; then
+ if [ -x "$ZENITY" ] ; then
+ $ZENITY --error --title="Error" --text="Error: black executable not found."
+ exit 1
+ elif [ -x "$XMSG" ] ; then
+ $XMSG -center -title "Error" "Error: black executable not found."
+ exit 1
+ elif [ \( \( "$OSTYPE" = "msys" \) -o \( "$OSTYPE" = "win32" \) \) -a \( -x "$PWSH" \) ]; then
+ winmessage="$(canonicalize_filename "./.git/hooks/winmessage.ps1")"
+ $PWSH -noprofile -executionpolicy bypass -file "$winmessage" -center -title "Error" --text "Error: black executable not found."
+ exit 1
+ fi
+ fi
+ printf "Error: black executable not found.\n"
+ printf "Set the correct path in $(canonicalize_filename "$0").\n"
+ exit 1
+fi
+
+# create a random filename to store our generated patch
+prefix="pre-commit-black"
+suffix="$(date +%s)"
+patch="/tmp/$prefix-$suffix.patch"
+
+# clean up any older black patches
+$DELETE_OLD_PATCHES && rm -f /tmp/$prefix*.patch
+
+# create one patch containing all changes to the files
+git diff-index --cached --diff-filter=ACMR --name-only $against -- | while read file;
+do
+ # ignore thirdparty files
+ if grep -q "thirdparty" <<< $file; then
+ continue;
+ fi
+
+ # ignore file if not one of the names or extensions we handle
+ if ! matches_name_or_extension "$file"; then
+ continue;
+ fi
+
+ # format our file with black, create a patch with diff and append it to our $patch
+ # The sed call is necessary to transform the patch from
+ # --- $file timestamp
+ # +++ $file timestamp
+ # to both lines working on the same file and having a/ and b/ prefix.
+ # Else it can not be applied with 'git apply'.
+ "$BLACK" "$BLACK_OPTIONS" --diff "$file" | \
+ sed -e "1s|--- |--- a/|" -e "2s|+++ |+++ b/|" >> "$patch"
+done
+
+# if no patch has been generated all is ok, clean up the file stub and exit
+if [ ! -s "$patch" ] ; then
+ printf "Files in this commit comply with the black formatter rules.\n"
+ rm -f "$patch"
+ exit 0
+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 black formatter rules:\n\n"
+
+if [ -t 1 ] ; then
+ $READER "$patch"
+ printf "\n"
+ # Allows us to read user input below, assigns stdin to keyboard
+ exec < /dev/tty
+ terminal="1"
+else
+ cat "$patch"
+ printf "\n"
+ # Allows non zero zenity/powershell output
+ set +e
+ terminal="0"
+fi
+
+while true; do
+ if [ $terminal = "0" ] ; then
+ if [ -x "$ZENITY" ] ; then
+ ans=$($ZENITY --text-info --filename="$patch" --width=800 --height=600 --title="Do you want to apply that patch?" --ok-label="Apply" --cancel-label="Do not apply" --extra-button="Apply and stage")
+ if [ "$?" = "0" ] ; then
+ yn="Y"
+ else
+ if [ "$ans" = "Apply and stage" ] ; then
+ yn="S"
+ else
+ yn="N"
+ fi
+ fi
+ elif [ -x "$XMSG" ] ; then
+ $XMSG -file "$patch" -buttons "Apply":100,"Apply and stage":200,"Do not apply":0 -center -default "Do not apply" -geometry 800x600 -title "Do you want to apply that patch?"
+ ans=$?
+ if [ "$ans" = "100" ] ; then
+ yn="Y"
+ elif [ "$ans" = "200" ] ; then
+ yn="S"
+ else
+ yn="N"
+ fi
+ elif [ \( \( "$OSTYPE" = "msys" \) -o \( "$OSTYPE" = "win32" \) \) -a \( -x "$PWSH" \) ]; then
+ winmessage="$(canonicalize_filename "./.git/hooks/winmessage.ps1")"
+ $PWSH -noprofile -executionpolicy bypass -file "$winmessage" -file "$patch" -buttons "Apply":100,"Apply and stage":200,"Do not apply":0 -center -default "Do not apply" -geometry 800x600 -title "Do you want to apply that patch?"
+ ans=$?
+ if [ "$ans" = "100" ] ; then
+ yn="Y"
+ elif [ "$ans" = "200" ] ; then
+ yn="S"
+ else
+ yn="N"
+ fi
+ else
+ printf "Error: zenity, xmessage, or powershell executable not found.\n"
+ exit 1
+ fi
+ else
+ read -p "Do you want to apply that patch (Y - Apply, N - Do not apply, S - Apply and stage files)? [Y/N/S] " yn
+ fi
+ case $yn in
+ [Yy] ) git apply $patch;
+ printf "The patch was applied. You can now stage the changes and commit again.\n\n";
+ break
+ ;;
+ [Nn] ) printf "\nYou can apply these changes with:\n git apply $patch\n";
+ 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\n";
+ break
+ ;;
+ [Ss] ) git apply $patch;
+ git diff-index --cached --diff-filter=ACMR --name-only $against -- | while read file;
+ do git add $file;
+ done
+ printf "The patch was applied and the changed files staged. You can now commit.\n\n";
+ break
+ ;;
+ * ) echo "Please answer yes or no."
+ ;;
+ esac
+done
+exit 1 # we don't commit in any case
diff --git a/misc/hooks/pre-commit-clang-format b/misc/hooks/pre-commit-clang-format
index e309233a8b..4e1fbdeb20 100755
--- a/misc/hooks/pre-commit-clang-format
+++ b/misc/hooks/pre-commit-clang-format
@@ -15,28 +15,37 @@
##################################################################
# SETTINGS
-# Set path to clang-format binary
-# CLANG_FORMAT="/usr/bin/clang-format"
-CLANG_FORMAT=`which clang-format`
+# Set path to clang-format binary.
+CLANG_FORMAT=`which clang-format 2>/dev/null`
# Remove any older patches from previous commits. Set to true or false.
-# DELETE_OLD_PATCHES=false
DELETE_OLD_PATCHES=false
# Only parse files with the extensions in FILE_EXTS. Set to true or false.
# If false every changed file in the commit will be parsed with clang-format.
# If true only files matching one of the extensions are parsed with clang-format.
-# PARSE_EXTS=true
PARSE_EXTS=true
# File types to parse. Only effective when PARSE_EXTS is true.
-# FILE_EXTS=".c .h .cpp .hpp"
FILE_EXTS=".c .h .cpp .hpp .cc .hh .cxx .m .mm .inc .java .glsl"
# Use pygmentize instead of cat to parse diff with highlighting.
# Install it with `pip install pygments` (Linux) or `easy_install Pygments` (Mac)
-# READER="pygmentize -l diff"
-READER=cat
+PYGMENTIZE=`which pygmentize 2>/dev/null`
+if [ ! -z "$PYGMENTIZE" ]; then
+ READER="pygmentize -l diff"
+else
+ READER=cat
+fi
+
+# Path to zenity
+ZENITY=`which zenity 2>/dev/null`
+
+# Path to xmessage
+XMSG=`which xmessage 2>/dev/null`
+
+# Path to powershell (Windows only)
+PWSH=`which powershell 2>/dev/null`
##################################################################
# There should be no need to change anything below this line.
@@ -66,6 +75,19 @@ else
fi
if [ ! -x "$CLANG_FORMAT" ] ; then
+ if [ ! -t 1 ] ; then
+ if [ -x "$ZENITY" ] ; then
+ $ZENITY --error --title="Error" --text="Error: clang-format executable not found."
+ exit 1
+ elif [ -x "$XMSG" ] ; then
+ $XMSG -center -title "Error" "Error: clang-format executable not found."
+ exit 1
+ elif [ \( \( "$OSTYPE" = "msys" \) -o \( "$OSTYPE" = "win32" \) \) -a \( -x "$PWSH" \) ]; then
+ winmessage="$(canonicalize_filename "./.git/hooks/winmessage.ps1")"
+ $PWSH -noprofile -executionpolicy bypass -file "$winmessage" -center -title "Error" --text "Error: clang-format executable not found."
+ exit 1
+ fi
+ fi
printf "Error: clang-format executable not found.\n"
printf "Set the correct path in $(canonicalize_filename "$0").\n"
exit 1
@@ -117,14 +139,62 @@ 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 clang-format rules:\n\n"
-$READER "$patch"
-printf "\n"
-# Allows us to read user input below, assigns stdin to keyboard
-exec < /dev/tty
+if [ -t 1 ] ; then
+ $READER "$patch"
+ printf "\n"
+ # Allows us to read user input below, assigns stdin to keyboard
+ exec < /dev/tty
+ terminal="1"
+else
+ cat "$patch"
+ printf "\n"
+ # Allows non zero zenity/powershell output
+ set +e
+ terminal="0"
+fi
while true; do
- read -p "Do you want to apply that patch (Y - Apply, N - Do not apply, S - Apply and stage files)? [Y/N/S] " yn
+ if [ $terminal = "0" ] ; then
+ if [ -x "$ZENITY" ] ; then
+ ans=$($ZENITY --text-info --filename="$patch" --width=800 --height=600 --title="Do you want to apply that patch?" --ok-label="Apply" --cancel-label="Do not apply" --extra-button="Apply and stage")
+ if [ "$?" = "0" ] ; then
+ yn="Y"
+ else
+ if [ "$ans" = "Apply and stage" ] ; then
+ yn="S"
+ else
+ yn="N"
+ fi
+ fi
+ elif [ -x "$XMSG" ] ; then
+ $XMSG -file "$patch" -buttons "Apply":100,"Apply and stage":200,"Do not apply":0 -center -default "Do not apply" -geometry 800x600 -title "Do you want to apply that patch?"
+ ans=$?
+ if [ "$ans" = "100" ] ; then
+ yn="Y"
+ elif [ "$ans" = "200" ] ; then
+ yn="S"
+ else
+ yn="N"
+ fi
+ elif [ \( \( "$OSTYPE" = "msys" \) -o \( "$OSTYPE" = "win32" \) \) -a \( -x "$PWSH" \) ]; then
+ winmessage="$(canonicalize_filename "./.git/hooks/winmessage.ps1")"
+ $PWSH -noprofile -executionpolicy bypass -file "$winmessage" -file "$patch" -buttons "Apply":100,"Apply and stage":200,"Do not apply":0 -center -default "Do not apply" -geometry 800x600 -title "Do you want to apply that patch?"
+ ans=$?
+ if [ "$ans" = "100" ] ; then
+ yn="Y"
+ elif [ "$ans" = "200" ] ; then
+ yn="S"
+ else
+ yn="N"
+ fi
+ else
+ printf "Error: zenity, xmessage, or powershell executable not found.\n"
+ exit 1
+ fi
+ else
+ read -p "Do you want to apply that patch (Y - Apply, N - Do not apply, S - Apply and stage files)? [Y/N/S] " yn
+ fi
case $yn in
[Yy] ) git apply $patch;
printf "The patch was applied. You can now stage the changes and commit again.\n\n";
diff --git a/misc/hooks/pre-commit-makerst b/misc/hooks/pre-commit-makerst
index d9b684e73b..b990788b99 100755
--- a/misc/hooks/pre-commit-makerst
+++ b/misc/hooks/pre-commit-makerst
@@ -2,4 +2,11 @@
# Git pre-commit hook that checks the class reference syntax using makerst.py.
-doc/tools/makerst.py doc/classes modules --dry-run
+# Workaround because we can't execute the .py file directly on windows
+PYTHON=python
+py_ver=$($PYTHON -c "import sys; print(sys.version_info.major)")
+if [[ "$py_ver" != "3" ]]; then
+ PYTHON+=3
+fi
+
+$PYTHON doc/tools/makerst.py doc/classes modules --dry-run
diff --git a/misc/hooks/winmessage.ps1 b/misc/hooks/winmessage.ps1
new file mode 100755
index 0000000000..3672579544
--- /dev/null
+++ b/misc/hooks/winmessage.ps1
@@ -0,0 +1,103 @@
+Param (
+ [string]$file = "",
+ [string]$text = "",
+ [string]$buttons = "OK:0",
+ [string]$default = "",
+ [switch]$nearmouse = $false,
+ [switch]$center = $false,
+ [string]$geometry = "",
+ [int32]$timeout = 0,
+ [string]$title = "Message"
+)
+Add-Type -assembly System.Windows.Forms
+
+$global:Result = 0
+
+$main_form = New-Object System.Windows.Forms.Form
+$main_form.Text = $title
+
+$geometry_data = $geometry.Split("+")
+if ($geometry_data.Length -ge 1) {
+ $size_data = $geometry_data[0].Split("x")
+ if ($size_data.Length -eq 2) {
+ $main_form.Width = $size_data[0]
+ $main_form.Height = $size_data[1]
+ }
+}
+if ($geometry_data.Length -eq 3) {
+ $main_form.StartPosition = [System.Windows.Forms.FormStartPosition]::Manual
+ $main_form.Location = New-Object System.Drawing.Point($geometry_data[1], $geometry_data[2])
+}
+if ($nearmouse) {
+ $main_form.StartPosition = [System.Windows.Forms.FormStartPosition]::Manual
+ $main_form.Location = System.Windows.Forms.Cursor.Position
+}
+if ($center) {
+ $main_form.StartPosition = [System.Windows.Forms.FormStartPosition]::CenterScreen
+}
+
+$main_form.SuspendLayout()
+
+$button_panel = New-Object System.Windows.Forms.FlowLayoutPanel
+$button_panel.SuspendLayout()
+$button_panel.FlowDirection = [System.Windows.Forms.FlowDirection]::RightToLeft
+$button_panel.Dock = [System.Windows.Forms.DockStyle]::Bottom
+$button_panel.Autosize = $true
+
+if ($file -ne "") {
+ $text = [IO.File]::ReadAllText($file).replace("`n", "`r`n")
+}
+
+if ($text -ne "") {
+ $text_box = New-Object System.Windows.Forms.TextBox
+ $text_box.Multiline = $true
+ $text_box.ReadOnly = $true
+ $text_box.Autosize = $true
+ $text_box.Text = $text
+ $text_box.Select(0,0)
+ $text_box.Dock = [System.Windows.Forms.DockStyle]::Fill
+ $main_form.Controls.Add($text_box)
+}
+
+$buttons_array = $buttons.Split(",")
+foreach ($button in $buttons_array) {
+ $button_data = $button.Split(":")
+ $button_ctl = New-Object System.Windows.Forms.Button
+ if ($button_data.Length -eq 2) {
+ $button_ctl.Tag = $button_data[1]
+ } else {
+ $button_ctl.Tag = 100 + $buttons_array.IndexOf($button)
+ }
+ if ($default -eq $button_data[0]) {
+ $main_form.AcceptButton = $button_ctl
+ }
+ $button_ctl.Autosize = $true
+ $button_ctl.Text = $button_data[0]
+ $button_ctl.Add_Click(
+ {
+ Param($sender)
+ $global:Result = $sender.Tag
+ $main_form.Close()
+ }
+ )
+ $button_panel.Controls.Add($button_ctl)
+}
+$main_form.Controls.Add($button_panel)
+
+$button_panel.ResumeLayout($false)
+$main_form.ResumeLayout($false)
+
+if ($timeout -gt 0) {
+ $timer = New-Object System.Windows.Forms.Timer
+ $timer.Add_Tick(
+ {
+ $global:Result = 0
+ $main_form.Close()
+ }
+ )
+ $timer.Interval = $timeout
+ $timer.Start()
+}
+$dlg_res = $main_form.ShowDialog()
+
+[Environment]::Exit($global:Result)