Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Tom de Vries <tdevries@suse.de>
To: gdb-patches@sourceware.org
Subject: [RFC 1/3] [pre-commit] Add shfmt
Date: Wed,  2 Sep 2026 15:17:37 +0200	[thread overview]
Message-ID: <20260902131739.2125928-2-tdevries@suse.de> (raw)
In-Reply-To: <20260902131739.2125928-1-tdevries@suse.de>

Add a new pre-commit hook shfmt, disabled.

A few notable changes in formatting compared to 'emacs' style are:
...
$ cat test.sh.bak
case "$1" in
    foo \
	| bar )
	:
	;;
esac

var=$(foo \
	  bar)
$ cp test.sh.bak test.sh; ./gdb/contrib/shfmt.sh test.sh
$ diff -u test.sh.bak test.sh
@@ -1,11 +1,11 @@
 case "$1" in
-    foo \
-	| bar )
+    foo | \
+	bar)
 	:
 	;;
 esac

 var=$(foo \
-	  bar)
+    bar)
...

The hook uses https://github.com/scop/pre-commit-shfmt.git, which provides a
.pre-commit-hooks.yaml file.  The file presents three alternatives:
- shfmt (prebuilt upstream executable)
- shfmt-src (build from source)
- shfmt-docker (Docker image)

I've chosen the shfmt-src one.  It relies on dependency
mvdan.cc/sh/v3/cmd/shfmt@v3.13.1, which points to go package
https://pkg.go.dev/mvdan.cc/sh/v3/cmd/shfmt, which uses repository
https://github.com/mvdan/sh.
---
 .pre-commit-config.yaml   | 12 ++++++
 gdb/contrib/pre-commit.py |  6 ++-
 gdb/contrib/shfmt.sh      | 83 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 100 insertions(+), 1 deletion(-)
 create mode 100755 gdb/contrib/shfmt.sh

diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 0b4285e6c82..2d2b5e38ca1 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -114,6 +114,18 @@ repos:
         # Enable strict mode to make sure we see and fix warnings.
         args: [--strict]
 
+  # Shell script hooks.
+  - repo: https://github.com/scop/pre-commit-shfmt.git
+    rev: v3.13.1-1
+    hooks:
+      - id: shfmt-src
+        alias: shfmt
+        entry: gdb/contrib/shfmt.sh
+        files: *gdb_files
+        args: []
+        # Disabled.
+        stages: [manual]
+
   # Local hooks.
   - repo: local
     hooks:
diff --git a/gdb/contrib/pre-commit.py b/gdb/contrib/pre-commit.py
index f3ad6f803b0..66b8667a2f2 100755
--- a/gdb/contrib/pre-commit.py
+++ b/gdb/contrib/pre-commit.py
@@ -49,7 +49,11 @@ def config_check_repo(repo):
 
     # Check version number.  Don't allow pre-releases like 9.0.0b1.
     # We currently only need to support x.y.z, but that could change.
-    if not re.fullmatch(r"\d+[.]\d+[.]\d+", rev):
+    re_rev = r"\d+[.]\d+[.]\d+"
+    if name == "https://github.com/scop/pre-commit-shfmt.git":
+        re_rev += r"-\d+"
+
+    if not re.fullmatch(re_rev, rev):
         print("Revision %s for repo %s not allowed." % (rev, name))
         return False
 
diff --git a/gdb/contrib/shfmt.sh b/gdb/contrib/shfmt.sh
new file mode 100755
index 00000000000..9cdf863b4d1
--- /dev/null
+++ b/gdb/contrib/shfmt.sh
@@ -0,0 +1,83 @@
+#!/bin/bash
+
+f2=()
+f4=()
+
+for f in "$@"; do
+    # The gdb/config/djgpp/* pattern matches the explicitly mentioned
+    # djcheck.sh and djconfig.sh.  Allow this.
+    # shellcheck disable=SC2221,SC2222
+    case "$f" in
+	*/configure)
+	    # Generated.
+	    continue
+	    ;;
+	gdb/config/djgpp/*)
+	    # For now, these scripts prefer `...` over $(...). See
+	    # gdb/config/djgpp/.shellcheckrc.
+	    # Shfmt automatically rewrites to $(...), so skip these.
+	    continue
+	    ;;
+	gdb/config/djgpp/djcheck.sh)
+	    # Mixed 2/4 indentation.
+	    continue
+	    ;;
+	gdb/config/djgpp/djconfig.sh \
+	    | gdb/contrib/expect-read1.sh \
+	    | gdb/features/feature_to_c.sh \
+	    | gdb/gdb_buildall.sh )
+	    f2=("${f2[@]}" "$f")
+	    ;;
+	*)
+	    f4=("${f4[@]}" "$f")
+	    ;;
+    esac
+done
+
+with_indent()
+{
+    indent="$1"
+    shift
+
+    if [ $# -eq 0 ]; then
+	return
+    fi
+
+    shfmt \
+	--language-dialect=auto \
+	--indent="$indent" \
+	--func-next-line \
+	--space-redirects \
+	--case-indent \
+	--binary-next-line \
+	--write \
+	"$@"
+}
+
+with_indent 2 "${f2[@]}"
+with_indent 4 "${f4[@]}"
+
+tmp=""
+
+cleanup()
+{
+    if [ "$tmp" != "" ]; then
+	rm -f "$tmp"
+    fi
+}
+
+# Schedule cleanup.
+trap cleanup EXIT
+
+tmp=$(mktemp)
+
+for f in "${f2[@]}" "${f4[@]}"; do
+    unexpand \
+	--first-only \
+	--tabs=8 \
+	"$f" \
+	> "$tmp"
+
+    # Use cat to preserve permissions on $f.
+    cat "$tmp" > "$f"
+done
-- 
2.51.0


  reply	other threads:[~2026-09-02 13:18 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-02 13:17 [RFC 0/3] " Tom de Vries
2026-09-02 13:17 ` Tom de Vries [this message]
2026-09-02 13:17 ` [RFC 2/3] [pre-commit] Enable shfmt Tom de Vries
2026-09-02 13:17 ` [RFC 3/3] [gdb/contrib] Use shfmt --simplify in shfmt.sh Tom de Vries
2026-09-15  7:26   ` Tom de Vries

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260902131739.2125928-2-tdevries@suse.de \
    --to=tdevries@suse.de \
    --cc=gdb-patches@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox