File: man-page-table-check

package info (click to toggle)
podman 5.7.0%2Bds2-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 23,824 kB
  • sloc: sh: 4,700; python: 2,798; perl: 1,885; ansic: 1,484; makefile: 977; ruby: 42; csh: 8
file content (176 lines) | stat: -rwxr-xr-x 4,897 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
#!/usr/bin/perl
#
# man-page-table-check - workaround for go-md2man bug that screws up tables
#
package Podman::ManPage::TableCheck;

use v5.14;
use utf8;

use strict;
use warnings;

(our $ME = $0) =~ s|.*/||;

###############################################################################
# BEGIN boilerplate args checking, usage messages

sub usage {
    print  <<"END_USAGE";
Usage: $ME [OPTIONS]

$ME checks man pages (the *roff files produced
by go-md2man) for empty table cells. Reason: go-md2man cannot handle
markdown characters (e.g. asterisk) in tables. It produces horribly
broken *roff which in turn makes unreadable man pages.

If $ME finds broken tables, it will highlight them
and display hints on how to resolve the problem.

OPTIONS:
  --help         display this message
END_USAGE

    exit;
}

# Command-line options.  Note that this operates directly on @ARGV !
our $debug   = 0;
our $force   = 0;
our $verbose = 0;
our $NOT     = '';              # print "blahing the blah$NOT\n" if $debug
sub handle_opts {
    use Getopt::Long;
    GetOptions(
        'debug!'     => \$debug,

        help         => \&usage,
    ) or die "Try `$ME --help' for help\n";
}

# END   boilerplate args checking, usage messages
###############################################################################

############################## CODE BEGINS HERE ###############################

# The term is "modulino".
__PACKAGE__->main()                                     unless caller();

# Main code.
sub main {
    # Note that we operate directly on @ARGV, not on function parameters.
    # This is deliberate: it's because Getopt::Long only operates on @ARGV
    # and there's no clean way to make it use @_.
    handle_opts();                      # will set package globals

    die "$ME: Too many arguments; try $ME --help\n"                 if @ARGV;

    my $manpage_dir = 'docs/build/man';         # FIXME-hardcoding
    opendir my $dir_fh, $manpage_dir
        or die "$ME: Cannot opendir $manpage_dir: $!\n";
    my @manpages;
    for my $ent (sort readdir $dir_fh) {
        next unless $ent =~ /^[a-z].*\.[1-8][a-z]?$/;   # groff files only
        next if -l "$manpage_dir/$ent";                 # skip links
        push @manpages, $ent;
    }
    closedir $dir_fh;

    @manpages
        or die "$ME: did not find any .[1-8] files under $manpage_dir\n";

    my $errs = 0;
    for my $file (@manpages) {
        $errs += check_tables("$manpage_dir/$file");
    }
    exit 0 if !$errs;

    die "\n$ME: found empty cells in the above man page(s)

This is a bug in go-md2man: it gets really confused when it sees
misaligned vertical-bar signs ('|') in tables, or a left-hand
column with more than 31 characters.

WORKAROUND: find the above line(s) in the docs/source/markdown file,
then fix the issue (left as exercise for the reader). Keep regenerating
docs until it passes:

    \$ make -C docs clean;make docs;$0
"
}


sub check_tables {
    my $path = shift;

    my $status = 0;

    my @cmd = ('man', '-l', '--no-hyphenation', '-Tlatin1', '-');
    pipe my $fh_read, my $fh_write;
    my $kidpid = fork;
    if ($kidpid) {                      # we are the parent
        close $fh_write;
    }
    elsif (defined $kidpid) {           # we are the child
        close $fh_read;

        open my $fh_in, '<:utf8', $path
            or die "$ME: Could not read $path: $!\n";
        # groff spits out nasty useless warnings
        close STDERR;
        open STDOUT, '>&', $fh_write;
        open my $fh_man, '|-', @cmd
            or die "$ME: Could not fork: $! (message will never be seen)\n";

        while (my $line = <$fh_in>) {
            $line =~ s/✅/OK/g;
            print { $fh_man } $line;
        }
        close $fh_in or die;
        close $fh_man or die;
        exit 0;
    }
    else {                              # fork failed
        die "$ME: could not fork: $!";
    }

    my $linecount = 0;
    my $want = 0;
    while (my $line = <$fh_read>) {
        ++$linecount;

        chomp $line;
        # Table borders (+----------+------------+)
        if ($line =~ /^\s*\+-+\+-+/) {
            $want = 1;
            next;
        }

        # Row immediately after table borders
        elsif ($want) {
#            print $line, "\n";
            # *Two* blank cells is OK, go-md2man always does this
            # on the last row of each table.
            if ($line !~ /^\s*\|\s+\|\s+\|/) {
                if ($line =~ /\|\s+\|/) {
                    warn "\n$ME: $path:\n"         if $status == 0;
                    warn "   $line\n";
                    $status = 1;
                }
            }
        }
        $want = 0;
    }
    close $fh_read;
    die "$ME: $path: command failed: @cmd\n"    if $?;
    waitpid $kidpid, 0;

    if ($linecount < 10) {
        die "$ME: $path: nothing seen!\n";
    }

    return $status;
}


1;