Subject: [bug#75501] [PATCH v3] gnu: mandoc: Support zstd-compressed man pages.

From: [email-masked]
Date: Tue, 28 Jan 2025 16:55:48 +0100

From: Sören Tempel <[email-masked]>

Since #68242 Guix uses zstd compression for man pages.  Unfortunately,
upstream mandoc only supports gzip compressed man pages.  Luckily, zstd
provides a wrapper library which easily allows adapting software using
zlib to zstd compression.  This patch uses this wrapper library in
conjunction with mandoc to add support for zstd compression to it,
thereby allowing Guix man pages to be viewed with mandoc again.

Without this patch, mandoc is essentially defunct on Guix.

* gnu/packages/man.scm (mandoc): Support zstd compression.
* gnu/local.mk: Add new patch.
* gnu/packages/patches/mandoc-support-zstd-compression.patch: New file.
---
Change since v2: Update reference to the upstream ML in the patch file.

 gnu/local.mk                                  |  1 +
 gnu/packages/man.scm                          | 54 ++++++++++------
 .../mandoc-support-zstd-compression.patch     | 63 +++++++++++++++++++
 3 files changed, 100 insertions(+), 18 deletions(-)
 create mode 100644 gnu/packages/patches/mandoc-support-zstd-compression.patch

diff --git a/gnu/local.mk b/gnu/local.mk
index 5fb354caae9..fef9a560284 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -1807,6 +1807,7 @@ dist_patch_DATA =						\
   %D%/packages/patches/lxc-no-static-bin.patch	\
   %D%/packages/patches/mactelnet-remove-init.patch		\
   %D%/packages/patches/mailutils-variable-lookup.patch		\
+  %D%/packages/patches/mandoc-support-zstd-compression.patch	\
   %D%/packages/patches/make-impure-dirs.patch			\
   %D%/packages/patches/mariadb-rocksdb-atomic-linking.patch	\
   %D%/packages/patches/mathjax-disable-webpack.patch			\
diff --git a/gnu/packages/man.scm b/gnu/packages/man.scm
index 3148fcc8a16..1ff1fac991f 100644
--- a/gnu/packages/man.scm
+++ b/gnu/packages/man.scm
@@ -37,6 +37,7 @@ (define-module (gnu packages man)
   #:use-module (guix build-system gnu)
   #:use-module (guix build-system ruby)
   #:use-module (guix utils)
+  #:use-module (gnu packages)
   #:use-module (gnu packages base)
   #:use-module (gnu packages compression)
   #:use-module (gnu packages dbm)
@@ -273,30 +274,47 @@ (define-public mandoc
               (method url-fetch)
               (uri (string-append "https://mandoc.bsd.lv/snapshots/mandoc-"
                                   version ".tar.gz"))
+              (patches (search-patches "mandoc-support-zstd-compression.patch"))
               (sha256
                (base32
                 "174x2x9ws47b14lm339j6rzm7mxy1j3qhh484khscw0yy1qdbw4b"))))
     (build-system gnu-build-system)
     (arguments
-     `(#:test-target "regress"
-       #:phases (modify-phases %standard-phases
-                  (add-before 'configure 'set-prefix
-                    (lambda* (#:key outputs #:allow-other-keys)
-                      (substitute* "configure"
-                        (("^CC=.*")
-                         (string-append "CC=" ,(cc-for-target) "\n"))
-                        (("^DEFCFLAGS=\\\\\"")
-                         "DEFCFLAGS=\"-O2 ")
-                        (("^UTF8_LOCALE=.*")      ;used for tests
-                         "UTF8_LOCALE=en_US.UTF-8\n")
-                        (("^MANPATH_(BASE|DEFAULT)=.*" _ which)
-                         (string-append "MANPATH_" which "="
-                                        "/run/current-system/profile/share/man\n"))
-                        (("^PREFIX=.*")
-                         (string-append "PREFIX=" (assoc-ref outputs "out")
-                                        "\n"))))))))
+      (list
+        #:test-target "regress"
+        #:make-flags
+        #~(list "VPATH=./zstd-src/zlibWrapper"
+                (string-join
+                  (list "CFLAGS=-DZWRAP_USE_ZSTD=1"
+                        "-I./zstd-src/zlibWrapper")
+                  " "))
+        #:phases
+        #~(modify-phases %standard-phases
+                         (add-after 'unpack 'unpack-zstd
+                           (lambda _
+                             (mkdir "zstd-src")
+                             (invoke "tar" "--strip-components=1" "-C"
+                                     "zstd-src" "-xf" #$(package-source zstd))))
+                         (add-before 'configure 'set-prefix
+                           (lambda* (#:key outputs #:allow-other-keys)
+                             (substitute*
+                               "configure"
+                               (("^CC=.*")
+                                (string-append "CC=" #$(cc-for-target) "\n"))
+                               (("^DEFCFLAGS=\\\\\"")
+                                "DEFCFLAGS=\"-O2 ")
+                               (("^UTF8_LOCALE=.*")      ;used for tests
+                                "UTF8_LOCALE=en_US.UTF-8\n")
+                               (("^MANPATH_(BASE|DEFAULT)=.*" _ which)
+                                (string-append
+                                  "MANPATH_" which "="
+                                  "/run/current-system/profile/share/man\n"))
+                               (("^PREFIX=.*")
+                                (string-append "PREFIX="
+                                               (assoc-ref outputs "out")
+                                               "\n"))))))))
     (native-inputs (list (libc-utf8-locales-for-target) perl)) ;used to run tests
-    (inputs (list zlib))
+    (inputs (list zlib (list zstd "lib")))
     (native-search-paths
      (list (search-path-specification
             (variable "MANPATH")
diff --git a/gnu/packages/patches/mandoc-support-zstd-compression.patch b/gnu/packages/patches/mandoc-support-zstd-compression.patch
new file mode 100644
index 00000000000..1c0ded56e4d
--- /dev/null
+++ b/gnu/packages/patches/mandoc-support-zstd-compression.patch
@@ -0,0 +1,63 @@
+mandoc upstream does not support zstd compression. However, Guix uses zstd
+compression for its man pages, therefore—without support for this compression
+method—mandoc would be quite useless. Hence, this patchset uses zlibWrapper
+from the zstd project to add zstd compression support to mandoc.
+
+Note that upstream is presently not interested in adding support for additional
+compression scheme, fourtunately, the patch is minimal and easy to maintain, see:
+
+	https://inbox.vuxu.org/mandoc-discuss/[email-masked]/T/#t
+
+diff -upr mandoc-1.14.6.orig/Makefile mandoc-1.14.6/Makefile
+--- mandoc-1.14.6.orig/Makefile	2025-01-11 16:20:31.511129163 +0100
++++ mandoc-1.14.6/Makefile	2025-01-11 19:16:35.924788821 +0100
+@@ -251,7 +251,12 @@ LIBMANDOC_OBJS	 = $(LIBMAN_OBJS) \
+ 		   msec.o \
+ 		   preconv.o \
+ 		   read.o \
+-		   tag.o
++		   tag.o \
++		   zstd_zlibwrapper.o \
++		   gzclose.o \
++		   gzlib.o \
++		   gzread.o \
++		   gzwrite.o
+ 
+ ALL_COBJS	 = compat_err.o \
+ 		   compat_fts.o \
+Only in mandoc-1.14.6: Makefile.orig
+diff -upr mandoc-1.14.6.orig/configure mandoc-1.14.6/configure
+--- mandoc-1.14.6.orig/configure	2025-01-11 16:20:31.511129163 +0100
++++ mandoc-1.14.6/configure	2025-01-11 19:16:35.924788821 +0100
+@@ -430,7 +430,7 @@ fi
+ [ "${FATAL}" -eq 0 ] || exit 1
+ 
+ # --- LDADD ---
+-LDADD="${LDADD} ${LD_NANOSLEEP} ${LD_RECVMSG} ${LD_OHASH} -lz"
++LDADD="${LDADD} ${LD_NANOSLEEP} ${LD_RECVMSG} ${LD_OHASH} -lz -lzstd"
+ echo "selected LDADD=\"${LDADD}\"" 1>&2
+ echo "selected LDADD=\"${LDADD}\"" 1>&3
+ echo 1>&3
+Only in mandoc-1.14.6: configure.orig
+diff -upr mandoc-1.14.6.orig/read.c mandoc-1.14.6/read.c
+--- mandoc-1.14.6.orig/read.c	2025-01-11 16:35:03.825441715 +0100
++++ mandoc-1.14.6/read.c	2025-01-11 19:16:35.924788821 +0100
+@@ -37,7 +37,7 @@
+ #include <stdlib.h>
+ #include <string.h>
+ #include <unistd.h>
+-#include <zlib.h>
++#include <zstd_zlibwrapper.h>
+ 
+ #include "mandoc_aux.h"
+ #include "mandoc.h"
+@@ -627,7 +627,7 @@ mparse_open(struct mparse *curp, const char *file)
+ 	int		  fd, save_errno;
+ 
+ 	cp = strrchr(file, '.');
+-	curp->gzip = (cp != NULL && ! strcmp(cp + 1, "gz"));
++	curp->gzip = (cp != NULL && (! strcmp(cp + 1, "gz") || ! strcmp(cp + 1, "zst")));
+ 
+ 	/* First try to use the filename as it is. */
+ 
+Only in mandoc-1.14.6: read.c.orig

base-commit: da69a9e15115d6acc7e4a95cc6295f97c97f827e