summaryrefslogtreecommitdiff
path: root/Documentation
diff options
context:
space:
mode:
Diffstat (limited to 'Documentation')
-rw-r--r--Documentation/Makefile3
-rwxr-xr-xDocumentation/lint-man-section-order.perl125
2 files changed, 127 insertions, 1 deletions
diff --git a/Documentation/Makefile b/Documentation/Makefile
index 34b4f5716a..5e0828869b 100644
--- a/Documentation/Makefile
+++ b/Documentation/Makefile
@@ -483,7 +483,8 @@ lint-docs::
--section=1 $(MAN1_TXT) \
--section=5 $(MAN5_TXT) \
--section=7 $(MAN7_TXT); \
- $(PERL_PATH) lint-man-end-blurb.perl $(MAN_TXT)
+ $(PERL_PATH) lint-man-end-blurb.perl $(MAN_TXT); \
+ $(PERL_PATH) lint-man-section-order.perl $(MAN_TXT);
ifeq ($(wildcard po/Makefile),po/Makefile)
doc-l10n install-l10n::
diff --git a/Documentation/lint-man-section-order.perl b/Documentation/lint-man-section-order.perl
new file mode 100755
index 0000000000..5767e7e456
--- /dev/null
+++ b/Documentation/lint-man-section-order.perl
@@ -0,0 +1,125 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+my %SECTIONS;
+{
+ my $order = 0;
+ %SECTIONS = (
+ 'NAME' => {
+ required => 1,
+ order => $order++,
+ },
+ 'SYNOPSIS' => {
+ required => 1,
+ order => $order++,
+ },
+ 'DESCRIPTION' => {
+ required => 1,
+ order => $order++,
+ bad => {
+ 'git-mktag.txt' => 'OPTIONS',
+ 'git-cvsserver.txt' => 'OPTIONS',
+ },
+ },
+ 'OPTIONS' => {
+ order => $order++,
+ required => 0,
+ bad => {
+ 'git-grep.txt' => 'CONFIGURATION',
+ 'git-rebase.txt' => 'CONFIGURATION',
+ },
+ },
+ 'CONFIGURATION' => {
+ order => $order++,
+ bad => {
+ 'git-svn.txt' => 'BUGS',
+ },
+ },
+ 'BUGS' => {
+ order => $order++,
+ },
+ 'SEE ALSO' => {
+ order => $order++,
+ },
+ 'GIT' => {
+ required => 1,
+ order => $order++,
+ },
+ );
+}
+my $SECTION_RX = do {
+ my ($names) = join "|", keys %SECTIONS;
+ qr/^($names)$/s;
+};
+
+my $exit_code = 0;
+sub report {
+ my ($msg) = @_;
+ print "$ARGV:$.: $msg\n";
+ $exit_code = 1;
+}
+
+my $last_was_section;
+my @actual_order;
+while (my $line = <>) {
+ chomp $line;
+ if ($line =~ $SECTION_RX) {
+ push @actual_order => $line;
+ $last_was_section = 1;
+ # Have no "last" section yet, processing NAME
+ next if @actual_order == 1;
+
+ my @expected_order = sort {
+ $SECTIONS{$a}->{order} <=> $SECTIONS{$b}->{order}
+ } @actual_order;
+
+ my $expected_last = $expected_order[-2];
+ my $actual_last = $actual_order[-2];
+ my $except_last = $SECTIONS{$line}->{bad}->{$ARGV} || '';
+ if (($SECTIONS{$line}->{bad}->{$ARGV} || '') eq $actual_last) {
+ # Either we're whitelisted, or ...
+ next
+ } elsif (exists $SECTIONS{$actual_last}->{bad}->{$ARGV}) {
+ # ... we're complaing about the next section
+ # which is out of order because this one is,
+ # don't complain about that one.
+ next;
+ } elsif ($actual_last ne $expected_last) {
+ report("section '$line' incorrectly ordered, comes after '$actual_last'");
+ }
+ next;
+ }
+ if ($last_was_section) {
+ my $last_section = $actual_order[-1];
+ if (length $last_section ne length $line) {
+ report("dashes under '$last_section' should match its length!");
+ }
+ if ($line !~ /^-+$/) {
+ report("dashes under '$last_section' should be '-' dashes!");
+ }
+ $last_was_section = 0;
+ }
+
+ if (eof) {
+ # We have both a hash and an array to consider, for
+ # convenience
+ my %actual_sections;
+ @actual_sections{@actual_order} = ();
+
+ for my $section (sort keys %SECTIONS) {
+ next if !$SECTIONS{$section}->{required} or exists $actual_sections{$section};
+ report("has no required '$section' section!");
+ }
+
+ # Reset per-file state
+ {
+ @actual_order = ();
+ # this resets our $. for each file
+ close ARGV;
+ }
+ }
+}
+
+exit $exit_code;