From 926850c9b8e83efeb9609824e10994d4a49c274c Mon Sep 17 00:00:00 2001 From: sternenseemann Date: Fri, 24 Sep 2021 19:20:23 +0200 Subject: [PATCH 1/7] nixos/documentation: move man-db-specifics into new man-db module It may be possible to revert the move of `documentation.man.manualPages` later. The problem is that other man implementations (mandoc) want to generate their index databases in place, so the approach taken here doesn't translate super well. --- nixos/modules/misc/documentation.nix | 53 +++-------------------- nixos/modules/misc/man-db.nix | 63 ++++++++++++++++++++++++++++ nixos/modules/module-list.nix | 2 + 3 files changed, 71 insertions(+), 47 deletions(-) create mode 100644 nixos/modules/misc/man-db.nix diff --git a/nixos/modules/misc/documentation.nix b/nixos/modules/misc/documentation.nix index 64b1c15086fc8..d107a1abbc56b 100644 --- a/nixos/modules/misc/documentation.nix +++ b/nixos/modules/misc/documentation.nix @@ -74,10 +74,6 @@ let ]; }; - # list of man outputs currently active intended for use as default values - # for man-related options, thus "man" is included unconditionally. - activeManOutputs = [ "man" ] ++ lib.optionals cfg.dev.enable [ "devman" ]; - in { @@ -107,8 +103,8 @@ in type = types.bool; default = true; description = '' - Whether to install manual pages and the man command. - This also includes "man" outputs. + Whether to install manual pages. + This also includes man outputs. ''; }; @@ -116,30 +112,12 @@ in type = types.bool; default = false; description = '' - Whether to generate the manual page index caches using - mandb(8). This allows searching for a page or + Whether to generate the manual page index caches. + This allows searching for a page or keyword using utilities like apropos(1). ''; }; - man.manualPages = mkOption { - type = types.path; - default = pkgs.buildEnv { - name = "man-paths"; - paths = config.environment.systemPackages; - pathsToLink = [ "/share/man" ]; - extraOutputsToInstall = activeManOutputs; - ignoreCollisions = true; - }; - defaultText = literalDocBook "all man pages in "; - description = '' - The manual pages to generate caches for if - is enabled. Must be a path to a directory with man pages under - /share/man; see the source for an example. - Advanced users can make this a content-addressed derivation to save a few rebuilds. - ''; - }; - info.enable = mkOption { type = types.bool; default = true; @@ -221,29 +199,10 @@ in config = mkIf cfg.enable (mkMerge [ + # The actual implementation for this lives in man-db.nix (mkIf cfg.man.enable { - environment.systemPackages = [ pkgs.man-db ]; environment.pathsToLink = [ "/share/man" ]; - environment.extraOutputsToInstall = activeManOutputs; - environment.etc."man_db.conf".text = - let - manualCache = pkgs.runCommandLocal "man-cache" { } '' - echo "MANDB_MAP ${cfg.man.manualPages}/share/man $out" > man.conf - ${pkgs.man-db}/bin/mandb -C man.conf -psc >/dev/null 2>&1 - ''; - in - '' - # Manual pages paths for NixOS - MANPATH_MAP /run/current-system/sw/bin /run/current-system/sw/share/man - MANPATH_MAP /run/wrappers/bin /run/current-system/sw/share/man - - ${optionalString cfg.man.generateCaches '' - # Generated manual pages cache for NixOS (immutable) - MANDB_MAP /run/current-system/sw/share/man ${manualCache} - ''} - # Manual pages caches for NixOS - MANDB_MAP /run/current-system/sw/share/man /var/cache/man/nixos - ''; + environment.extraOutputsToInstall = [ "man" ] ++ optional cfg.dev.enable "devman"; }) (mkIf cfg.info.enable { diff --git a/nixos/modules/misc/man-db.nix b/nixos/modules/misc/man-db.nix new file mode 100644 index 0000000000000..94898504b3f75 --- /dev/null +++ b/nixos/modules/misc/man-db.nix @@ -0,0 +1,63 @@ +{ config, pkgs, lib, ... }: + +let + cfg = config.documentation.man.man-db; +in + +{ + options = { + documentation.man.man-db = { + enable = lib.mkEnableOption "man-db as the default man page viewer" // { + default = config.documentation.man.enable; + defaultText = lib.literalExpression "config.documentation.man.enable"; + example = false; + }; + + manualPages = lib.mkOption { + type = lib.types.path; + default = pkgs.buildEnv { + name = "man-paths"; + paths = config.environment.systemPackages; + pathsToLink = [ "/share/man" ]; + extraOutputsToInstall = [ "man" ] + ++ lib.optionals config.documentation.dev.enable [ "devman" ]; + ignoreCollisions = true; + }; + defaultText = lib.literalDocBook "all man pages in "; + description = '' + The manual pages to generate caches for if + is enabled. Must be a path to a directory with man pages under + /share/man; see the source for an example. + Advanced users can make this a content-addressed derivation to save a few rebuilds. + ''; + }; + }; + }; + + imports = [ + (lib.mkRenamedOptionModule [ "documentation" "man" "manualPages" ] [ "documentation" "man" "man-db" "manualPages" ]) + ]; + + config = lib.mkIf cfg.enable { + environment.systemPackages = [ pkgs.man-db ]; + environment.etc."man_db.conf".text = + let + manualCache = pkgs.runCommandLocal "man-cache" { } '' + echo "MANDB_MAP ${cfg.manualPages}/share/man $out" > man.conf + ${pkgs.man-db}/bin/mandb -C man.conf -psc >/dev/null 2>&1 + ''; + in + '' + # Manual pages paths for NixOS + MANPATH_MAP /run/current-system/sw/bin /run/current-system/sw/share/man + MANPATH_MAP /run/wrappers/bin /run/current-system/sw/share/man + + ${lib.optionalString config.documentation.man.generateCaches '' + # Generated manual pages cache for NixOS (immutable) + MANDB_MAP /run/current-system/sw/share/man ${manualCache} + ''} + # Manual pages caches for NixOS + MANDB_MAP /run/current-system/sw/share/man /var/cache/man/nixos + ''; + }; +} diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 55de017350248..33c13e3855c0c 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -108,6 +108,8 @@ ./misc/lib.nix ./misc/label.nix ./misc/locate.nix + ./misc/man-db.nix + ./misc/mandoc.nix ./misc/meta.nix ./misc/nixpkgs.nix ./misc/passthru.nix From 6553d1d5e7c27e0b62a6f01495a8541460c87c73 Mon Sep 17 00:00:00 2001 From: sternenseemann Date: Fri, 24 Sep 2021 19:31:03 +0200 Subject: [PATCH 2/7] nixos/documentation: properly reference apropos(1), mention man -k man -k is useful to mention as it is -- in constrast to apropos(1) -- actually required by POSIX. --- nixos/modules/misc/documentation.nix | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/nixos/modules/misc/documentation.nix b/nixos/modules/misc/documentation.nix index d107a1abbc56b..8f09568ee0937 100644 --- a/nixos/modules/misc/documentation.nix +++ b/nixos/modules/misc/documentation.nix @@ -114,7 +114,16 @@ in description = '' Whether to generate the manual page index caches. This allows searching for a page or - keyword using utilities like apropos(1). + keyword using utilities like + + apropos + 1 + + and the -k option of + + man + 1 + . ''; }; From 14550e5bb07e9274d0d59f98be9f46dcdd115b80 Mon Sep 17 00:00:00 2001 From: sternenseemann Date: Sun, 19 Sep 2021 19:51:03 +0200 Subject: [PATCH 3/7] nixos/mandoc: init Adds a NixOS module which allows using mandoc as the main manual viewer. It can be used as a drop-in replacement for documentation.man which relies on GNU's man-db and provides more or less the same features. The generateCaches option requires a different implementation for mandoc, so it is hard to share code between the two modules -- hence it has been implemented separately. Using both at the same time makes little sense and wouldn't quite work, so there's an assertion to prevent it. To make makewhatis(8) index manual pages which are symlinks to the nix store, we need to set READ_ALLOWED_PATH to include `builtins.storeDir`. For background and discussion see: https://inbox.vuxu.org/mandoc-tech/c9932669-e9d4-1454-8708-7c8e36967e8e@systemli.org/T/ --- nixos/modules/misc/documentation.nix | 13 ++++++- nixos/modules/misc/mandoc.nix | 51 ++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 nixos/modules/misc/mandoc.nix diff --git a/nixos/modules/misc/documentation.nix b/nixos/modules/misc/documentation.nix index 8f09568ee0937..bb294addccd96 100644 --- a/nixos/modules/misc/documentation.nix +++ b/nixos/modules/misc/documentation.nix @@ -207,8 +207,19 @@ in }; config = mkIf cfg.enable (mkMerge [ + { + assertions = [ + { + assertion = !(cfg.man.man-db.enable && cfg.man.mandoc.enable); + message = '' + man-db and mandoc can't be used as the default man page viewer at the same time! + ''; + } + ]; + } - # The actual implementation for this lives in man-db.nix + # The actual implementation for this lives in man-db.nix or mandoc.nix, + # depending on which backend is active. (mkIf cfg.man.enable { environment.pathsToLink = [ "/share/man" ]; environment.extraOutputsToInstall = [ "man" ] ++ optional cfg.dev.enable "devman"; diff --git a/nixos/modules/misc/mandoc.nix b/nixos/modules/misc/mandoc.nix new file mode 100644 index 0000000000000..939f87a317847 --- /dev/null +++ b/nixos/modules/misc/mandoc.nix @@ -0,0 +1,51 @@ +{ config, lib, pkgs, ... }: + +let + makewhatis = "${lib.getBin pkgs.mandoc}/bin/makewhatis"; + + cfg = config.documentation.man.mandoc; + +in { + meta.maintainers = [ lib.maintainers.sternenseemann ]; + + options = { + documentation.man.mandoc = { + enable = lib.mkEnableOption "mandoc as the default man page viewer"; + + manPath = lib.mkOption { + type = with lib.types; listOf str; + default = [ "share/man" ]; + example = lib.literalExpression "[ \"share/man\" \"share/man/fr\" ]"; + description = '' + Change the manpath, i. e. the directories where + man1 + looks for section-specific directories of man pages. + You only need to change this setting if you want extra man pages + (e. g. in non-english languages). All values must be strings that + are a valid path from the target prefix (without including it). + The first value given takes priority. + ''; + }; + }; + }; + + config = lib.mkIf cfg.enable { + environment = { + systemPackages = [ pkgs.mandoc ]; + + # tell mandoc about man pages + etc."man.conf".text = lib.concatMapStrings (path: '' + manpath /run/current-system/sw/${path} + '') cfg.manPath; + + # create mandoc.db for whatis(1), apropos(1) and man(1) -k + # TODO(@sternenseemman): fix symlinked directories not getting indexed, + # see: https://inbox.vuxu.org/mandoc-tech/20210906171231.GF83680@athene.usta.de/T/#e85f773c1781e3fef85562b2794f9cad7b2909a3c + extraSetup = lib.mkIf config.documentation.man.generateCaches '' + ${makewhatis} -T utf8 ${ + lib.concatMapStringsSep " " (path: "\"$out/${path}\"") cfg.manPath + } + ''; + }; + }; +} From 49b365c63015af8f9ffdddedcabecc88f0a04770 Mon Sep 17 00:00:00 2001 From: sternenseemann Date: Fri, 24 Sep 2021 20:54:08 +0200 Subject: [PATCH 4/7] nixos/tests/man: test common functionality of both man impls --- nixos/tests/all-tests.nix | 1 + nixos/tests/man.nix | 100 +++++++++++++++++++++++++++++ pkgs/tools/misc/man-db/default.nix | 6 +- pkgs/tools/misc/mandoc/default.nix | 6 +- 4 files changed, 111 insertions(+), 2 deletions(-) create mode 100644 nixos/tests/man.nix diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index 09cd26a766925..ab9ade1124a7a 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -255,6 +255,7 @@ in magnetico = handleTest ./magnetico.nix {}; mailcatcher = handleTest ./mailcatcher.nix {}; mailhog = handleTest ./mailhog.nix {}; + man = handleTest ./man.nix {}; mariadb-galera-mariabackup = handleTest ./mysql/mariadb-galera-mariabackup.nix {}; mariadb-galera-rsync = handleTest ./mysql/mariadb-galera-rsync.nix {}; matomo = handleTest ./matomo.nix {}; diff --git a/nixos/tests/man.nix b/nixos/tests/man.nix new file mode 100644 index 0000000000000..1ff5af4e80591 --- /dev/null +++ b/nixos/tests/man.nix @@ -0,0 +1,100 @@ + +import ./make-test-python.nix ({ pkgs, lib, ... }: let + manImplementations = [ + "mandoc" + "man-db" + ]; + + machineNames = builtins.map machineSafe manImplementations; + + makeConfig = useImpl: { + # Note: mandoc currently can't index symlinked section directories. + # So if a man section comes from one package exclusively (e. g. + # 1p from man-pages-posix and 2 from man-pages), it isn't searchable. + environment.systemPackages = [ + pkgs.man-pages + pkgs.openssl + pkgs.libunwind + ]; + + documentation = { + enable = true; + nixos.enable = lib.mkForce true; + dev.enable = true; + man = { + enable = true; + generateCaches = true; + } // lib.listToAttrs (builtins.map (impl: { + name = impl; + value = { + enable = useImpl == impl; + }; + }) manImplementations); + }; + }; + + machineSafe = builtins.replaceStrings [ "-" ] [ "_" ]; +in { + name = "man"; + meta.maintainers = [ lib.maintainers.sternenseemann ]; + + nodes = lib.listToAttrs (builtins.map (i: { + name = machineSafe i; + value = makeConfig i; + }) manImplementations); + + testScript = '' + import re + start_all() + + def match_man_k(page, section, haystack): + """ + Check if the man page {page}({section}) occurs in + the output of `man -k` given as haystack. Note: + This is not super reliable, e. g. it can't deal + with man pages that are in multiple sections. + """ + + for line in haystack.split("\n"): + # man -k can look like this: + # page(3) - bla + # page (3) - bla + # pagea, pageb (3, 3P) - foo + # pagea, pageb, pagec(3) - bar + pages = line.split("(")[0] + sections = re.search("\\([a-zA-Z1-9, ]+\\)", line) + if sections is None: + continue + else: + sections = sections.group(0)[1:-1] + + if page in pages and f'{section}' in sections: + return True + + return False + + '' + lib.concatMapStrings (machine: '' + with subtest("Test direct man page lookups in ${machine}"): + # man works + ${machine}.succeed("man man > /dev/null") + # devman works + ${machine}.succeed("man 3 libunwind > /dev/null") + # NixOS configuration man page is installed + ${machine}.succeed("man configuration.nix > /dev/null") + + with subtest("Test generateCaches via man -k in ${machine}"): + expected = [ + ("openssl", "ssl", 3), + ("unwind", "libunwind", 3), + ("user", "useradd", 8), + ("user", "userdel", 8), + ("mem", "free", 3), + ("mem", "free", 1), + ] + + for (keyword, page, section) in expected: + matches = ${machine}.succeed(f"man -k {keyword}") + if not match_man_k(page, section, matches): + raise Exception(f"{page}({section}) missing in matches: {matches}") + '') machineNames; +}) diff --git a/pkgs/tools/misc/man-db/default.nix b/pkgs/tools/misc/man-db/default.nix index f1739cbd50dd2..d495c912f5996 100644 --- a/pkgs/tools/misc/man-db/default.nix +++ b/pkgs/tools/misc/man-db/default.nix @@ -1,4 +1,4 @@ -{ lib, stdenv, fetchurl, pkg-config, libpipeline, db, groff, libiconv, makeWrapper, buildPackages }: +{ lib, stdenv, fetchurl, pkg-config, libpipeline, db, groff, libiconv, makeWrapper, buildPackages, nixosTests }: stdenv.mkDerivation rec { pname = "man-db"; @@ -73,6 +73,10 @@ stdenv.mkDerivation rec { doCheck = !stdenv.hostPlatform.isMusl /* iconv binary */ && !stdenv.hostPlatform.isDarwin; + passthru.tests = { + nixos = nixosTests.man; + }; + meta = with lib; { homepage = "http://man-db.nongnu.org"; description = "An implementation of the standard Unix documentation system accessed using the man command"; diff --git a/pkgs/tools/misc/mandoc/default.nix b/pkgs/tools/misc/mandoc/default.nix index 1771f6515bc41..2d974b8af63dd 100644 --- a/pkgs/tools/misc/mandoc/default.nix +++ b/pkgs/tools/misc/mandoc/default.nix @@ -1,4 +1,4 @@ -{ lib, stdenv, fetchurl, zlib, perl }: +{ lib, stdenv, fetchurl, zlib, perl, nixosTests }: let # check if we can execute binaries for the host platform on the build platform @@ -62,6 +62,10 @@ stdenv.mkDerivation rec { checkInputs = [ perl ]; preCheck = "patchShebangs --build regress/regress.pl"; + passthru.tests = { + nixos = nixosTests.man; + }; + meta = with lib; { homepage = "https://mandoc.bsd.lv/"; description = "suite of tools compiling mdoc and man"; From f8a6d105f72e7a109b10ef39b789c82ac850bc51 Mon Sep 17 00:00:00 2001 From: sternenseemann Date: Sat, 2 Oct 2021 15:26:54 +0200 Subject: [PATCH 5/7] nixos/man-db: add package option --- nixos/modules/misc/man-db.nix | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/nixos/modules/misc/man-db.nix b/nixos/modules/misc/man-db.nix index 94898504b3f75..8bd329bc4e0c3 100644 --- a/nixos/modules/misc/man-db.nix +++ b/nixos/modules/misc/man-db.nix @@ -31,6 +31,16 @@ in Advanced users can make this a content-addressed derivation to save a few rebuilds. ''; }; + + package = lib.mkOption { + type = lib.types.package; + default = pkgs.man-db; + defaultText = lib.literalExpression "pkgs.man-db"; + description = '' + The man-db derivation to use. Useful to override + configuration options used for the package. + ''; + }; }; }; @@ -39,12 +49,12 @@ in ]; config = lib.mkIf cfg.enable { - environment.systemPackages = [ pkgs.man-db ]; + environment.systemPackages = [ cfg.package ]; environment.etc."man_db.conf".text = let manualCache = pkgs.runCommandLocal "man-cache" { } '' echo "MANDB_MAP ${cfg.manualPages}/share/man $out" > man.conf - ${pkgs.man-db}/bin/mandb -C man.conf -psc >/dev/null 2>&1 + ${cfg.package}/bin/mandb -C man.conf -psc >/dev/null 2>&1 ''; in '' From 5f3913799cf571e52f48fdb85f8c27799b089c36 Mon Sep 17 00:00:00 2001 From: sternenseemann Date: Sat, 2 Oct 2021 15:28:48 +0200 Subject: [PATCH 6/7] nixos/mandoc: add package option --- nixos/modules/misc/mandoc.nix | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/nixos/modules/misc/mandoc.nix b/nixos/modules/misc/mandoc.nix index 939f87a317847..3da60f2f8e65f 100644 --- a/nixos/modules/misc/mandoc.nix +++ b/nixos/modules/misc/mandoc.nix @@ -1,7 +1,7 @@ { config, lib, pkgs, ... }: let - makewhatis = "${lib.getBin pkgs.mandoc}/bin/makewhatis"; + makewhatis = "${lib.getBin cfg.package}/bin/makewhatis"; cfg = config.documentation.man.mandoc; @@ -26,12 +26,22 @@ in { The first value given takes priority. ''; }; + + package = lib.mkOption { + type = lib.types.package; + default = pkgs.mandoc; + defaultText = lib.literalExpression "pkgs.mandoc"; + description = '' + The mandoc derivation to use. Useful to override + configuration options used for the package. + ''; + }; }; }; config = lib.mkIf cfg.enable { environment = { - systemPackages = [ pkgs.mandoc ]; + systemPackages = [ cfg.package ]; # tell mandoc about man pages etc."man.conf".text = lib.concatMapStrings (path: '' From 1b4aa04f5bc4755880c6ed4de99aaf5fb8a04c6d Mon Sep 17 00:00:00 2001 From: sternenseemann Date: Mon, 22 Nov 2021 23:25:22 +0100 Subject: [PATCH 7/7] nixos/doc: document documentation.man changes in 22.05 rel notes --- .../from_md/release-notes/rl-2205.section.xml | 14 ++++++++++++++ nixos/doc/manual/release-notes/rl-2205.section.md | 2 ++ 2 files changed, 16 insertions(+) diff --git a/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml b/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml index 1e425248be0fc..cdc23ad888b18 100644 --- a/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml +++ b/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml @@ -163,6 +163,20 @@ ~100MB for python itself). + + + documentation.man has been refactored to + support choosing a man implementation other than GNU’s + man-db. For this, + documentation.man.manualPages has been + renamed to + documentation.man.man-db.manualPages. If + you want to use the new alternative man implementation + mandoc, add + documentation.man = { enable = true; man-db.enable = false; mandoc.enable = true; } + to your configuration. + +
diff --git a/nixos/doc/manual/release-notes/rl-2205.section.md b/nixos/doc/manual/release-notes/rl-2205.section.md index ca89732fa801d..27ebceab2ec9a 100644 --- a/nixos/doc/manual/release-notes/rl-2205.section.md +++ b/nixos/doc/manual/release-notes/rl-2205.section.md @@ -60,6 +60,8 @@ In addition to numerous new and upgraded packages, this release has the followin This has the added benefit to reduce the closure size of `ipython` from ~400MB to ~160MB (including ~100MB for python itself). +- `documentation.man` has been refactored to support choosing a man implementation other than GNU's `man-db`. For this, `documentation.man.manualPages` has been renamed to `documentation.man.man-db.manualPages`. If you want to use the new alternative man implementation `mandoc`, add `documentation.man = { enable = true; man-db.enable = false; mandoc.enable = true; }` to your configuration. + ## Other Notable Changes {#sec-release-22.05-notable-changes} - The option [services.redis.servers](#opt-services.redis.servers) was added