]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
tools: rewrite checkcompletion.sh to be source-based
authorKarel Zak <kzak@redhat.com>
Thu, 2 Oct 2025 12:07:53 +0000 (14:07 +0200)
committerKarel Zak <kzak@redhat.com>
Fri, 3 Oct 2025 11:25:10 +0000 (13:25 +0200)
The original checkcompletion.sh checked compiled binaries in the build
directory, which was unreliable and build-dependent. The new version
performs comprehensive source-based verification by:

1. Extracting program names from */Makemodule.am files (bin_PROGRAMS,
   sbin_PROGRAMS, usrbin_exec_PROGRAMS, usrsbin_exec_PROGRAMS)

2. Verifying three-way consistency:
   - Programs defined in Makemodule.am files
   - bash-completion files in bash-completion/ directory
   - Entries in bash-completion/Makemodule.am
   - Entries in meson.build

3. Properly handling special cases:
   - Programs that don't need completion (system tools like login, agetty)
   - Programs with special install hooks (runuser, lastb symlinks)

The script now provides clear categorized output:
- Programs missing bash-completion files
- bash-completion files not registered in Makemodule.am
- Orphaned bash-completion files without programs

This makes it easier to maintain bash-completion consistency and catch
issues before release.

Signed-off-by: Karel Zak <kzak@redhat.com>
tools/checkcompletion.sh

index f3fdda486692425f82ef5198f76822b4e791253f..58e1f7a08c78df4aef803101e8db0afb12b9810c 100755 (executable)
 #!/bin/bash
 
 #
-# This script checks if we have bash-completion scripts for the all compiled
-# binaries.
+# This script verifies bash-completion consistency by checking:
+# 1. All user-facing programs have bash-completion files
+# 2. All bash-completion files are registered in bash-completion/Makemodule.am
+# 3. All bash-completion files are registered in meson.build
+# 4. All bash-completion files correspond to actual programs
 #
-# Copyright (C) 2016 Karel Zak <kzak@redhat.com>
+# Copyright (C) 2025 Karel Zak <kzak@redhat.com>
 #
 
+set -e
 
 die() {
-       echo "error: $1"
+       echo "error: $1" >&2
        exit 1
 }
 
 usage() {
-       echo "Usage:"
-       echo " $0 [<top_srcdir>]"
+       echo "Usage: $0 [<top_srcdir>]"
+       echo
+       echo "Verifies bash-completion consistency across:"
+       echo "  - Program definitions in */Makemodule.am"
+       echo "  - bash-completion/ directory contents"
+       echo "  - bash-completion/Makemodule.am registrations"
+       echo "  - meson.build registrations"
+       exit 1
 }
 
-# unwanted scripts -- use grep -E, e.g. (aaa|bbb|ccc)
-completion_exclude="(nologin)"
+# Programs that don't need bash completion:
+# - nologin: no interactive use
+# - agetty: terminal setup, no user interaction
+# - login: authentication, no command-line arguments
+# - sulogin: emergency login, no arguments
+# - switch_root: initramfs utility, internal use
+# - vipw: wrapper around editor
+# - line: deprecated, simple utility
+# - kill: conflicts with bash built-in kill command
+exclude_programs="nologin|agetty|login|sulogin|switch_root|vipw|line|kill"
+
+# Programs with special handling in bash-completion/Makemodule.am (symlinks/aliases)
+# These are handled via install-data-hook-bashcomp-* rules
+# - runuser: symlinked to su completion
+# - lastb: symlinked to last completion
+special_handling="runuser|lastb"
+
+top_srcdir=${1:-.}
+[ -d "${top_srcdir}" ] || die "directory '${top_srcdir}' not found"
 
-top_srcdir=${1-"."}
-completion_dir="${top_srcdir}/bash-completion"
+cd "${top_srcdir}" || die "cannot cd to ${top_srcdir}"
 
+completion_dir="bash-completion"
 [ -d "${completion_dir}" ] || die "not found ${completion_dir}"
 
