doc: check well-formedness of delimited sections

Having an empty line before each delimited sections is not required by asciidoc, but it is a safety measure that prevents generating malformed asciidoc when generating translated documentation. When a delimited section appears just after a paragraph, the asciidoc processor checks that the length of the delimited section header is different from the length of the paragraph. If it is not, the asciidoc processor will generate a title. In the original English documentation, this is not a problem because the authors always check the output of the asciidoc processor and fix the length of the delimited section header if it turns out to be the same as the paragraph length. However, this is not the case for translations, where the authors have no way to check the length of the delimited section header or the output of the asciidoc processor. This can lead to a section title that is not intended. Indeed, this test also checks that titles are correctly formed, that is, the length of the underline is equal to the length of the title (otherwise it would not be a title but a section header). Finally, this test checks that the delimited section are terminated within the same file. Signed-off-by: Jean-Noël Avila <jn.avila@free.fr> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jean-Noël Avila committed Aug 11, 2025 at 20:53 UTC 63d33eb7f6ba315c3ecdda63295d9f915d184fcd
14 files changed +80 -4
Documentation/Makefile
+10 -1
@@ -497,9 +497,17 @@ $(LINT_DOCS_FSCK_MSGIDS): ../fsck.h fsck-msgids.adoc
497 $(call mkdir_p_parent_template)
498 $(QUIET_GEN)$(PERL_PATH) lint-fsck-msgids.perl \
499 ../fsck.h fsck-msgids.adoc $@
500 -
500 lint-docs-fsck-msgids: $(LINT_DOCS_FSCK_MSGIDS)
501
502 +## Lint: delimited sections
503 +LINT_DOCS_DELIMITED_SECTIONS = $(patsubst %.adoc,.build/lint-docs/delimited-sections/%.ok,$(MAN_TXT))
504 +$(LINT_DOCS_DELIMITED_SECTIONS): lint-delimited-sections.perl
505 +$(LINT_DOCS_DELIMITED_SECTIONS): .build/lint-docs/delimited-sections/%.ok: %.adoc
506 + $(call mkdir_p_parent_template)
507 + $(QUIET_LINT_DELIMSEC)$(PERL_PATH) lint-delimited-sections.perl $< >$@
508 +.PHONY: lint-docs-delimited-sections
509 +lint-docs-delimited-sections: $(LINT_DOCS_DELIMITED_SECTIONS)
510 +
511 lint-docs-manpages:
512 $(QUIET_GEN)./lint-manpages.sh
513
@@ -528,6 +536,7 @@ lint-docs: lint-docs-fsck-msgids
536 lint-docs: lint-docs-gitlink
537 lint-docs: lint-docs-man-end-blurb
538 lint-docs: lint-docs-man-section-order
539 +lint-docs: lint-docs-delimited-sections
540 lint-docs: lint-docs-manpages
541 lint-docs: lint-docs-meson
542
Documentation/RelNotes/1.6.2.4.adoc
+1
@@ -37,3 +37,4 @@ exec >/var/tmp/1
37 echo O=$(git describe maint)
38 O=v1.6.2.3-38-g318b847
39 git shortlog --no-merges $O..maint
40 +---
Documentation/diff-format.adoc
+1
@@ -103,6 +103,7 @@ if the file was renamed on any side of history. With
103 followed by the name of the path in the merge commit.
104
105 Examples for `-c` and `--cc` without `--combined-all-paths`:
106 +
107 ------------------------------------------------
108 ::100644 100644 100644 fabadb8 cc95eb0 4866510 MM desc.c
109 ::100755 100755 100755 52b7a2d 6d1ac04 d2ac7d7 RM bar.sh
Documentation/git-commit.adoc
+1
@@ -281,6 +281,7 @@ variable (see linkgit:git-config[1]).
281 +
282 --
283 It is a rough equivalent for:
284 +
285 ------
286 $ git reset --soft HEAD^
287 $ ... do something else to come up with the right tree ...
Documentation/git-fast-import.adoc
+2
@@ -605,9 +605,11 @@ Marks must be declared (via `mark`) before they can be used.
605
606 The special case of restarting an incremental import from the
607 current branch value should be written as:
608 +
609 ----
610 from refs/heads/branch^0
611 ----
612 +
613 The `^0` suffix is necessary as fast-import does not permit a branch to
614 start from itself, and the branch is created in memory before the
615 `from` command is even read from the input. Adding `^0` will force
Documentation/git-p4.adoc
+1
@@ -66,6 +66,7 @@ Clone
66 ~~~~~
67 Generally, 'git p4 clone' is used to create a new Git directory
68 from an existing p4 repository:
69 +
70 ------------
71 $ git p4 clone //depot/path/project
72 ------------
Documentation/git-rebase.adoc
+1 -1
@@ -687,7 +687,7 @@ In addition, the following pairs of options are incompatible:
687 * --fork-point and --root
688
689 BEHAVIORAL DIFFERENCES
690 ------------------------
690 +----------------------
691
692 `git rebase` has two primary backends: 'apply' and 'merge'. (The 'apply'
693 backend used to be known as the 'am' backend, but the name led to
Documentation/git-svn.adoc
+2
@@ -1012,9 +1012,11 @@ branch.
1012
1013 If you do merge, note the following rule: 'git svn dcommit' will
1014 attempt to commit on top of the SVN commit named in
1015 +
1016 ------------------------------------------------------------------------
1017 git log --grep=^git-svn-id: --first-parent -1
1018 ------------------------------------------------------------------------
1019 +
1020 You 'must' therefore ensure that the most recent commit of the branch
1021 you want to dcommit to is the 'first' parent of the merge. Chaos will
1022 ensue otherwise, especially if the first parent is an older commit on
Documentation/gitprotocol-http.adoc
+1 -1
@@ -318,7 +318,7 @@ Extra Parameter.
318
319
320 Smart Service git-upload-pack
321 -------------------------------
321 +-----------------------------
322 This service reads from the repository pointed to by `$GIT_URL`.
323
324 Clients MUST first perform ref discovery with
Documentation/gitsubmodules.adoc
+2 -1
@@ -8,6 +8,7 @@ gitsubmodules - Mounting one repository inside another
8 SYNOPSIS
9 --------
10 .gitmodules, $GIT_DIR/config
11 +
12 ------------------
13 git submodule
14 git <command> --recurse-submodules
@@ -240,7 +241,7 @@ Workflow for a third party library
241
242
243 Workflow for an artificially split repo
243 ---------------------------------------
244 +---------------------------------------
245
246 # Enable recursion for relevant commands, such that
247 # regular commands recurse into submodules by default
Documentation/lint-delimited-sections.perl new
+48
@@ -0,0 +1,48 @@
1 +#!/usr/bin/perl
2 +
3 +use strict;
4 +use warnings;
5 +
6 +my $exit_code = 0;
7 +sub report {
8 + my ($msg) = @_;
9 + print STDERR "$ARGV:$.: $msg\n";
10 + $exit_code = 1;
11 +}
12 +
13 +my $line_length = 0;
14 +my $in_section = 0;
15 +my $section_header = "";
16 +
17 +
18 +while (my $line = <>) {
19 + if (($line =~ /^\+?$/) ||
20 + ($line =~ /^\[.*\]$/) ||
21 + ($line =~ /^ifdef::/)) {
22 + $line_length = 0;
23 + } elsif ($line =~ /^[^-.]/) {
24 + $line_length = length($line);
25 + } elsif (($line =~ /^-{3,}$/) || ($line =~ /^\.{3,}$/)) {
26 + if ($in_section) {
27 + if ($line eq $section_header) {
28 + $in_section = 0;
29 + }
30 + next;
31 + }
32 + if ($line_length == 0) {
33 + $in_section = 1;
34 + $section_header = $line;
35 + next;
36 + }
37 + if (($line_length != 0) && (length($line) != $line_length)) {
38 + report("section delimiter not preceded by an empty line");
39 + }
40 + $line_length = 0;
41 + }
42 +}
43 +
44 +if ($in_section) {
45 + report("section not finished");
46 +}
47 +
48 +exit $exit_code;
Documentation/mergetools/vimdiff.adoc
+8
@@ -3,6 +3,7 @@ Description
3
4 When specifying `--tool=vimdiff` in `git mergetool` Git will open Vim with a 4
5 windows layout distributed in the following way:
6 +
7 ....
8 ------------------------------------------
9 | | | |
@@ -56,6 +57,7 @@ needed in this case. The next layout definition is equivalent:
57 +
58 --
59 If, for some reason, we are not interested in the `BASE` buffer.
60 +
61 ....
62 ------------------------------------------
63 | | | |
@@ -72,6 +74,7 @@ If, for some reason, we are not interested in the `BASE` buffer.
74 Only the `MERGED` buffer will be shown. Note, however, that all the other
75 ones are still loaded in vim, and you can access them with the "buffers"
76 command.
77 +
78 ....
79 ------------------------------------------
80 | |
@@ -88,6 +91,7 @@ command.
91 When `MERGED` is not present in the layout, you must "mark" one of the
92 buffers with an arobase (`@`). That will become the buffer you need to edit and
93 save after resolving the conflicts.
94 +
95 ....
96 ------------------------------------------
97 | | |
@@ -106,6 +110,7 @@ save after resolving the conflicts.
110 Three tabs will open: the first one is a copy of the default layout, while
111 the other two only show the differences between (`BASE` and `LOCAL`) and
112 (`BASE` and `REMOTE`) respectively.
113 +
114 ....
115 ------------------------------------------
116 | <TAB #1> | TAB #2 | TAB #3 | |
@@ -119,6 +124,7 @@ the other two only show the differences between (`BASE` and `LOCAL`) and
124 | |
125 ------------------------------------------
126 ....
127 +
128 ....
129 ------------------------------------------
130 | TAB #1 | <TAB #2> | TAB #3 | |
@@ -132,6 +138,7 @@ the other two only show the differences between (`BASE` and `LOCAL`) and
138 | | |
139 ------------------------------------------
140 ....
141 +
142 ....
143 ------------------------------------------
144 | TAB #1 | TAB #2 | <TAB #3> | |
@@ -151,6 +158,7 @@ the other two only show the differences between (`BASE` and `LOCAL`) and
158 --
159 Same as the previous example, but adds a fourth tab with the same
160 information as the first tab, with a different layout.
161 +
162 ....
163 ---------------------------------------------
164 | TAB #1 | TAB #2 | TAB #3 | <TAB #4> |
Documentation/technical/long-running-process-protocol.adoc
+1
@@ -24,6 +24,7 @@ After the version negotiation Git sends a list of all capabilities that
24 it supports and a flush packet. Git expects to read a list of desired
25 capabilities, which must be a subset of the supported capabilities list,
26 and a flush packet as response:
27 +
28 ------------------------
29 packet: git> git-filter-client
30 packet: git> version=2
shared.mak
+1
@@ -88,6 +88,7 @@ ifndef V
88
89 QUIET_LINT_GITLINK = @echo ' ' LINT GITLINK $<;
90 QUIET_LINT_MANSEC = @echo ' ' LINT MAN SEC $<;
91 + QUIET_LINT_DELIMSEC = @echo ' ' LINT DEL SEC $<;
92 QUIET_LINT_MANEND = @echo ' ' LINT MAN END $<;
93
94 export V