summaryrefslogtreecommitdiffstats
path: root/nixos
diff options
context:
space:
mode:
authorgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>2023-01-26 00:13:32 +0000
committerGitHub <noreply@github.com>2023-01-26 00:13:32 +0000
commit0f008a08f08e97837c43bc09fbf614ccd7577aa4 (patch)
treead04fb8b9672cdc06a19e0a6e727c5b8b2eb02f5 /nixos
parent738bf6e95d1cf1ecb58b1333aebc250ca866e382 (diff)
parentb8140c4fde4a6c3b415b2417e4780f18569be9f3 (diff)
Merge master into haskell-updates
Diffstat (limited to 'nixos')
-rw-r--r--nixos/doc/manual/default.nix33
-rw-r--r--nixos/doc/manual/from_md/release-notes/rl-2305.section.xml9
-rw-r--r--nixos/doc/manual/release-notes/rl-2305.section.md2
-rw-r--r--nixos/lib/make-options-doc/default.nix88
-rw-r--r--nixos/lib/make-options-doc/mergeJSON.py245
-rw-r--r--nixos/lib/make-options-doc/options-to-docbook.xsl179
-rw-r--r--nixos/lib/make-options-doc/optionsJSONtoXML.nix6
-rw-r--r--nixos/lib/make-options-doc/optionsToDocbook.py343
-rw-r--r--nixos/lib/make-options-doc/sortXML.py27
-rw-r--r--nixos/lib/testing/driver.nix4
-rw-r--r--nixos/lib/testing/network.nix41
-rw-r--r--nixos/modules/virtualisation/qemu-vm.nix32
-rw-r--r--nixos/tests/networking.nix134
13 files changed, 514 insertions, 629 deletions
diff --git a/nixos/doc/manual/default.nix b/nixos/doc/manual/default.nix
index a89e5e466500..0ddb3fa7fbe9 100644
--- a/nixos/doc/manual/default.nix
+++ b/nixos/doc/manual/default.nix
@@ -176,36 +176,6 @@ let
lintrng $out/man-pages-combined.xml
'';
- olinkDB = runCommand "manual-olinkdb"
- { inherit sources;
- nativeBuildInputs = [ buildPackages.libxml2.bin buildPackages.libxslt.bin ];
- }
- ''
- xsltproc \
- ${manualXsltprocOptions} \
- --stringparam collect.xref.targets only \
- --stringparam targets.filename "$out/manual.db" \
- --nonet \
- ${docbook_xsl_ns}/xml/xsl/docbook/xhtml/chunktoc.xsl \
- ${manual-combined}/manual-combined.xml
-
- cat > "$out/olinkdb.xml" <<EOF
- <?xml version="1.0" encoding="utf-8"?>
- <!DOCTYPE targetset SYSTEM
- "file://${docbook_xsl_ns}/xml/xsl/docbook/common/targetdatabase.dtd" [
- <!ENTITY manualtargets SYSTEM "file://$out/manual.db">
- ]>
- <targetset>
- <targetsetinfo>
- Allows for cross-referencing olinks between the manpages
- and manual.
- </targetsetinfo>
-
- <document targetdoc="manual">&manualtargets;</document>
- </targetset>
- EOF
- '';
-
in rec {
inherit generatedSources;
@@ -224,7 +194,6 @@ in rec {
mkdir -p $dst
xsltproc \
${manualXsltprocOptions} \
- --stringparam target.database.document "${olinkDB}/olinkdb.xml" \
--stringparam id.warnings "1" \
--nonet --output $dst/ \
${docbook_xsl_ns}/xml/xsl/docbook/xhtml/chunktoc.xsl \
@@ -261,7 +230,6 @@ in rec {
xsltproc \
${manualXsltprocOptions} \
- --stringparam target.database.document "${olinkDB}/olinkdb.xml" \
--nonet --xinclude --output $dst/epub/ \
${docbook_xsl_ns}/xml/xsl/docbook/epub/docbook.xsl \
${manual-combined}/manual-combined.xml
@@ -295,7 +263,6 @@ in rec {
--param man.output.base.dir "'$out/share/man/'" \
--param man.endnotes.are.numbered 0 \
--param man.break.after.slash 1 \
- --stringparam target.database.document "${olinkDB}/olinkdb.xml" \
${docbook_xsl_ns}/xml/xsl/docbook/manpages/docbook.xsl \
${manual-combined}/man-pages-combined.xml
'';
diff --git a/nixos/doc/manual/from_md/release-notes/rl-2305.section.xml b/nixos/doc/manual/from_md/release-notes/rl-2305.section.xml
index aa58c2a354d5..0e6add60c354 100644
--- a/nixos/doc/manual/from_md/release-notes/rl-2305.section.xml
+++ b/nixos/doc/manual/from_md/release-notes/rl-2305.section.xml
@@ -739,6 +739,15 @@
been fixed to allow more than one plugin in the path.
</para>
</listitem>
+ <listitem>
+ <para>
+ A new option was added to the virtualisation module that
+ enables specifying explicitly named network interfaces in QEMU
+ VMs. The existing <literal>virtualisation.vlans</literal> is
+ still supported for cases where the name of the network
+ interface is irrelevant.
+ </para>
+ </listitem>
</itemizedlist>
</section>
</section>
diff --git a/nixos/doc/manual/release-notes/rl-2305.section.md b/nixos/doc/manual/release-notes/rl-2305.section.md
index 13ff807b79c0..2329373f54b8 100644
--- a/nixos/doc/manual/release-notes/rl-2305.section.md
+++ b/nixos/doc/manual/release-notes/rl-2305.section.md
@@ -185,3 +185,5 @@ In addition to numerous new and upgraded packages, this release has the followin
- `nixos-version` now accepts `--configuration-revision` to display more information about the current generation revision
- The option `services.nomad.extraSettingsPlugins` has been fixed to allow more than one plugin in the path.
+
+- A new option was added to the virtualisation module that enables specifying explicitly named network interfaces in QEMU VMs. The existing `virtualisation.vlans` is still supported for cases where the name of the network interface is irrelevant.
diff --git a/nixos/lib/make-options-doc/default.nix b/nixos/lib/make-options-doc/default.nix
index 335217703c82..01db7bcbee9b 100644
--- a/nixos/lib/make-options-doc/default.nix
+++ b/nixos/lib/make-options-doc/default.nix
@@ -109,29 +109,7 @@ in rec {
{ meta.description = "List of NixOS options in JSON format";
nativeBuildInputs = [
pkgs.brotli
- (let
- # python3Minimal can't be overridden with packages on Darwin, due to a missing framework.
- # Instead of modifying stdenv, we take the easy way out, since most people on Darwin will
- # just be hacking on the Nixpkgs manual (which also uses make-options-doc).
- python = if pkgs.stdenv.isDarwin then pkgs.python3 else pkgs.python3Minimal;
- self = (python.override {
- inherit self;
- includeSiteCustomize = true;
- });
- in self.withPackages (p:
- let
- # TODO add our own small test suite when rendering is split out into a new tool
- markdown-it-py = p.markdown-it-py.override {
- disableTests = true;
- };
- mdit-py-plugins = p.mdit-py-plugins.override {
- inherit markdown-it-py;
- disableTests = true;
- };
- in [
- markdown-it-py
- mdit-py-plugins
- ]))
+ pkgs.python3Minimal
];
options = builtins.toFile "options.json"
(builtins.unsafeDiscardStringContext (builtins.toJSON optionsNix));
@@ -141,8 +119,6 @@ in rec {
if baseOptionsJSON == null
then builtins.toFile "base.json" "{}"
else baseOptionsJSON;
-
- MANPAGE_URLS = pkgs.path + "/doc/manpage-urls.json";
}
''
# Export list of options in different format.
@@ -153,7 +129,6 @@ in rec {
python ${./mergeJSON.py} \
${lib.optionalString warningsAreErrors "--warnings-are-errors"} \
${if allowDocBook then "--warn-on-docbook" else "--error-on-docbook"} \
- ${lib.optionalString markdownByDefault "--markdown-by-default"} \
$baseJSON $options \
> $dst/options.json
@@ -172,21 +147,45 @@ in rec {
fi >"$out"
'';
- # Convert options.json into an XML file.
- # The actual generation of the xml file is done in nix purely for the convenience
- # of not having to generate the xml some other way
- optionsXML = pkgs.runCommand "options.xml" {} ''
- export NIX_STORE_DIR=$TMPDIR/store
- export NIX_STATE_DIR=$TMPDIR/state
- ${pkgs.nix}/bin/nix-instantiate \
- --eval --xml --strict ${./optionsJSONtoXML.nix} \
- --argstr file ${optionsJSON}/share/doc/nixos/options.json \
- > "$out"
- '';
+ optionsDocBook = pkgs.runCommand "options-docbook.xml" {
+ MANPAGE_URLS = pkgs.path + "/doc/manpage-urls.json";
+ OTD_DOCUMENT_TYPE = documentType;
+ OTD_VARIABLE_LIST_ID = variablelistId;
+ OTD_OPTION_ID_PREFIX = optionIdPrefix;
+ OTD_REVISION = revision;
+
+ nativeBuildInputs = [
+ (let
+ # python3Minimal can't be overridden with packages on Darwin, due to a missing framework.
+ # Instead of modifying stdenv, we take the easy way out, since most people on Darwin will
+ # just be hacking on the Nixpkgs manual (which also uses make-options-doc).
+ python = if pkgs.stdenv.isDarwin then pkgs.python3 else pkgs.python3Minimal;
+ self = (python.override {
+ inherit self;
+ includeSiteCustomize = true;
+ });
+ in self.withPackages (p:
+ let
+ # TODO add our own small test suite when rendering is split out into a new tool
+ markdown-it-py = p.markdown-it-py.override {
+ disableTests = true;
+ };
+ mdit-py-plugins = p.mdit-py-plugins.override {
+ inherit markdown-it-py;
+ disableTests = true;
+ };
+ in [
+ markdown-it-py
+ mdit-py-plugins
+ ]))
+ ];
+ } ''
+ python ${./optionsToDocbook.py} \
+ ${lib.optionalString markdownByDefault "--markdown-by-default"} \
+ ${optionsJSON}/share/doc/nixos/options.json \
+ > options.xml
- optionsDocBook = pkgs.runCommand "options-docbook.xml" {} ''
- optionsXML=${optionsXML}
- if grep /nixpkgs/nixos/modules $optionsXML; then
+ if grep /nixpkgs/nixos/modules options.xml; then
echo "The manual appears to depend on the location of Nixpkgs, which is bad"
echo "since this prevents sharing via the NixOS channel. This is typically"
echo "caused by an option default that refers to a relative path (see above"
@@ -194,14 +193,7 @@ in rec {
exit 1
fi
- ${pkgs.python3Minimal}/bin/python ${./sortXML.py} $optionsXML sorted.xml
- ${pkgs.libxslt.bin}/bin/xsltproc \
- --stringparam documentType '${documentType}' \
- --stringparam revision '${revision}' \
- --stringparam variablelistId '${variablelistId}' \
- --stringparam optionIdPrefix '${optionIdPrefix}' \
- -o intermediate.xml ${./options-to-docbook.xsl} sorted.xml
${pkgs.libxslt.bin}/bin/xsltproc \
- -o "$out" ${./postprocess-option-descriptions.xsl} intermediate.xml
+ -o "$out" ${./postprocess-option-descriptions.xsl} options.xml
'';
}
diff --git a/nixos/lib/make-options-doc/mergeJSON.py b/nixos/lib/make-options-doc/mergeJSON.py
index 2de0bbae1d91..b4f72b8a3fdc 100644
--- a/nixos/lib/make-options-doc/mergeJSON.py
+++ b/nixos/lib/make-options-doc/mergeJSON.py
@@ -3,19 +3,6 @@ import json
import os
import sys
from typing import Any, Dict, List
-from collections.abc import MutableMapping, Sequence
-import inspect
-
-# for MD conversion
-import markdown_it
-import markdown_it.renderer
-from markdown_it.token import Token
-from markdown_it.utils import OptionsDict
-from mdit_py_plugins.container import container_plugin
-from mdit_py_plugins.deflist import deflist_plugin
-from mdit_py_plugins.myst_role import myst_role_plugin
-import re
-from xml.sax.saxutils import escape, quoteattr
JSON = Dict[str, Any]
@@ -55,236 +42,9 @@ def unpivot(options: Dict[Key, Option]) -> Dict[str, JSON]:
result[opt.name] = opt.value
return result
-manpage_urls = json.load(open(os.getenv('MANPAGE_URLS')))
-
-class Renderer(markdown_it.renderer.RendererProtocol):
- __output__ = "docbook"
- def __init__(self, parser=None):
- self.rules = {
- k: v
- for k, v in inspect.getmembers(self, predicate=inspect.ismethod)
- if not (k.startswith("render") or k.startswith("_"))
- } | {
- "container_{.note}_open": self._note_open,
- "container_{.note}_close": self._note_close,
- "container_{.important}_open": self._important_open,
- "container_{.important}_close": self._important_close,
- "container_{.warning}_open": self._warning_open,
- "container_{.warning}_close": self._warning_close,
- }
- def render(self, tokens: Sequence[Token], options: OptionsDict, env: MutableMapping) -> str:
- assert '-link-tag-stack' not in env
- env['-link-tag-stack'] = []
- assert '-deflist-stack' not in env
- env['-deflist-stack'] = []
- def do_one(i, token):
- if token.type == "inline":
- assert token.children is not None
- return self.renderInline(token.children, options, env)
- elif token.type in self.rules:
- return self.rules[token.type](tokens[i], tokens, i, options, env)
- else:
- raise NotImplementedError("md token not supported yet", token)
- return "".join(map(lambda arg: do_one(*arg), enumerate(tokens)))
- def renderInline(self, tokens: Sequence[Token], options: OptionsDict, env: MutableMapping) -> str:
- # HACK to support docbook links and xrefs. link handling is only necessary because the docbook
- # manpage stylesheet converts - in urls to a mathematical minus, which may be somewhat incorrect.
- for i, token in enumerate(tokens):
- if token.type != 'link_open':
- continue
- token.tag = 'link'
- # turn [](#foo) into xrefs
- if token.attrs['href'][0:1] == '#' and tokens[i + 1].type == 'link_close':
- token.tag = "xref"
- # turn <x> into links without contents
- if tokens[i + 1].type == 'text' and tokens[i + 1].content == token.attrs['href']:
- tokens[i + 1].content = ''
-
- def do_one(i, token):
- if token.type in self.rules:
- return self.rules[token.type](tokens[i], tokens, i, options, env)
- else:
- raise NotImplementedError("md node not supported yet", token)
- return "".join(map(lambda arg: do_one(*arg), enumerate(tokens)))
-
- def text(self, token, tokens, i, options, env):
- return escape(token.content)
- def paragraph_open(self, token, tokens, i, options, env):
- return "<para>"
- def paragraph_close(self, token, tokens, i, options, env):
- return "</para>"
- def hardbreak(self, token, tokens, i, options, env):
- return "<literallayout>\n</literallayout>"
- def softbreak(self, token, tokens, i, options, env):
- # should check options.breaks() and emit hard break if so
- return "\n"
- def code_inline(self, token, tokens, i, options, env):
- return f"<literal>{escape(token.content)}</literal>"
- def code_block(self, token, tokens, i, options, env):
- return f"<programlisting>{escape(token.content)}</programlisting>"
- def link_open(self, token, tokens, i, options, env):
- env['-link-tag-stack'].append(token.tag)
- (attr, start) = ('linkend', 1) if token.attrs['href'][0] == '#' else ('xlink:href', 0)
- return f"<{token.tag} {attr}={quoteattr(token.attrs['href'][start:])}>"
- def link_close(self, token, tokens, i, options, env):
- return f"</{env['-link-tag-stack'].pop()}>"
- def list_item_open(self, token, tokens, i, options, env):
- return "<listitem>"
- def list_item_close(self, token, tokens, i, options, env):
- return "</listitem>\n"
- # HACK open and close para for docbook change size. remove soon.
- def bullet_list_open(self, token, tokens, i, options, env):
- return "<para><itemizedlist>\n"
- def bullet_list_close(self, token, tokens, i, options, env):
- return "\n</itemizedlist></para>"
- def em_open(self, token, tokens, i, options, env):
- return "<emphasis>"
- def em_close(self, token, tokens, i, options, env):
- return "</emphasis>"
- def strong_open(self, token, tokens, i, options, env):
- return "<emphasis role=\"strong\">"
- def strong_close(self, token, tokens, i, options, env):
- return "</emphasis>"
- def fence(self, token, tokens, i, options, env):
- info = f" language={quoteattr(token.info)}" if token.info != "" else ""
- return f"<programlisting{info}>{escape(token.content)}</programlisting>"
- def blockquote_open(self, token, tokens, i, options, env):
- return "<para><blockquote>"
- def blockquote_close(self, token, tokens, i, options, env):
- return "</blockquote></para>"
- def _note_open(self, token, tokens, i, options, env):
- return "<para><note>"
- def _note_close(self, token, tokens, i, options, env):
- return "</note></para>"
- def _important_open(self, token, tokens, i, options, env):
- return "<para><important>"
- def _important_close(self, token, tokens, i, options, env):
- return "</important></para>"
- def _warning_open(self, token, tokens, i, options, env):
- return "<para><warning>"
- def _warning_close(self, token, tokens, i, options, env):
- return "</warning></para>"
- # markdown-it emits tokens based on the html syntax tree, but docbook is
- # slightly different. html has <dl>{<dt/>{<dd/>}}</dl>,
- # docbook has <variablelist>{<varlistentry><term/><listitem/></varlistentry>}<variablelist>
- # we have to reject multiple definitions for the same term for time being.
- def dl_open(self, token, tokens, i, options, env):
- env['-deflist-stack'].append({})
- return "<para><variablelist>"
- def dl_close(self, token, tokens, i, options, env):
- env['-deflist-stack'].pop()
- return "</variablelist></para>"
- def dt_open(self, token, tokens, i, options, env):
- env['-deflist-stack'][-1]['has-dd'] = False
- return "<varlistentry><term>"
- def dt_close(self, token, tokens, i, options, env):
- return "</term>"
- def dd_open(self, token, tokens, i, options, env):
- if env['-deflist-stack'][-1]['has-dd']:
- raise Exception("multiple definitions per term not supported")
- env['-deflist-stack'][-1]['has-dd'] = True
- return "<listitem>"
- def dd_close(self, token, tokens, i, options, env):
- return "</listitem></varlistentry>"
- def myst_role(self, token, tokens, i, options, env):
- if token.meta['name'] == 'command':
- return f"<command>{escape(token.content)}</command>"
- if token.meta['name'] == 'file':
- return f"<filename>{escape(token.content)}</filename>"
- if token.meta['name'] == 'var':
- return f"<varname>{escape(token.content)}</varname>"
- if token.meta['name'] == 'env':
- return f"<envar>{escape(token.content)}</envar>"
- if token.meta['name'] == 'option':
- return f"<option>{escape(token.content)}</option>"
- if token.meta['name'] == 'manpage':
- [page, section] = [ s.strip() for s in token.content.rsplit('(', 1) ]
- section = section[:-1]
- man = f"{page}({section})"
- title = f"<refentrytitle>{escape(page)}</refentrytitle>"
- vol = f"<manvolnum>{escape(section)}</manvolnum>"
- ref = f"<citerefentry>{title}{vol}</citerefentry>"
- if man in manpage_urls:
- return f"<link xlink:href={quoteattr(manpage_urls[man])}>{ref}</link>"
- else:
- return ref
- raise NotImplementedError("md node not supported yet", token)
-
-md = (
- markdown_it.MarkdownIt(renderer_cls=Renderer)
- # TODO maybe fork the plugin and have only a single rule for all?
- .use(container_plugin, name="{.note}")
- .use(container_plugin, name="{.important}")
- .use(container_plugin, name="{.warning}")
- .use(deflist_plugin)
- .use(myst_role_plugin)
-)
-
-# converts in-place!
-def convertMD(options: Dict[str, Any]) -> str:
- def convertString(path: str, text: str) -> str:
- try:
- rendered = md.render(text)
- return rendered
- except:
- print(f"error in {path}")
- raise
-
- def optionIs(option: Dict[str, Any], key: str, typ: str) -> bool:
- if key not in option: return False
- if type(option[key]) != dict: return False
- if '_type' not in option[key]: return False
- return option[key]['_type'] == typ
-
- def convertCode(name: str, option: Dict[str, Any], key: str):
- rendered = f"{key}-db"
- if optionIs(option, key, 'literalMD'):
- option[rendered] = convertString(name, f"*{key.capitalize()}:*\n{option[key]['text']}")
- elif optionIs(option, key, 'literalExpression'):
- code = option[key]['text']
- # for multi-line code blocks we only have to count ` runs at the beginning
- # of a line, but this is much easier.
- multiline = '\n' in code
- longest, current = (0, 0)
- for c in code:
- current = current + 1 if c == '`' else 0
- longest = max(current, longest)
- # inline literals need a space to separate ticks from content, code blocks
- # need newlines. inline literals need one extra tick, code blocks need three.
- ticks, sep = ('`' * (longest + (3 if multiline else 1)), '\n' if multiline else ' ')
- code = f"{ticks}{sep}{code}{sep}{ticks}"
- option[rendered] = convertString(name, f"*{key.capitalize()}:*\n{code}")
- elif optionIs(option, key, 'literalDocBook'):
- option[rendered] = f"<para><emphasis>{key.capitalize()}:</emphasis> {option[key]['text']}</para>"
- elif key in option:
- raise Exception(f"{name} {key} has unrecognized type", option[key])
-
- for (name, option) in options.items():
- try:
- if optionIs(option, 'description', 'mdDoc'):
- option['description'] = convertString(name, option['description']['text'])
- elif markdownByDefault:
- option['description'] = convertString(name, option['description'])
- else:
- option['description'] = ("<nixos:option-description><para>" +
- option['description'] +
- "</para></nixos:option-description>")
-
- convertCode(name, option, 'example')
- convertCode(name, option, 'default')
-
- if 'relatedPackages' in option:
- option['relatedPackages'] = convertString(name, option['relatedPackages'])
- except Exception as e:
- raise Exception(f"Failed to render option {name}: {str(e)}")
-
-
- return options
-
warningsAreErrors = False
warnOnDocbook = False
errorOnDocbook = False
-markdownByDefault = False
optOffset = 0
for arg in sys.argv[1:]:
if arg == "--warnings-are-errors":
@@ -296,9 +56,6 @@ for arg in sys.argv[1:]:
elif arg == "--error-on-docbook":
optOffset += 1
errorOnDocbook = True
- if arg == "--markdown-by-default":
- optOffset += 1
- markdownByDefault = True
options = pivot(json.load(open(sys.argv[1 + optOffset], 'r')))
overrides = pivot(json.load(open(sys.argv[2 + optOffset], 'r')))
@@ -404,4 +161,4 @@ if hasWarnings and warningsAreErrors:
file=sys.stderr)
sys.exit(1)
-json.dump(convertMD(unpivot(options)), fp=sys.stdout)
+json.dump(unpivot(options), fp=sys.stdout)
diff --git a/nixos/lib/make-options-doc/options-to-docbook.xsl b/nixos/lib/make-options-doc/options-to-docbook.xsl
deleted file mode 100644
index a2e88febdaff..000000000000
--- a/nixos/lib/make-options-doc/options-to-docbook.xsl
+++ /dev/null
@@ -1,179 +0,0 @@
-<?xml version="1.0"?>
-
-<xsl:stylesheet version="1.0"
- xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
- xmlns:str="http://exslt.org/strings"
- xmlns:xlink="http://www.w3.org/1999/xlink"
- xmlns:nixos="tag:nixos.org"
- xmlns="http://docbook.org/ns/docbook"
- extension-element-prefixes="str"
- >
-
- <xsl:output method='xml' encoding="UTF-8" />
-
- <xsl:param name="revision" />
- <xsl:param name="documentType" />
- <xsl:param name="program" />
- <xsl:param name="variablelistId" />
- <xsl:param name="optionIdPrefix" />
-
-
- <xsl:template match="/expr/list">
- <xsl:choose>
- <xsl:when test="$documentType = 'appendix'">
- <appendix xml:id="appendix-configuration-options">
- <title>Configuration Options</title>
- <xsl:call-template name="variable-list"/>
- </appendix>
- </xsl:when>
- <xsl:otherwise>
- <xsl:call-template name="variable-list"/>
- </xsl:otherwise>
- </xsl:choose>
- </xsl:template>
-
- <xsl:template name="variable-list">
- <variablelist>
- <xsl:attribute name="id" namespace="http://www.w3.org/XML/1998/namespace"><xsl:value-of select="$variablelistId"/></xsl:attribute>
- <xsl:for-each select="attrs">
- <xsl:variable name="id" select="
- concat($optionIdPrefix,
- translate(
- attr[@name = 'name']/string/@value,
- '*&lt; >[]:&quot;',
- '________'
- ))" />
- <varlistentry>
- <term xlink:href="#{$id}">
- <xsl:attribute name="xml:id"><xsl:value-of select="$id"/></xsl:attribute>
- <option>
- <xsl:value-of select="attr[@name = 'name']/string/@value" />
- </option>
- </term>
-
- <listitem>
-
- <xsl:value-of disable-output-escaping="yes"
- select="attr[@name = 'description']/string/@value" />
-
- <xsl:if test="attr[@name = 'type']">
- <para>
- <emphasis>Type:</emphasis>
- <xsl:text> </xsl:text>
- <xsl:value-of select="attr[@name = 'type']/string/@value"/>
- <xsl:if test="attr[@name = 'readOnly']/bool/@value = 'true'">
- <xsl:text> </xsl:text>
- <emphasis>(read only)</emphasis>
- </xsl:if>
- </para>
- </xsl:if>
-
- <xsl:if test="attr[@name = 'default-db']">
- <xsl:value-of disable-output-escaping="yes"
- select="attr[@name = 'default-db']/string/@value" />
- </xsl:if>
-
- <xsl:if test="attr[@name = 'example-db']">
- <xsl:value-of disable-output-escaping="yes"
- select="attr[@name = 'example-db']/string/@value" />
- </xsl:if>
-
- <xsl:if test="attr[@name = 'relatedPackages']">
- <para>
- <emphasis>Related packages:</emphasis>
- </para>
- <xsl:value-of disable-output-escaping="yes"
- select="attr[@name = 'relatedPackages']/string/@value" />
- </xsl:if>
-
- <xsl:if test="count(attr[@name = 'declarations']/list/*) != 0">
- <para>
- <emphasis>Declared by:</emphasis>
- </para>
- <xsl:apply-templates select="attr[@name = 'declarations']" />
- </xsl:if>
-
- <xsl:if test="count(attr[@name = 'definitions']/list/*) != 0">
- <para>
- <emphasis>Defined by:</emphasis>
- </para>
- <xsl:apply-templates select="attr[@name = 'definitions']" />
- </xsl:if>
-
- </listitem>
-
- </varlistentry>
-
- </xsl:for-each>
-
- </variablelist>
- </xsl:template>
-
-
- <xsl:template match="attrs[attr[@name = '_type' and string[@value = 'literalDocBook']]]" mode = "top">
- <xsl:value-of disable-output-escaping="yes" select="attr[@name = 'text']/string/@value" />
- </xsl:template>
-
-
- <xsl:template match="attr[@name = 'declarations' or @name = 'definitions']">
- <simplelist>
- <!--
- Example:
- opt.declarations = [ { name = "foo/bar.nix"; url = "https://github.com/....."; } ];
- -->
- <xsl:for-each select="list/attrs[attr[@name = 'name']]">
- <member><filename>
- <xsl:if test="attr[@name = 'url']">
- <xsl:attribute name="xlink:href"><xsl:value-of select="attr[@name = 'url']/string/@value"/></xsl:attribute>
- </xsl:if>
- <xsl:value-of select="attr[@name = 'name']/string/@value"/>
- </filename></member>
- </xsl:for-each>
-
- <!--
- When the declarations/definitions are raw strings,
- fall back to hardcoded location logic, specific to Nixpkgs.
- -->
- <xsl:for-each select="list/string">
- <member><filename>
- <!-- Hyperlink the filename either to the NixOS Subversion
- repository (if it’s a module and we have a revision number),
- or to the local filesystem. -->
- <xsl:choose>
- <xsl:when test="not(starts-with(@value, '/'))">
- <xsl:choose>
- <xsl:when test="$revision = 'local'">
- <xsl:attribute name="xlink:href">https://github.com/NixOS/nixpkgs/blob/master/<xsl:value-of select="@value"/></xsl:attribute>
- </xsl:when>
- <xsl:otherwise>
- <xsl:attribute name="xlink:href">https://github.com/NixOS/nixpkgs/blob/<xsl:value-of select="$revision"/>/<xsl:value-of select="@value"/></xsl:attribute>
- </xsl:otherwise>
- </xsl:choose>
- </xsl:when>
- <xsl:when test="$revision != 'local' and $program = 'nixops' and contains(@value, '/nix/')">
- <xsl:attribute name="xlink:href">https://github.com/NixOS/nixops/blob/<xsl:value-of select="$revision"/>/nix/<xsl:value-of select="substring-after(@value, '/nix/')"/></xsl:attribute>
- </xsl:when>
- <xsl:otherwise>
- <xsl:attribute name="xlink:href">file://<xsl:value-of select="@value"/></xsl:attribute>
- </xsl:otherwise>
- </xsl:choose>
- <!-- Print the filename and make it user-friendly by replacing the
- /nix/store/<hash> prefix by the default location of nixos
- sources. -->
- <xsl:choose>
- <xsl:when test="not(starts-with(@value, '/'))">
- &lt;nixpkgs/<xsl:value-of select="@value"/>&gt;
- </xsl:when>
- <xsl:when test="contains(@value, 'nixops') and contains(@value, '/nix/')">
- &lt;nixops/<xsl:value-of select="substring-after(@value, '/nix/')"/>&gt;
- </xsl:when>
- <xsl:otherwise>
- <xsl:value-of select="@value" />
- </xsl:otherwise>
- </xsl:choose>
- </filename></member>
- </xsl:for-each>
- </simplelist>
- </xsl:template>
-
-</xsl:stylesheet>
diff --git a/nixos/lib/make-options-doc/optionsJSONtoXML.nix b/nixos/lib/make-options-doc/optionsJSONtoXML.nix
deleted file mode 100644
index ba50c5f898b5..000000000000
--- a/nixos/lib/make-options-doc/optionsJSONtoXML.nix
+++ /dev/null
@@ -1,6 +0,0 @@
-{ file }:
-
-builtins.attrValues
- (builtins.mapAttrs
- (name: def: def // { inherit name; })
- (builtins.fromJSON (builtins.readFile file)))
diff --git a/nixos/lib/make-options-doc/optionsToDocbook.py b/nixos/lib/make-options-doc/optionsToDocbook.py
new file mode 100644
index 000000000000..021623d10a7a
--- /dev/null
+++ b/nixos/lib/make-options-doc/optionsToDocbook.py
@@ -0,0 +1,343 @@
+import collections
+import json
+import os
+import sys
+from typing import Any, Dict, List
+from collections.abc import MutableMapping, Sequence
+import inspect
+
+# for MD conversion
+import markdown_it
+import markdown_it.renderer
+from markdown_it.token import Token
+from markdown_it.utils import OptionsDict
+from mdit_py_plugins.container import container_plugin
+from mdit_py_plugins.deflist import deflist_plugin
+from mdit_py_plugins.myst_role import myst_role_plugin
+from xml.sax.saxutils import escape, quoteattr
+
+manpage_urls = json.load(open(os.getenv('MANPAGE_URLS')))
+
+class Renderer(markdown_it.renderer.RendererProtocol):
+ __output__ = "docbook"
+ def __init__(self, parser=None):
+ self.rules = {
+ k: v
+ for k, v in inspect.getmembers(self, predicate=inspect.ismethod)
+ if not (k.startswith("render") or k.startswith("_"))
+ } | {
+ "container_{.note}_open": self._note_open,
+ "contain