Merge branch 'mauro' into docs-mw

Mauro says:

This patch series change the way maintainer entry profile links
are added to the documentation. Instead of having an entry for
each of them at an ReST file, get them from MAINTAINERS content.

That should likely make easier to maintain, as there will be a single
point to place all such profiles.

The output is a per-subsystem sorted (*) series of links shown as a
list like this:

    - Arm And Arm64 Soc Sub-Architectures (Common Parts)
    - Arm/Samsung S3C, S5P And Exynos Arm Architectures
    - Arm/Tesla Fsd Soc Support
    ...
    - Xfs Filesystem

Please notice that the series is doing one logical change per patch.
I could have merged some changes altogether, but I opted doing it
in small steps to help reviews. If you prefer, feel free to merge
maintainers_include changes on merge.

There is one interesting side effect of this series: there is no
need to add rst files containing profiles inside a TOC tree: Just
creating the file anywhere inside Documentation and adding a P entry
is enough. Adding them to a TOC won't hurt.
This commit is contained in:
Jonathan Corbet 2026-05-03 09:49:52 -06:00
commit 709061c5d2
4 changed files with 152 additions and 56 deletions

View File

@ -92,24 +92,8 @@ full series, or privately send a reminder email. This section might also
list how review works for this code area and methods to get feedback
that are not directly from the maintainer.
Existing profiles
-----------------
Maintainer Handbooks
--------------------
For now, existing maintainer profiles are listed here; we will likely want
to do something different in the near future.
.. toctree::
:maxdepth: 1
../doc-guide/maintainer-profile
../nvdimm/maintainer-entry-profile
../arch/riscv/patch-acceptance
../process/maintainer-soc
../process/maintainer-soc-clean-dts
../driver-api/media/maintainer-entry-profile
../process/maintainer-netdev
../driver-api/vfio-pci-device-specific-driver-acceptance
../nvme/feature-and-quirk-policy
../filesystems/nfs/nfsd-maintainer-entry-profile
../filesystems/xfs/xfs-maintainer-entry-profile
../mm/damon/maintainer-profile
For examples of other subsystem handbooks see
Documentation/process/maintainer-handbooks.rst.

View File

@ -7,14 +7,13 @@ The purpose of this document is to provide subsystem specific information
which is supplementary to the general development process handbook
:ref:`Documentation/process <development_process_main>`.
Contents:
For developers, see below for all the known subsystem specific guides.
If the subsystem you are contributing to does not have a guide listed
here, it is fair to seek clarification of questions raised in
Documentation/maintainer/maintainer-entry-profile.rst.
.. toctree::
:numbered:
:maxdepth: 2
For maintainers, consider documenting additional requirements and
expectations if submissions routinely overlook specific submission
criteria. See Documentation/maintainer/maintainer-entry-profile.rst.
maintainer-netdev
maintainer-soc
maintainer-soc-clean-dts
maintainer-tip
maintainer-kvm-x86
.. maintainers-profile-toc::

View File

@ -1 +1,3 @@
.. SPDX-License-Identifier: GPL-2.0
.. maintainers-include::

View File

