podman/hack/man-page-checker
Daniel J Walsh 980b1e87d4
Switch use of Flags to Options
Want to have man pages match commands, since we have lots of printed
man pages with using Options, we will change the command line to use
Options in --help.

Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2020-10-21 08:37:57 -04:00

182 lines
6.8 KiB
Bash
Executable file

#!/usr/bin/env bash
#
# man-page-checker - validate and cross-reference man page names
#
verbose=
for i; do
case "$i" in
-v|--verbose) verbose=verbose ;;
esac
done
die() {
echo "$(basename $0): $*" >&2
exit 1
}
cd $(dirname $0)/../docs/source/markdown || die "Please run me from top-level libpod dir"
rc=0
for md in *.1.md;do
# Read the first line after '# NAME' (or '## NAME'). (FIXME: # and ##
# are not the same; should we stick to one convention?)
# There may be more than one name, e.g. podman-info.1.md has
# podman-system-info then another line with podman-info. We
# care only about the first.
name=$(egrep -A1 '^#* NAME' $md|tail -1|awk '{print $1}' | tr -d \\\\)
expect=$(basename $md .1.md)
if [ "$name" != "$expect" ]; then
echo
printf "Inconsistent program NAME in %s:\n" $md
printf " NAME= %s (expected: %s)\n" $name $expect
rc=1
fi
done
# Pass 2: compare descriptions.
#
# Make sure the descriptive text in podman-foo.1.md matches the one
# in the table in podman.1.md. podman-remote is not a podman subcommand,
# so it is excluded here.
for md in $(ls -1 *-*.1.md | grep -v remote);do
desc=$(egrep -A1 '^#* NAME' $md|tail -1|sed -e 's/^podman[^ ]\+ - //')
# podman.1.md has a two-column table; podman-*.1.md all have three.
parent=$(echo $md | sed -e 's/^\(.*\)-.*$/\1.1.md/')
if [[ $parent =~ "podman-auto" ]]; then
# podman-auto-update.1.md is special cased as it's structure differs
# from that of other man pages where main and sub-commands split by
# dashes.
parent="podman.1.md"
fi
x=3
if expr -- "$parent" : ".*-" >/dev/null; then
x=4
fi
# Find the descriptive text in the parent man page.
# Strip off the final period; let's not warn about such minutia.
parent_desc=$(grep $md $parent | awk -F'|' "{print \$$x}" | sed -e 's/^ \+//' -e 's/ \+$//' -e 's/\.$//')
if [ "$desc" != "$parent_desc" ]; then
echo
printf "Inconsistent subcommand descriptions:\n"
printf " %-32s = '%s'\n" $md "$desc"
printf " %-32s = '%s'\n" $parent "$parent_desc"
printf "Please ensure that the NAME section of $md\n"
printf "matches the subcommand description in $parent\n"
rc=1
fi
done
# Helper function: compares man page synopsis vs --help usage message
function compare_usage() {
local cmd="$1"
local from_man="$2"
# Sometimes in CI we run before podman gets built.
test -x ../../../bin/podman || return
# Run 'cmd --help', grab the line immediately after 'Usage:'
local help_output=$(../../../bin/$cmd --help)
local from_help=$(echo "$help_output" | grep -A1 '^Usage:' | tail -1)
# strip off command name from both
from_man=$(sed -e "s/\*\*$cmd\*\*[[:space:]]*//" <<<"$from_man")
from_help=$(sed -e "s/^[[:space:]]*$cmd[[:space:]]*//" <<<"$from_help")
# man page lists 'foo [*options*]', help msg shows 'foo [flags]'.
# Make sure if one has it, the other does too.
if expr "$from_man" : "\[\*options\*\]" >/dev/null; then
if expr "$from_help" : "\[options\]" >/dev/null; then
:
else
echo "WARNING: $cmd: man page shows '[*options*]', help does not show [options]"
rc=1
fi
elif expr "$from_help" : "\[flags\]" >/dev/null; then
echo "WARNING: $cmd: --help shows [flags], man page does not show [*options*]"
rc=1
fi
# Strip off options and flags; start comparing arguments
from_man=$(sed -e 's/^\[\*options\*\][[:space:]]*//' <<<"$from_man")
from_help=$(sed -e 's/^\[flags\][[:space:]]*//' <<<"$from_help")
# Args in man page are '*foo*', in --help are 'FOO'. Convert all to
# UPCASE simply because it stands out better to the eye.
from_man=$(sed -e 's/\*\([a-z-]\+\)\*/\U\1/g' <<<"$from_man")
# FIXME: one of the common patterns is for --help to show 'POD [POD...]'
# but man page show 'pod ...'. This conversion may help one day, but
# not yet: there are too many inconsistencies such as '[pod ...]'
# (brackets) and 'pod...' (no space between).
# from_help=$(sed -e 's/\([A-Z]\+\)[[:space:]]\+\[\1[[:space:]]*\.\.\.\]/\1 .../' <<<"$from_help")
# Compare man-page and --help usage strings. For now, do so only
# when run with --verbose.
if [[ "$from_man" != "$from_help" ]]; then
if [ -n "$verbose" ]; then
printf "%-25s man='%s' help='%s'\n" "$cmd:" "$from_man" "$from_help"
# Yeah, we're not going to enable this as a blocker any time soon.
# rc=1
fi
fi
}
# Pass 3: compare synopses.
#
# Make sure the SYNOPSIS line in podman-foo.1.md reads '**podman foo** ...'
for md in *.1.md;do
# FIXME: several pages have a multi-line form of SYNOPSIS in which
# many or all flags are enumerated. Some of these are trivial
# and really should be made into one line (podman-container-exists,
# container-prune, others); some are more complicated and I
# would still like to see them one-lined (container-runlabel,
# image-trust) but I'm not 100% comfortable doing so myself.
# To view those:
# $ less $(for i in docs/*.1.md;do x=$(grep -A2 '^#* SYNOPSIS' $i|tail -1); if [ -n "$x" ]; then echo $i;fi;done)
#
synopsis=$(egrep -A1 '^#* SYNOPSIS' $md|tail -1)
# Command name must be bracketed by double asterisks; options and
# arguments are bracketed by single ones.
# E.g. '**podman volume inspect** [*options*] *volume*...'
# Get the command name, and confirm that it matches the md file name.
cmd=$(echo "$synopsis" | sed -e 's/\(.*\)\*\*.*/\1/' | tr -d \*)
md_nodash=$(basename "$md" .1.md | tr '-' ' ')
if [[ $md_nodash = 'podman auto update' ]]; then
# special case: the command is "auto-update", with a hyphen
md_nodash='podman auto-update'
fi
if [ "$cmd" != "$md_nodash" -a "$cmd" != "podman-remote" ]; then
echo
printf "Inconsistent program name in SYNOPSIS in %s:\n" $md
printf " SYNOPSIS = %s (expected: '%s')\n" "$cmd" "$md_nodash"
rc=1
fi
# The convention is to use UPPER CASE in 'podman foo --help',
# but *lower case bracketed by asterisks* in the man page
if expr "$synopsis" : ".*[A-Z]" >/dev/null; then
echo
printf "Inconsistent capitalization in SYNOPSIS in %s\n" $md
printf " '%s' should not contain upper-case characters\n" "$synopsis"
rc=1
fi
# (for debugging, and getting a sense of standard conventions)
#printf " %-32s ------ '%s'\n" $md "$synopsis"
# If bin/podman is available, run "cmd --help" and compare Usage
# messages. This is complicated, so do it in a helper function.
compare_usage "$md_nodash" "$synopsis"
done
exit $rc