-bin_files=$(cd ${top_srcdir} && find * -maxdepth 0 -perm /u+x \
-               \! -type d \
-               \! -name \*.sh \! -name \*.cache \! -name \*.status \
-               \! -name configure \! -name libtool | sort)
+# Extract all user-facing programs from Makemodule.am files
+# We look for: bin_PROGRAMS, sbin_PROGRAMS, usrbin_exec_PROGRAMS, usrsbin_exec_PROGRAMS
+extract_programs() {
+       find . -name "Makemodule.am" -type f -exec grep -h \
+               -E "^(bin|sbin|usrbin_exec|usrsbin_exec)_PROGRAMS \+=" {} \; \
+               | sed 's/.*+= *//' \
+               | tr ' ' '\n' \
+               | sed 's/\\//' \
+               | grep -v '^$' \
+               | grep -v '\.static$' \
+               | sort -u
+}
+
+# Extract programs from bash-completion/Makemodule.am
+extract_completion_registered() {
+       grep 'bash-completion/' "${completion_dir}/Makemodule.am" \
+               | sed -e 's/.*bash-completion\///' \
+                     -e 's/\s.*//' \
+               | sort -u
+}
+
+# Get actual bash-completion files
+get_completion_files() {
+       ls "${completion_dir}" \
+               | grep -v '^Makemodule.am$' \
+               | sort
+}
+
+# Extract programs from meson.build
+extract_meson_registered() {
+       if [ -f "meson.build" ]; then
+               grep "bashcompletions +=" meson.build \
+                       | sed -e "s/.*bashcompletions += //" \
+                             -e "s/\[//" \
+                             -e "s/\]//" \
+                             -e "s/'//g" \
+                       | tr ',' '\n' \
+                       | sed -e 's/^ *//' \
+                             -e 's/ *$//' \
+                       | grep -v '^$' \
+                       | sort -u
+       fi
+}
+
+# Get programs that should have completions
+programs=$(extract_programs | grep -v -w -E "(${exclude_programs}|${special_handling})")
+
+# Get registered completions
+registered=$(extract_completion_registered)
 
-completion_files=$(cd ${completion_dir}/ && find * ! -name '*.am' | sort -u)
-completion_missing=$(comm -3 <(echo "$completion_files") <(echo "$bin_files"))
+# Get meson registered completions
+meson_registered=$(extract_meson_registered)
 
-if [ -n "$completion_missing" -a -n "$completion_exclude" ]; then
-       completion_missing=$(echo "$completion_missing" | grep -v -E "$completion_exclude")
+# Get actual completion files
+files=$(get_completion_files)
+
+# Find programs without completion files
+missing_files=$(comm -23 <(echo "$programs") <(echo "$files"))
+
+# Find completion files not registered in Makemodule.am
+unregistered=$(comm -23 <(echo "$files") <(echo "$registered"))
+
+# Find completion files without corresponding programs
+orphaned=$(comm -23 <(echo "$files") <(echo "$programs"))
+
+# Find completion files not registered in meson.build
+meson_unregistered=$(comm -23 <(echo "$files") <(echo "$meson_registered"))
+
+# Report findings
+errors=0
+
+if [ -n "$missing_files" ]; then
+       echo "Programs missing bash-completion files:"
+       echo "$missing_files" | sed 's/^/  /'
+       errors=$((errors + 1))
 fi
 
-if [ -n "$completion_missing" ]; then
-       echo "Missing completion scripts:"
-       echo "$completion_missing"
+if [ -n "$unregistered" ]; then
+       echo "bash-completion files not registered in bash-completion/Makemodule.am:"
+       echo "$unregistered" | sed 's/^/  /'
+       errors=$((errors + 1))
 fi
 
+if [ -n "$orphaned" ]; then
+       echo "bash-completion files without corresponding programs:"
+       echo "$orphaned" | sed 's/^/  /'
+       errors=$((errors + 1))
+fi
+
+if [ -n "$meson_unregistered" ]; then
+       echo "bash-completion files not registered in meson.build:"
+       echo "$meson_unregistered" | sed 's/^/  /'
+       errors=$((errors + 1))
+fi
+
+if [ $errors -eq 0 ]; then
+       echo "All bash-completion files are consistent."
+       exit 0
+else
+       exit 1
+fi