@ -21,29 +21,31 @@ import sys
import re
import os.path
from glob import glob
from docutils import statemachine
from docutils.parsers.rst import Directive
from docutils.parsers.rst.directives.misc import Include
#
# Base URL for intersphinx-like links to maintainer profiles
#
KERNELDOC_URL = "https://docs.kernel.org/"
def ErrorString(exc): # Shamelessly stolen from docutils
return f'{exc.__class__.__name}: {exc}'
__version__ = '1.0'
def setup(app):
app.add_directive("maintainers-include", MaintainersInclude)
return dict(
version = __version__,
parallel_read_safe = True,
parallel_write_safe = True
)
maint_parser = None
class MaintainersInclude(Include):
"""MaintainersInclude (``maintainers-include``) directive"""
required_arguments = 0
class MaintainersParser:
"""Parse MAINTAINERS file(s) content"""
def parse_maintainers(self, path):
"""Parse all the MAINTAINERS lines into ReST for human-readability"""
def __init__(self, app_dir, path):
self.path = path
self.profile_toc = set()
self.profile_entries = {}
result = list()
result.append(".. _maintainers:")
@ -61,6 +63,9 @@ class MaintainersInclude(Include):
prev = None
field_prev = ""
field_content = ""
subsystem_name = None
base_dir, doc_dir, sphinx_dir = app_dir.partition("Documentation")
for line in open(path):
# Have we reached the end of the preformatted Descriptions text?
@ -78,6 +83,39 @@ class MaintainersInclude(Include):
# Drop needless input whitespace.
line = line.rstrip()
#
# Handle profile entries - either as files or as https refs
#
match = re.match(rf"P:\s*({doc_dir})(/\S+)\.rst", line)
if match:
name = "".join(match.groups())
entry = os.path.relpath(base_dir + name, app_dir)
full_name = os.path.join(base_dir, name)
path = os.path.relpath(full_name, app_dir)
#
# When SPHINXDIRS is used, it will try to reference files
# outside srctree, causing warnings. To avoid that, point
# to the latest official documentation
#
if path.startswith("../"):
entry = KERNELDOC_URL + match.group(2) + ".html"
else:
entry = "/" + entry
if "*" in entry:
for e in glob(entry):
self.profile_toc.add(e)
self.profile_entries[subsystem_name] = e
else:
self.profile_toc.add(entry)
self.profile_entries[subsystem_name] = entry
else:
match = re.match(r"P:\s*(https?://.*)", line)
if match:
entry = match.group(1).strip()
self.profile_entries[subsystem_name] = entry
# Linkify all non-wildcard refs to ReST files in Documentation/.
pat = r'(Documentation/([^\s\?\*]*)\.rst)'
m = re.search(pat, line)
@ -113,6 +151,8 @@ class MaintainersInclude(Include):
output = field_content + "\n\n"
field_content = ""
subsystem_name = line.title()
# Collapse whitespace in subsystem name.
heading = re.sub(r"\s+", " ", line)
output = output + "%s\n%s" % (heading, "~" * len(heading))
@ -165,33 +205,104 @@ class MaintainersInclude(Include):
for separated in field_content.split('\n'):
result.append(separated)
output = "\n".join(result)
self.output = "\n".join(result)
# Create a TOC class
class MaintainersInclude(Include):
"""MaintainersInclude (``maintainers-include``) directive"""
required_arguments = 0
def emit(self):
"""Parse all the MAINTAINERS lines into ReST for human-readability"""
global maint_parser
path = maint_parser.path
output = maint_parser.output
# For debugging the pre-rendered results...
#print(output, file=open("/tmp/MAINTAINERS.rst", "w"))
self.state_machine.insert_input(
statemachine.string2lines(output), path)
self.state.document.settings.record_dependencies.add(path)
self.state_machine.insert_input(statemachine.string2lines(output), path)
def run(self):
"""Include the MAINTAINERS file as part of this reST file."""
if not self.state.document.settings.file_insertion_enabled:
raise self.warning('"%s" directive disabled.' % self.name)
# Walk up source path directories to find Documentation/../
path = self.state_machine.document.attributes['source']
path = os.path.realpath(path)
tail = path
while tail != "Documentation" and tail != "":
(path, tail) = os.path.split(path)
# Append "MAINTAINERS"
path = os.path.join(path, "MAINTAINERS")
try:
self.state.document.settings.record_dependencies.add(path)
lines = self.parse_maintainers(path)
lines = self.emit()
except IOError as error:
raise self.severe('Problems with "%s" directive path:\n%s.' %
(self.name, ErrorString(error)))
return []
class MaintainersProfile(Include):
required_arguments = 0
def emit(self):
"""Parse all the MAINTAINERS lines looking for profile entries"""
global maint_parser
path = maint_parser.path
#
# Produce a list with all maintainer profiles, sorted by subsystem name
#
output = ""
for profile, entry in sorted(maint_parser.profile_entries.items()):
if entry.startswith("http"):
output += f"- `{profile} <{entry}>`_\n"
else:
output += f"- :doc:`{profile} <{entry}>`\n"
#
# Create a hidden TOC table with all profiles. That allows adding
# profiles without needing to add them on any index.rst file.
#
output += "\n.. toctree::\n"
output += " :hidden:\n\n"
for fname in maint_parser.profile_toc:
output += f" {fname}\n"
output += "\n"
self.state.document.settings.record_dependencies.add(path)
self.state_machine.insert_input(statemachine.string2lines(output), path)
def run(self):
"""Include the MAINTAINERS file as part of this reST file."""
if not self.state.document.settings.file_insertion_enabled:
raise self.warning('"%s" directive disabled.' % self.name)
try:
lines = self.emit()
except IOError as error:
raise self.severe('Problems with "%s" directive path:\n%s.' %
(self.name, ErrorString(error)))
return []
def setup(app):
global maint_parser
#
# NOTE: we're using os.fspath() here because of a Sphinx warning:
# RemovedInSphinx90Warning: Sphinx 9 will drop support for representing paths as strings. Use "pathlib.Path" or "os.fspath" instead.
#
app_dir = os.fspath(app.srcdir)
srctree = os.path.abspath(os.environ["srctree"])
path = os.path.join(srctree, "MAINTAINERS")
maint_parser = MaintainersParser(app_dir, path)
app.add_directive("maintainers-include", MaintainersInclude)
app.add_directive("maintainers-profile-toc", MaintainersProfile)
return dict(
version = __version__,
parallel_read_safe = True,
parallel_write_safe = True
)