[FIX] systemd: every man page operation at once, not one per pass

mv: cannot stat '<pkgdir>/usr/share/man/man3': No such file or directory

Fifteenth instance, and the first where the whole class was handled before the
failures arrived. -Dman=disabled means NO man pages exist, and package() touches
them six times -- three moves into split packages, three removals of pages Arch
does not ship.

Treated by kind rather than by name: the moves are neutralised, because with no
pages there is nothing to move; the removals get -f, because their intent still
holds on a machine that HAS the DocBook stack, and one of them also removes a
binary that must still go. Five moves, three removals, counted and reported by
the hook.

This is the procedure written into jsoncpp's hook one commit earlier, applied
forwards: after disabling documentation, grep package() for the output paths.
Chasing man3 alone would have cost five more passes.

The first guard for it matched any `rm` without a dash and condemned correct
code -- systemd removes plenty that is not documentation. Same mistake as the
blanket `grep tcl8.6` in sqlite's hook, and caught the same way.

--- FR ---

  mv: cannot stat '<pkgdir>/usr/share/man/man3': No such file or directory

Quinzième occurrence, et la première où toute la classe est traitée avant que les
échecs n'arrivent. -Dman=disabled signifie qu'AUCUNE page n'existe, et package()
y touche six fois — trois déplacements vers des sous-paquets, trois suppressions
de pages qu'Arch ne livre pas.

Traitées par nature et non par nom : les déplacements sont neutralisés, puisqu'il
n'y a rien à déplacer ; les suppressions reçoivent -f, car leur intention tient
toujours sur une machine dotée de la pile DocBook, et l'une retire aussi un
binaire qui doit bien partir. Cinq déplacements, trois suppressions, comptés et
rapportés par le hook.

C'est la procédure inscrite dans le hook de jsoncpp un commit plus tôt, appliquée
à l'endroit : après avoir désactivé une documentation, chercher dans package() les
chemins de sortie. Poursuivre man3 seul aurait coûté cinq passes de plus.

Le premier garde écrit pour cela attrapait tout `rm` sans tiret et condamnait du
code juste — systemd supprime beaucoup qui n'est pas de la documentation. Même
erreur que le `grep tcl8.6` global du hook sqlite, attrapée de la même façon.

Assisted-by: Claude Opus 5
This commit is contained in:
Mathieu Benoit 2026-08-24 00:21:48 -04:00
parent 376c6d6a91
commit 61abc5aef9

View file

@ -309,3 +309,62 @@ io.open("PKGBUILD", "w", encoding="utf-8").write(s)
ZZPY ZZPY
grep -q -- "-Dman=disabled" PKGBUILD || { echo "systemd: man not disabled" >&2; exit 1; } grep -q -- "-Dman=disabled" PKGBUILD || { echo "systemd: man not disabled" >&2; exit 1; }
echo "systemd: man pages disabled (DocBook stylesheets absent, not xsltproc)" echo "systemd: man pages disabled (DocBook stylesheets absent, not xsltproc)"
# --- and every man page operation in package() --------------------------------
#
# mv: cannot stat '<pkgdir>/usr/share/man/man3': No such file or directory
#
# FIFTEENTH time, and the first where the whole class was handled at once instead
# of one path per pass. -Dman=disabled means NO man pages exist, and package()
# touches them six times:
#
# mv .../man/man3 systemd-libs/man3
# mv .../man/man8/*nss* systemd-libs/man8/
# mv .../man/man1/ukify.1 systemd-ukify/man1/
# rm .../man/man1/init.1
# rm .../man/man8/{halt,poweroff,reboot,shutdown}.8
# rm .../usr/{bin/resolvconf,share/man/man1/resolvconf.1}
#
# Treated by KIND rather than by name:
#
# mv -- neutralised. These move pages into split packages, and with no pages
# there is nothing to move and the split simply has no man section.
# rm -- made tolerant with -f. These delete pages Arch does not want shipped,
# and that intent still holds on a machine that HAS the DocBook stack.
# The last one also removes a binary, which must still go.
#
# This is the procedure written in jsoncpp's hook, applied before the failures
# arrive rather than after: grep package() for the output paths, not the tool.
set -euo pipefail
python3 - <<'ZZPY'
import io, re
lines = io.open("PKGBUILD", encoding="utf-8").read().split("\n")
mv_n = rm_n = 0
for i in range(len(lines) - 1, -1, -1):
l = lines[i]
if "share/man" not in l and not re.search(r"\bman[0-9]\b", l):
continue
if re.match(r"^[ \t]*mv ", l):
j = i
while lines[j].rstrip().endswith("\\"):
j += 1
ind = re.match(r"^[ \t]*", l).group(0)
lines[i:j + 1] = [ind + ": # no man pages are built: -Dman=disabled above."]
mv_n += 1
elif re.match(r"^[ \t]*rm ", l) and not re.match(r"^[ \t]*rm -[a-z]*f", l):
lines[i] = re.sub(r"^([ \t]*)rm ", r"\1rm -f ", l)
rm_n += 1
assert mv_n >= 1, "systemd: no man page moves found"
assert rm_n >= 1, "systemd: no man page removals found"
io.open("PKGBUILD", "w", encoding="utf-8").write("\n".join(lines))
print(" %d move(s) neutralised, %d removal(s) made tolerant" % (mv_n, rm_n))
ZZPY
grep -qE "^[[:space:]]*mv .*(share/man|\bman[0-9]\b)" PKGBUILD && {
echo "systemd: a man page move survived" >&2; exit 1; }
# Scoped to man paths. The first version of this guard matched any `rm` without
# a dash and condemned correct code -- systemd's package() removes plenty of
# things that have nothing to do with documentation. Same mistake as the blanket
# `grep tcl8.6` in sqlite's hook: a check must ask about what it changed.
grep -qE "^[[:space:]]*rm [^-].*(share/man|\bman[0-9]\b)" PKGBUILD && {
echo "systemd: an intolerant rm of a man path survived" >&2; exit 1; }
echo "systemd: all man page operations handled"