[binutils-gdb] [pre-commit] Add codespell-log commit-msg hook

Tom de Vries vries@sourceware.org
Fri Apr 25 17:22:49 GMT 2025


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=129228c8b01a8fe0345e33fe07d185047721bd68

commit 129228c8b01a8fe0345e33fe07d185047721bd68
Author: Tom de Vries <tdevries@suse.de>
Date:   Fri Apr 25 19:22:36 2025 +0200

    [pre-commit] Add codespell-log commit-msg hook
    
    Now that we're using codespell to check spelling in gdb files, can we use
    codespell to bring this spelling warning:
    ...
    $ echo usuable | codespell -
    1: usuable
            usuable ==> usable
    ...
    to:
    ...
    $ git commit -a -m "Usuable stuff"
    ...
    ?
    
    First, let's look at a straightforward commit-msg hook implementation:
    ...
        - id: codespell
          name: codespell-commit-msg
          verbose: true
          always_run: true
          stages: [commit-msg]
    ...
    installed using:
    ...
    $ pre-commit install -t commit-msg
    ...
    
    When trying the commit, we get:
    ...
    $ echo "/* bla */" >> gdb/gdb.c
    $ git commit -a -m "Usuable stuff"
    black................................................(no files to check)Skipped
    flake8...............................................(no files to check)Skipped
    isort................................................(no files to check)Skipped
    codespell............................................(no files to check)Skipped
    check-include-guards.................................(no files to check)Skipped
    black................................................(no files to check)Skipped
    flake8...............................................(no files to check)Skipped
    codespell............................................(no files to check)Skipped
    codespell-commit-msg.....................................................Failed
    - hook id: codespell
    - duration: 0.06s
    - exit code: 65
    
    .git/COMMIT_EDITMSG:1: Usuable ==> Usable
    
    check-include-guards.................................(no files to check)Skipped
    $
    ...
    
    The commit was aborted, but the commit message is still there:
    ...
    $ cat .git/COMMIT_EDITMSG
    Usuable stuff
    ...
    
    We can retry and edit the commit message to clean up the typo:
    ...
    $ git commit -e -F .git/COMMIT_EDITMSG -a
    ...
    but it's a bit cumbersome.
    
    Furthermore, say we fix a typo and want to document this in the commit log, and
    do:
    ...
    $ git commit -m "Fixed typo: useable -> usable" -a
    ...
    
    This commit cannot succeed, unless we add a codespell ignore tag, which feels
    like taking it too far.
    
    Both these problems can be addressed by setting things up in such a way that
    the commit always succeeds, and codespell output is shown as a hint.
    
    Ideally, we'd tell to pre-commit to implement this using some setting, but
    there doesn't seem to be one.
    
    So we use some indirection.  Instead of using native codespell, use a local
    hook that calls a script gdb/contrib/codespell-log.sh, which calls pre-commit,
    which calls codespell.
    
    Using this approach, we get:
    ...
    $ echo "/* bla */" >> gdb/gdb.c
    $ git commit -a -m "Usuable stuff"
    black................................................(no files to check)Skipped
    flake8...............................................(no files to check)Skipped
    isort................................................(no files to check)Skipped
    codespell............................................(no files to check)Skipped
    check-include-guards.................................(no files to check)Skipped
    black................................................(no files to check)Skipped
    flake8...............................................(no files to check)Skipped
    codespell............................................(no files to check)Skipped
    check-include-guards.................................(no files to check)Skipped
    codespell-log............................................................Passed
    - hook id: codespell-log
    - duration: 0.18s
    
    codespell-log-internal...................................................Failed
    - hook id: codespell
    - exit code: 65
    
    .git/COMMIT_EDITMSG:1: Usuable ==> Usable
    
    [codespell/codespell-log-2 d081bd25a40] Usuable stuff
     1 file changed, 1 insertion(+)
    $
    ...
    
    This is obviously convoluted, but it works.  Perhaps we can propose a
    pre-commit improvement (always_pass) and simplify this eventually.
    
    Checked new script codespell-log.sh with shell-check.
    
    Approved-By: Simon Marchi <simon.marchi@efficios.com>

Diff:
---
 .pre-commit-config.yaml      |  8 ++++
 gdb/contrib/codespell-log.sh | 95 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 103 insertions(+)

diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index b55685b5f70..7cb7008f2df 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -38,6 +38,7 @@
 # See https://pre-commit.com/hooks.html for more hooks
 
 minimum_pre_commit_version: 3.2.0
+default_install_hook_types: [pre-commit, commit-msg]
 repos:
   - repo: https://github.com/psf/black-pre-commit-mirror
     rev: 25.1.0
@@ -80,3 +81,10 @@ repos:
       # All gdb header files, but not headers in the test suite.
       files: '^(gdb(support|server)?)/.*\.h$'
       exclude: '.*/testsuite/.*'
+    - id: codespell-log
+      name: codespell-log
+      language: script
+      entry: gdb/contrib/codespell-log.sh
+      verbose: true
+      always_run: true
+      stages: [commit-msg]
diff --git a/gdb/contrib/codespell-log.sh b/gdb/contrib/codespell-log.sh
new file mode 100755
index 00000000000..10780f86c5f
--- /dev/null
+++ b/gdb/contrib/codespell-log.sh
@@ -0,0 +1,95 @@
+#!/usr/bin/env bash
+
+# Copyright (C) 2025 Free Software Foundation, Inc.
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# Script to be used as pre-commit commit-msg hook to spell-check the commit
+# log using codespell.
+#
+# Using codespell directly as a pre-commit commit-msg hook has the drawback
+# that:
+# - if codespell fails, the commit fails
+# - if the commit log mentions a typo correction, it'll require a
+#   codespell:ignore annotation.
+#
+# This script works around these problems by treating codespell output as a
+# hint, and ignoring codespell exit status.
+#
+# Implementation note: rather than using codespell directly, this script uses
+# pre-commit to call codespell, because it allows us to control the codespell
+# version that is used.
+
+# Exit on error.
+set -e
+
+# Initialize temporary file names.
+cfg=""
+output=""
+
+cleanup()
+{
+    for f in "$cfg" "$output"; do
+	if [ "$f" != "" ]; then
+	    rm -f "$f"
+	fi
+    done
+}
+
+# Schedule cleanup.
+trap cleanup EXIT
+
+# Create temporary files.
+cfg=$(mktemp)
+output=$(mktemp)
+
+gen_cfg ()
+{
+    cat > "$1" <<EOF
+repos:
+- repo: https://github.com/codespell-project/codespell
+  rev: v2.4.1
+  hooks:
+  - id: codespell
+    name: codespell-log-internal
+    stages: [manual]
+    args: [--config, gdb/contrib/setup.cfg]
+EOF
+}
+
+# Generate pre-commit configuration file.
+gen_cfg "$cfg"
+
+# Setup pre-commit command to run.
+cmd=(pre-commit \
+    run \
+    -c "$cfg" \
+    codespell \
+    --hook-stage manual \
+    --files "$@")
+
+# Run pre-commit command.
+if "${cmd[@]}" \
+     > "$output" \
+     2>&1; then
+    # Command succeeded quietly, we're done.
+    exit 0
+fi
+
+# Command failed quietly, now show the output.
+#
+# Simply doing "cat $output" doesn't produce colored output, so we just
+# run the command again, that should be fast enough.
+#
+# Ignore codespell exit status.
+"${cmd[@]}" || true


More information about the Binutils-cvs mailing list