forked from heavy-duty/ceremony
fix(changelog): one fragment, one diagnosis, wherever the long entry sits
awk runs END on the way out of an exit from a main rule, so the length row printed mid-file was followed by the citation row it outranks — the internal protocol line landing inside the human-facing excerpt. Found by claude-bot and kimi-bot in #262's first round, independently and with the same reproduction. The guard is the reported flag the empty-heading walk in this same predicate already uses. The fixtures are the axis 57.md could not reach: its over-bound entry is last, so only END's flush can print. 58.md puts one before another bullet, 59.md before a heading and after a misplaced cite. With lib/changelog.sh alone reverted they red, which is what the green suite was hiding. Refs #262.
This commit is contained in:
parent
84c73fe22e
commit
75a5b68c8a
3 changed files with 42 additions and 4 deletions
|
|
@ -7,6 +7,9 @@
|
||||||
- The refusal distinguishes an entry carrying no reference at all from one
|
- The refusal distinguishes an entry carrying no reference at all from one
|
||||||
whose reference is present but not terminal, and names the shape to
|
whose reference is present but not terminal, and names the shape to
|
||||||
write in both (#262).
|
write in both (#262).
|
||||||
|
- The 300-character bound still outranks the citation across the whole
|
||||||
|
fragment, and the outranked problem stays out of the message it lost
|
||||||
|
to: one fragment, one diagnosis, wherever in the file it sits (#262).
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -208,6 +208,7 @@ changelog_fragment_problem() {
|
||||||
sub(/ $/, "", e)
|
sub(/ $/, "", e)
|
||||||
len = length(e)
|
len = length(e)
|
||||||
if (len > max) {
|
if (len > max) {
|
||||||
|
reported = 1
|
||||||
printf "long\t%d\t%s\n", len, excerpt(e)
|
printf "long\t%d\t%s\n", len, excerpt(e)
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
@ -227,9 +228,15 @@ changelog_fragment_problem() {
|
||||||
}
|
}
|
||||||
/^[[:space:]]*$/ { next }
|
/^[[:space:]]*$/ { next }
|
||||||
entry != "" { entry = entry " " $0 }
|
entry != "" { entry = entry " " $0 }
|
||||||
|
# An exit from a main rule still runs END, so a length row printed
|
||||||
|
# mid-file would be followed by the citation row it outranks — two
|
||||||
|
# lines spliced into one diagnosis, the internal protocol row landing
|
||||||
|
# inside the human-facing excerpt (#262 round 1). The reported flag is
|
||||||
|
# the same guard the empty-heading walk above uses, for the same
|
||||||
|
# reason: one diagnosis per fragment is the contract.
|
||||||
END {
|
END {
|
||||||
if (flush()) exit
|
if (flush()) exit
|
||||||
if (cite_kind != "") printf "%s\t\t%s\n", cite_kind, cite_excerpt
|
if (!reported && cite_kind != "") printf "%s\t\t%s\n", cite_kind, cite_excerpt
|
||||||
}
|
}
|
||||||
' "$file"
|
' "$file"
|
||||||
)"
|
)"
|
||||||
|
|
|
||||||
|
|
@ -420,16 +420,44 @@ check "cite: the reference need not match the filename" 0 "" \
|
||||||
check "cite: an over-bound entry outranks an earlier uncited one" 1 \
|
check "cite: an over-bound entry outranks an earlier uncited one" 1 \
|
||||||
"57.md' has a 301-character entry" \
|
"57.md' has a 301-character entry" \
|
||||||
changelog_fragment_problem "$PF/57.md"
|
changelog_fragment_problem "$PF/57.md"
|
||||||
assert_one_diagnosis_57() {
|
assert_one_diagnosis() {
|
||||||
local count
|
local count
|
||||||
count="$(changelog_fragment_problem "$PF/57.md" | wc -l)"
|
count="$(changelog_fragment_problem "$PF/$1.md" | wc -l)"
|
||||||
[ "$count" = 1 ] || {
|
[ "$count" = 1 ] || {
|
||||||
printf 'wanted one diagnosis, got %s\n' "$count"
|
printf 'wanted one diagnosis, got %s\n' "$count"
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
check "cite: the outranked citation problem is not reported beside it" 0 "" \
|
check "cite: the outranked citation problem is not reported beside it" 0 "" \
|
||||||
assert_one_diagnosis_57
|
assert_one_diagnosis 57
|
||||||
|
|
||||||
|
# The axis 57.md cannot test: its over-bound entry is LAST, so the only
|
||||||
|
# flush that can print is END's, which exits immediately. A flush from a
|
||||||
|
# main rule exits too — but awk runs END on the way out, so the citation
|
||||||
|
# row a mid-file length row outranks would print after it unless END is
|
||||||
|
# guarded. Both ways out of the walk, a bullet and a heading.
|
||||||
|
{
|
||||||
|
printf -- '- Uncited, and it comes first.\n'
|
||||||
|
printf -- '- %s\n' "$(mkchars 301)"
|
||||||
|
printf -- '- A later entry the walk never reaches (#57).\n'
|
||||||
|
} >"$PF/58.md"
|
||||||
|
check "cite: an over-bound entry that is not the last one still reports the bound" 1 \
|
||||||
|
"58.md' has a 301-character entry" \
|
||||||
|
changelog_fragment_problem "$PF/58.md"
|
||||||
|
check "cite: and it is still one diagnosis, not the protocol row spliced into it" 0 "" \
|
||||||
|
assert_one_diagnosis 58
|
||||||
|
{
|
||||||
|
printf '### Fixed\n'
|
||||||
|
printf -- '- Misplaced, and it comes first. (#59)\n'
|
||||||
|
printf -- '- %s\n' "$(mkchars 301)"
|
||||||
|
printf '### Changed\n'
|
||||||
|
printf -- '- The heading is the other way out of the walk (#59).\n'
|
||||||
|
} >"$PF/59.md"
|
||||||
|
check "cite: a heading after the over-bound entry is the same one diagnosis" 1 \
|
||||||
|
"59.md' has a 301-character entry" \
|
||||||
|
changelog_fragment_problem "$PF/59.md"
|
||||||
|
check "cite: the misplaced row does not ride along with it either" 0 "" \
|
||||||
|
assert_one_diagnosis 59
|
||||||
|
|
||||||
# Published sections keep their pre-rule prose (D4): reddening history is a
|
# Published sections keep their pre-rule prose (D4): reddening history is a
|
||||||
# wall, not a guard. Every shipped section predates the cite.
|
# wall, not a guard. Every shipped section predates the cite.
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue