From be3a599628fa7b6d1ae369a7903e91dc256c1665 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 27 Apr 2026 15:00:01 +0200 Subject: [PATCH 01/12] MAINTAINERS: add an entry for media maintainers profile The media subsystem has a maintainers entry profile, but its entry is missing at MAINTAINERS. Add it. Acked-by: Randy Dunlap Signed-off-by: Mauro Carvalho Chehab Message-ID: <5af4aa6a716228eea4d59dc26b97d642e1e7d419.1776176108.git.mchehab+huawei@kernel.org> Signed-off-by: Linux RISC-V bot --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index 2fb1c75afd1638..f52ec50f6d10b4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -16223,6 +16223,7 @@ P: Documentation/driver-api/media/maintainer-entry-profile.rst W: https://linuxtv.org Q: https://patchwork.linuxtv.org/project/linux-media/list/ T: git git://linuxtv.org/media.git +P: Documentation/driver-api/media/maintainer-entry-profile.rst F: Documentation/admin-guide/media/ F: Documentation/devicetree/bindings/media/ F: Documentation/driver-api/media/ From ef789628359775b86e695772ca299afe99ebe4b2 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 27 Apr 2026 15:00:02 +0200 Subject: [PATCH 02/12] MAINTAINERS: add maintainer-tip.rst to X86 The X86 subsystem has a maintainers entry profile, but its entry is missing at MAINTAINERS. Add it. Acked-by: Randy Dunlap Acked-by: Dan Williams Signed-off-by: Mauro Carvalho Chehab Message-ID: <970434c647aa1e1e9a81c87b4d5fed934d4018a7.1776176108.git.mchehab+huawei@kernel.org> Signed-off-by: Linux RISC-V bot --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index f52ec50f6d10b4..a00d4ba61c2a85 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -28808,6 +28808,7 @@ M: Ingo Molnar M: Borislav Petkov M: Dave Hansen M: x86@kernel.org +P: Documentation/process/maintainer-tip.rst R: "H. Peter Anvin" L: linux-kernel@vger.kernel.org S: Maintained From e41a91951f6db35c3e4c839cb3f3c79ab288e623 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 27 Apr 2026 15:00:03 +0200 Subject: [PATCH 03/12] docs: maintainers: add SPDX license to the file While this file is really trivial, add a SPDX license line on it. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Linux RISC-V bot --- Documentation/process/maintainers.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/process/maintainers.rst b/Documentation/process/maintainers.rst index 6174cfb4138ffc..5d1b1464c3aeac 100644 --- a/Documentation/process/maintainers.rst +++ b/Documentation/process/maintainers.rst @@ -1 +1,3 @@ +.. SPDX-License-Identifier: GPL-2.0 + .. maintainers-include:: From ab3d64e1c4cd9420718b6d7d05492c59af422bd0 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 27 Apr 2026 15:00:04 +0200 Subject: [PATCH 04/12] docs: maintainers_include: auto-generate maintainer profile TOC Add a feature to allow auto-generating media entry profiles from the corresponding field inside MAINTAINERS file(s). Suggested-by: Dan Williams Closes: https://lore.kernel.org/linux-doc/69dd6299440be_147c801005b@djbw-dev.notmuch/ Acked-by: Dan Williams Signed-off-by: Mauro Carvalho Chehab Message-ID: <4e9512a3d05942c98361d06d60a118d7c78762b6.1776176108.git.mchehab+huawei@kernel.org> Signed-off-by: Linux RISC-V bot --- Documentation/sphinx/maintainers_include.py | 93 +++++++++++++++++---- 1 file changed, 76 insertions(+), 17 deletions(-) diff --git a/Documentation/sphinx/maintainers_include.py b/Documentation/sphinx/maintainers_include.py index 519ad18685b23f..1dac83bf1a65bf 100755 --- a/Documentation/sphinx/maintainers_include.py +++ b/Documentation/sphinx/maintainers_include.py @@ -21,6 +21,8 @@ import re import os.path +from textwrap import indent + from docutils import statemachine from docutils.parsers.rst import Directive from docutils.parsers.rst.directives.misc import Include @@ -30,20 +32,11 @@ def ErrorString(exc): # Shamelessly stolen from docutils __version__ = '1.0' -def setup(app): - app.add_directive("maintainers-include", MaintainersInclude) - return dict( - version = __version__, - parallel_read_safe = True, - parallel_write_safe = True - ) +class MaintainersParser: + """Parse MAINTAINERS file(s) content""" -class MaintainersInclude(Include): - """MaintainersInclude (``maintainers-include``) directive""" - required_arguments = 0 - - def parse_maintainers(self, path): - """Parse all the MAINTAINERS lines into ReST for human-readability""" + def __init__(self, base_path, path): + self.profiles = list() result = list() result.append(".. _maintainers:") @@ -78,6 +71,12 @@ def parse_maintainers(self, path): # Drop needless input whitespace. line = line.rstrip() + match = re.match(r"P:\s*(Documentation/\S+)\.rst", line) + if match: + fname = os.path.relpath(match.group(1), base_path) + if fname not in self.profiles: + self.profiles.append(fname) + # Linkify all non-wildcard refs to ReST files in Documentation/. pat = r'(Documentation/([^\s\?\*]*)\.rst)' m = re.search(pat, line) @@ -165,12 +164,62 @@ def parse_maintainers(self, path): 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, base_path, path): + """Parse all the MAINTAINERS lines into ReST for human-readability""" + + output = MaintainersParser(base_path, path).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_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") + base_path = os.path.dirname(self.state.document.document.current_source) + + try: + self.state.document.settings.record_dependencies.add(path) + lines = self.emit(base_path, path) + 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, base_path, path): + """Parse all the MAINTAINERS lines looking for profile entries""" + + profiles = MaintainersParser(base_path, path).profiles + + output = ".. toctree::\n" + output += " :maxdepth: 2\n\n" + output += indent("\n".join(profiles), " ") + + self.state_machine.insert_input(statemachine.string2lines(output), path) def run(self): """Include the MAINTAINERS file as part of this reST file.""" @@ -186,12 +235,22 @@ def run(self): # Append "MAINTAINERS" path = os.path.join(path, "MAINTAINERS") + base_path = os.path.dirname(self.state.document.document.current_source) try: self.state.document.settings.record_dependencies.add(path) - lines = self.parse_maintainers(path) + lines = self.emit(base_path, path) except IOError as error: raise self.severe('Problems with "%s" directive path:\n%s.' % (self.name, ErrorString(error))) return [] + +def setup(app): + 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 + ) From e0a82014cf6d5366792980127d7c527e032e3176 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 27 Apr 2026 15:00:05 +0200 Subject: [PATCH 05/12] docs: auto-generate maintainer entry profile links Instead of manually creating a TOC tree for them, use the new tag to auto-generate its TOC. Co-developed-by: Dan Williams Signed-off-by: Dan Williams Signed-off-by: Mauro Carvalho Chehab Message-ID: <9228f77b0339b8e5dea4a201ab6d4feb30cef5c2.1776176108.git.mchehab+huawei@kernel.org> Signed-off-by: Linux RISC-V bot --- .../maintainer/maintainer-entry-profile.rst | 26 ++++--------------- .../process/maintainer-handbooks.rst | 19 +++++++------- 2 files changed, 15 insertions(+), 30 deletions(-) diff --git a/Documentation/maintainer/maintainer-entry-profile.rst b/Documentation/maintainer/maintainer-entry-profile.rst index 6020d188e13de1..58e2af333692dc 100644 --- a/Documentation/maintainer/maintainer-entry-profile.rst +++ b/Documentation/maintainer/maintainer-entry-profile.rst @@ -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 ------------------ - -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 +Maintainer Handbooks +-------------------- + +For examples of other subsystem handbooks see +Documentation/process/maintainer-handbooks.rst. diff --git a/Documentation/process/maintainer-handbooks.rst b/Documentation/process/maintainer-handbooks.rst index 3d72ad25fc6acc..531985a0fae810 100644 --- a/Documentation/process/maintainer-handbooks.rst +++ b/Documentation/process/maintainer-handbooks.rst @@ -7,14 +7,15 @@ The purpose of this document is to provide subsystem specific information which is supplementary to the general development process handbook :ref:`Documentation/process `. -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. + +For maintainers, consider documenting additional requirements and +expectations if submissions routinely overlook specific submission +criteria. See Documentation/maintainer/maintainer-entry-profile.rst. -.. toctree:: - :numbered: - :maxdepth: 2 +Contents: - maintainer-netdev - maintainer-soc - maintainer-soc-clean-dts - maintainer-tip - maintainer-kvm-x86 +.. maintainers-profile-toc:: From 5c13050e76bba5108e9103d93cc6bd4d2d9a88e5 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 27 Apr 2026 15:00:06 +0200 Subject: [PATCH 06/12] docs: maintainers_include: use a better title for profiles As we're picking the name of the subsystem from MAINTAINERS, also use its subsystem name for the titles. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Linux RISC-V bot --- Documentation/sphinx/maintainers_include.py | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/Documentation/sphinx/maintainers_include.py b/Documentation/sphinx/maintainers_include.py index 1dac83bf1a65bf..cf428db7599cc1 100755 --- a/Documentation/sphinx/maintainers_include.py +++ b/Documentation/sphinx/maintainers_include.py @@ -36,7 +36,7 @@ class MaintainersParser: """Parse MAINTAINERS file(s) content""" def __init__(self, base_path, path): - self.profiles = list() + self.profiles = {} result = list() result.append(".. _maintainers:") @@ -54,6 +54,7 @@ def __init__(self, base_path, path): prev = None field_prev = "" field_content = "" + subsystem_name = None for line in open(path): # Have we reached the end of the preformatted Descriptions text? @@ -75,7 +76,10 @@ def __init__(self, base_path, path): if match: fname = os.path.relpath(match.group(1), base_path) if fname not in self.profiles: - self.profiles.append(fname) + if self.profiles.get(fname) is None: + self.profiles[fname] = subsystem_name + else: + self.profiles[fname] += f", {subsystem_name}" # Linkify all non-wildcard refs to ReST files in Documentation/. pat = r'(Documentation/([^\s\?\*]*)\.rst)' @@ -112,6 +116,8 @@ def __init__(self, base_path, path): 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)) @@ -217,7 +223,13 @@ def emit(self, base_path, path): output = ".. toctree::\n" output += " :maxdepth: 2\n\n" - output += indent("\n".join(profiles), " ") + + items = sorted(profiles.items(), key=lambda kv: (kv[1] or "", kv[0])) + for fname, profile in items: + if profile: + output += f" {profile} <{fname}>\n" + else: + output += f" {fname}\n" self.state_machine.insert_input(statemachine.string2lines(output), path) From 67188f39755f4b3ba31c85eddcce1539ae2d26d4 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 27 Apr 2026 15:00:07 +0200 Subject: [PATCH 07/12] docs: maintainers_include: add external profile URLs Some subsystem profiles are maintained elsewhere. Add them to the output. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Linux RISC-V bot --- Documentation/sphinx/maintainers_include.py | 28 +++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/Documentation/sphinx/maintainers_include.py b/Documentation/sphinx/maintainers_include.py index cf428db7599cc1..f1b8d4b00c2adc 100755 --- a/Documentation/sphinx/maintainers_include.py +++ b/Documentation/sphinx/maintainers_include.py @@ -37,6 +37,7 @@ class MaintainersParser: def __init__(self, base_path, path): self.profiles = {} + self.profile_urls = {} result = list() result.append(".. _maintainers:") @@ -81,6 +82,16 @@ def __init__(self, base_path, path): else: self.profiles[fname] += f", {subsystem_name}" + match = re.match(r"P:\s*(https?://.*)", line) + if match: + url = match.group(1).strip() + if url not in self.profile_urls: + if self.profile_urls.get(url) is None: + self.profile_urls[url] = subsystem_name + else: + self.profile_urls[url] += f", {subsystem_name}" + + # Linkify all non-wildcard refs to ReST files in Documentation/. pat = r'(Documentation/([^\s\?\*]*)\.rst)' m = re.search(pat, line) @@ -219,18 +230,31 @@ class MaintainersProfile(Include): def emit(self, base_path, path): """Parse all the MAINTAINERS lines looking for profile entries""" - profiles = MaintainersParser(base_path, path).profiles + maint = MaintainersParser(base_path, path) output = ".. toctree::\n" output += " :maxdepth: 2\n\n" - items = sorted(profiles.items(), key=lambda kv: (kv[1] or "", kv[0])) + items = sorted(maint.profiles.items(), + key=lambda kv: (kv[1] or "", kv[0])) for fname, profile in items: if profile: output += f" {profile} <{fname}>\n" else: output += f" {fname}\n" + output += "\n**External profiles**\n\n" + + items = sorted(maint.profile_urls.items(), + key=lambda kv: (kv[1] or "", kv[0])) + for url, profile in items: + if profile: + output += f"- {profile} <{url}>\n" + else: + output += f"- {url}\n" + + output += "\n" + self.state_machine.insert_input(statemachine.string2lines(output), path) def run(self): From 420ca746baa518fd5d565376f3223a7ab0474b37 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 27 Apr 2026 15:00:08 +0200 Subject: [PATCH 08/12] docs: maintainers_include: preserve names for files under process/ When a maintainer's profile is stored outside process, they're already included on some other book and the name of the filesystem may not be there. That's why the logic picks the name from the subsystem's name. However, files directly placed together with maintainers-handbooks.rst (e.g. under Documentation/process/) is a different history: those aren't placed anywhere, so we can keep using their own names, letting Sphinx do his thing. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Linux RISC-V bot --- Documentation/sphinx/maintainers_include.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Documentation/sphinx/maintainers_include.py b/Documentation/sphinx/maintainers_include.py index f1b8d4b00c2adc..948746b998a358 100755 --- a/Documentation/sphinx/maintainers_include.py +++ b/Documentation/sphinx/maintainers_include.py @@ -76,11 +76,13 @@ def __init__(self, base_path, path): match = re.match(r"P:\s*(Documentation/\S+)\.rst", line) if match: fname = os.path.relpath(match.group(1), base_path) - if fname not in self.profiles: + if fname.startswith("../"): if self.profiles.get(fname) is None: self.profiles[fname] = subsystem_name else: self.profiles[fname] += f", {subsystem_name}" + else: + self.profiles[fname] = None match = re.match(r"P:\s*(https?://.*)", line) if match: From ba3f67ad3f36b25f344b16a2fd0a29aac492acd8 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 27 Apr 2026 15:00:09 +0200 Subject: [PATCH 09/12] docs: maintainers_include: Only show main entry for profiles Instead of showing as a "Contents:" with 2 identation levels, drop its title and show profiles as a list of entries. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Linux RISC-V bot --- Documentation/process/maintainer-handbooks.rst | 2 -- Documentation/sphinx/maintainers_include.py | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/Documentation/process/maintainer-handbooks.rst b/Documentation/process/maintainer-handbooks.rst index 531985a0fae810..3821e78aefc0ab 100644 --- a/Documentation/process/maintainer-handbooks.rst +++ b/Documentation/process/maintainer-handbooks.rst @@ -16,6 +16,4 @@ For maintainers, consider documenting additional requirements and expectations if submissions routinely overlook specific submission criteria. See Documentation/maintainer/maintainer-entry-profile.rst. -Contents: - .. maintainers-profile-toc:: diff --git a/Documentation/sphinx/maintainers_include.py b/Documentation/sphinx/maintainers_include.py index 948746b998a358..7ab92182061277 100755 --- a/Documentation/sphinx/maintainers_include.py +++ b/Documentation/sphinx/maintainers_include.py @@ -235,7 +235,7 @@ def emit(self, base_path, path): maint = MaintainersParser(base_path, path) output = ".. toctree::\n" - output += " :maxdepth: 2\n\n" + output += " :maxdepth: 1\n\n" items = sorted(maint.profiles.items(), key=lambda kv: (kv[1] or "", kv[0])) From 342830df41d00b606b9d5b95a8f1e486ab6961ae Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 27 Apr 2026 15:00:10 +0200 Subject: [PATCH 10/12] docs: maintainers_include: improve its output There are three "types" of profiles: 1. Profiles already included inside subsystem-specific documentation. This is the most common case; 2. Profiles that are hosted externally; 3. Profiles that are at the same location as maintainer-handbooks.rst. For (3), we need to create a TOC, as they don't exist elsewhere. Change the logic to create TOC just for (3), prepending the content of maintainer-handbooks with a sorted entry of all types, before the TOC. With such change, we can have an unique sorted list of profiles, having the subsystem names used there listed. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Linux RISC-V bot --- Documentation/sphinx/maintainers_include.py | 76 +++++++++++---------- 1 file changed, 40 insertions(+), 36 deletions(-) diff --git a/Documentation/sphinx/maintainers_include.py b/Documentation/sphinx/maintainers_include.py index 7ab92182061277..5413c1350bbafe 100755 --- a/Documentation/sphinx/maintainers_include.py +++ b/Documentation/sphinx/maintainers_include.py @@ -21,7 +21,7 @@ import re import os.path -from textwrap import indent +from glob import glob from docutils import statemachine from docutils.parsers.rst import Directive @@ -36,8 +36,8 @@ class MaintainersParser: """Parse MAINTAINERS file(s) content""" def __init__(self, base_path, path): - self.profiles = {} - self.profile_urls = {} + self.profile_toc = set() + self.profile_entries = {} result = list() result.append(".. _maintainers:") @@ -73,26 +73,24 @@ def __init__(self, base_path, path): # Drop needless input whitespace. line = line.rstrip() + # + # Handle profile entries - either as files or as https refs + # match = re.match(r"P:\s*(Documentation/\S+)\.rst", line) if match: - fname = os.path.relpath(match.group(1), base_path) - if fname.startswith("../"): - if self.profiles.get(fname) is None: - self.profiles[fname] = subsystem_name - else: - self.profiles[fname] += f", {subsystem_name}" + entry = os.path.relpath(match.group(1), base_path) + if "*" in entry: + for e in glob(entry): + self.profile_toc.add(e) + self.profile_entries[subsystem_name] = e else: - self.profiles[fname] = None - - match = re.match(r"P:\s*(https?://.*)", line) - if match: - url = match.group(1).strip() - if url not in self.profile_urls: - if self.profile_urls.get(url) is None: - self.profile_urls[url] = subsystem_name - else: - self.profile_urls[url] += f", {subsystem_name}" - + 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)' @@ -234,26 +232,32 @@ def emit(self, base_path, path): maint = MaintainersParser(base_path, path) - output = ".. toctree::\n" - output += " :maxdepth: 1\n\n" + # + # Produce a list with all maintainer profiles, sorted by subsystem name + # + output = "" - items = sorted(maint.profiles.items(), - key=lambda kv: (kv[1] or "", kv[0])) - for fname, profile in items: - if profile: - output += f" {profile} <{fname}>\n" + for profile, entry in maint.profile_entries.items(): + if entry.startswith("http"): + if profile: + output += f"- `{profile} <{entry}>`_\n" + else: + output += f"- `<{entry}>_`\n" else: - output += f" {fname}\n" + if profile: + output += f"- :doc:`{profile} <{entry}>`\n" + else: + output += f"- :doc:`<{entry}>`\n" - output += "\n**External profiles**\n\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" - items = sorted(maint.profile_urls.items(), - key=lambda kv: (kv[1] or "", kv[0])) - for url, profile in items: - if profile: - output += f"- {profile} <{url}>\n" - else: - output += f"- {url}\n" + for fname in maint.profile_toc: + output += f" {fname}\n" output += "\n" From 931c2e82085048a58e06c156f012d190b5688664 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 27 Apr 2026 15:00:11 +0200 Subject: [PATCH 11/12] docs: maintainers_include: fix support for O=dir os.path.relpath() will do the wrong thing with O=dir, as the build system uses "cd " internally. Solve it by using app.srcdir, which, on normal cases, point to Documentation/, or, when SPHINXDIRS=process, it will be set with Documentation/process. While here, remove a dead code while writing maintainer profiles, as now all entries should have both profile and entry. Reported-by: Randy Dunlap Closes: https://lore.kernel.org/linux-doc/88335220-3527-4b1f-9500-417f7ebb7a02@infradead.org/T/#m6854cbd8d30e2c5d3e8c4173bae1c3d6922ff970 Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Linux RISC-V bot --- Documentation/sphinx/maintainers_include.py | 71 +++++++++++++++------ 1 file changed, 50 insertions(+), 21 deletions(-) diff --git a/Documentation/sphinx/maintainers_include.py b/Documentation/sphinx/maintainers_include.py index 5413c1350bbafe..ae52e8198750f3 100755 --- a/Documentation/sphinx/maintainers_include.py +++ b/Documentation/sphinx/maintainers_include.py @@ -27,15 +27,24 @@ 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' +app_dir = "." + class MaintainersParser: """Parse MAINTAINERS file(s) content""" - def __init__(self, base_path, path): + def __init__(self, path): + global app_dir + self.profile_toc = set() self.profile_entries = {} @@ -57,6 +66,9 @@ def __init__(self, base_path, path): field_content = "" subsystem_name = None + base_dir, doc_dir, sphinx_dir = app_dir.partition("Documentation") + print("BASE DIR", base_dir) + for line in open(path): # Have we reached the end of the preformatted Descriptions text? if descriptions and line.startswith('Maintainers'): @@ -76,9 +88,25 @@ def __init__(self, base_path, path): # # Handle profile entries - either as files or as https refs # - match = re.match(r"P:\s*(Documentation/\S+)\.rst", line) + match = re.match(rf"P:\s*({doc_dir})(/\S+)\.rst", line) if match: - entry = os.path.relpath(match.group(1), base_path) + 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 + + print(f"{name}: entry: {entry} FULL: {full_name} path: {path}") + if "*" in entry: for e in glob(entry): self.profile_toc.add(e) @@ -189,10 +217,10 @@ class MaintainersInclude(Include): """MaintainersInclude (``maintainers-include``) directive""" required_arguments = 0 - def emit(self, base_path, path): + def emit(self, path): """Parse all the MAINTAINERS lines into ReST for human-readability""" - output = MaintainersParser(base_path, path).output + output = MaintainersParser(path).output # For debugging the pre-rendered results... #print(output, file=open("/tmp/MAINTAINERS.rst", "w")) @@ -213,11 +241,10 @@ def run(self): # Append "MAINTAINERS" path = os.path.join(path, "MAINTAINERS") - base_path = os.path.dirname(self.state.document.document.current_source) try: self.state.document.settings.record_dependencies.add(path) - lines = self.emit(base_path, path) + lines = self.emit(path) except IOError as error: raise self.severe('Problems with "%s" directive path:\n%s.' % (self.name, ErrorString(error))) @@ -227,27 +254,20 @@ def run(self): class MaintainersProfile(Include): required_arguments = 0 - def emit(self, base_path, path): + def emit(self, path): """Parse all the MAINTAINERS lines looking for profile entries""" - maint = MaintainersParser(base_path, path) + maint = MaintainersParser(path) # # Produce a list with all maintainer profiles, sorted by subsystem name # output = "" - - for profile, entry in maint.profile_entries.items(): + for profile, entry in sorted(maint.profile_entries.items()): if entry.startswith("http"): - if profile: - output += f"- `{profile} <{entry}>`_\n" - else: - output += f"- `<{entry}>_`\n" + output += f"- `{profile} <{entry}>`_\n" else: - if profile: - output += f"- :doc:`{profile} <{entry}>`\n" - else: - output += f"- :doc:`<{entry}>`\n" + output += f"- :doc:`{profile} <{entry}>`\n" # # Create a hidden TOC table with all profiles. That allows adding @@ -261,6 +281,8 @@ def emit(self, base_path, path): output += "\n" + print(output) + self.state_machine.insert_input(statemachine.string2lines(output), path) def run(self): @@ -277,11 +299,10 @@ def run(self): # Append "MAINTAINERS" path = os.path.join(path, "MAINTAINERS") - base_path = os.path.dirname(self.state.document.document.current_source) try: self.state.document.settings.record_dependencies.add(path) - lines = self.emit(base_path, path) + lines = self.emit(path) except IOError as error: raise self.severe('Problems with "%s" directive path:\n%s.' % (self.name, ErrorString(error))) @@ -289,6 +310,14 @@ def run(self): return [] def setup(app): + global app_dir + + # + # 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) + app.add_directive("maintainers-include", MaintainersInclude) app.add_directive("maintainers-profile-toc", MaintainersProfile) return dict( From 527bde154bf25fadb7d7fd52d9aa135df5913fbb Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 27 Apr 2026 15:00:12 +0200 Subject: [PATCH 12/12] docs: maintainers_include: parse MAINTAINERS just once Change the logic to parse MAINTAINERS file content just once, while still allowing using it multiple times. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Linux RISC-V bot --- Documentation/sphinx/maintainers_include.py | 61 +++++++-------------- 1 file changed, 21 insertions(+), 40 deletions(-) diff --git a/Documentation/sphinx/maintainers_include.py b/Documentation/sphinx/maintainers_include.py index ae52e8198750f3..436e7ac42ffc0d 100755 --- a/Documentation/sphinx/maintainers_include.py +++ b/Documentation/sphinx/maintainers_include.py @@ -37,14 +37,13 @@ def ErrorString(exc): # Shamelessly stolen from docutils __version__ = '1.0' -app_dir = "." +maint_parser = None class MaintainersParser: """Parse MAINTAINERS file(s) content""" - def __init__(self, path): - global app_dir - + def __init__(self, app_dir, path): + self.path = path self.profile_toc = set() self.profile_entries = {} @@ -67,7 +66,6 @@ def __init__(self, path): subsystem_name = None base_dir, doc_dir, sphinx_dir = app_dir.partition("Documentation") - print("BASE DIR", base_dir) for line in open(path): # Have we reached the end of the preformatted Descriptions text? @@ -105,8 +103,6 @@ def __init__(self, path): else: entry = "/" + entry - print(f"{name}: entry: {entry} FULL: {full_name} path: {path}") - if "*" in entry: for e in glob(entry): self.profile_toc.add(e) @@ -217,14 +213,17 @@ class MaintainersInclude(Include): """MaintainersInclude (``maintainers-include``) directive""" required_arguments = 0 - def emit(self, path): + def emit(self): """Parse all the MAINTAINERS lines into ReST for human-readability""" + global maint_parser - output = MaintainersParser(path).output + path = maint_parser.path + output = maint_parser.output # For debugging the pre-rendered results... #print(output, file=open("/tmp/MAINTAINERS.rst", "w")) + self.state.document.settings.record_dependencies.add(path) self.state_machine.insert_input(statemachine.string2lines(output), path) def run(self): @@ -232,19 +231,8 @@ def run(self): 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.emit(path) + lines = self.emit() except IOError as error: raise self.severe('Problems with "%s" directive path:\n%s.' % (self.name, ErrorString(error))) @@ -254,16 +242,17 @@ def run(self): class MaintainersProfile(Include): required_arguments = 0 - def emit(self, path): + def emit(self): """Parse all the MAINTAINERS lines looking for profile entries""" + global maint_parser - maint = MaintainersParser(path) + path = maint_parser.path # # Produce a list with all maintainer profiles, sorted by subsystem name # output = "" - for profile, entry in sorted(maint.profile_entries.items()): + for profile, entry in sorted(maint_parser.profile_entries.items()): if entry.startswith("http"): output += f"- `{profile} <{entry}>`_\n" else: @@ -276,13 +265,12 @@ def emit(self, path): output += "\n.. toctree::\n" output += " :hidden:\n\n" - for fname in maint.profile_toc: + for fname in maint_parser.profile_toc: output += f" {fname}\n" output += "\n" - print(output) - + self.state.document.settings.record_dependencies.add(path) self.state_machine.insert_input(statemachine.string2lines(output), path) def run(self): @@ -290,19 +278,8 @@ def run(self): 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.emit(path) + lines = self.emit() except IOError as error: raise self.severe('Problems with "%s" directive path:\n%s.' % (self.name, ErrorString(error))) @@ -310,13 +287,17 @@ def run(self): return [] def setup(app): - global app_dir + 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)