]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
docs: maintainers_include: better handle doc wildcards
authorMauro Carvalho Chehab <mchehab+huawei@kernel.org>
Sat, 9 May 2026 06:56:44 +0000 (08:56 +0200)
committerJonathan Corbet <corbet@lwn.net>
Fri, 15 May 2026 14:01:48 +0000 (08:01 -0600)
As warned by sashiko-bot, the new logic doesn't handle wildcards
on Documentation/.

Change the logic to properly handle it, cleaning up the code
to remove some code duplication.

Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
Signed-off-by: Jonathan Corbet <corbet@lwn.net>
Message-ID: <eb575072d60c20243afee6f94ef71427ef7b2e79.1778309595.git.mchehab+huawei@kernel.org>

Documentation/sphinx/maintainers_include.py

index 8c7b79721eddf4922d5c1db38356f6dd245f0248..be8e566e036358bf54ef95c03984d04bec85e908 100755 (executable)
@@ -95,7 +95,7 @@ class MaintainersParser:
         self.base_dir = base_dir
         self.app_dir = app_dir
 
-        self.re_doc = re.compile(r'(Documentation/([^\s\?\*]*)\.rst)')
+        self.re_doc = re.compile(r'(Documentation/(\S*)\.rst)')
 
         #
         # Output variables with maintainers content to be stored
@@ -132,29 +132,47 @@ class MaintainersParser:
                 # Retain previous line for state machine transitions.
                 prev = line
 
+    def get_entries(self, text):
+        """Generate refs to ReST files in Documentation/"""
+
+        if "Documentation/" not in text:
+            return None
+
+        if "*" in text or "?" in text:
+            m = self.re_doc.search(text)
+            if not m:
+                return None
+
+            doc_list = glob(m.group(1), root_dir=self.base_dir)
+        else:
+            doc_list = [text]
+
+        entries = {}
+        for doc in doc_list:
+            m = self.re_doc.search(doc)
+            if m:
+                fname = m.group(1)
+                ename = m.group(2)
+
+                entry = os.path.relpath(self.base_dir + fname, self.app_dir)
+                entry = entry.removesuffix(".rst")
+
+                if entry.startswith("../"):
+                    html = KERNELDOC_URL + ename + ".html"
+                    entries[entry] = f'`{ename} <{html}>`_'
+                else:
+                    entries[entry] = f':doc:`{ename} </{entry}>`'
+
+        return entries
+
     def linkify(self, text):
-        """Linkify all non-wildcard refs to ReST files in Documentation/"""
+        """Return a list of doc files converted to cross-references"""
 
-        m = self.re_doc.search(text)
-        if m:
-            fname = m.group(1)
-            ename = m.group(2)
-
-            entry = os.path.relpath(self.base_dir + fname, self.app_dir)
-            entry = entry.removesuffix(".rst")
-
-            #
-            # When SPHINXDIRS is used, it will try to reference files
-            # outside srctree, causing warnings. To avoid that, point
-            # to the latest official documentation
-            #
-            if entry.startswith("../"):
-                html = KERNELDOC_URL + ename + ".html"
-                text = self.re_doc.sub(f'`{ename} <{html}>`_', text)
-            else:
-                text = self.re_doc.sub(f':doc:`{ename} </{entry}>`', text)
+        entries = self.get_entries(text)
+        if not entries:
+            return text
 
-        return text
+        return self.re_doc.sub(", ".join(entries.values()), text)
 
     def parse_descriptions(self, line):
         """Handle contents of the descriptions section."""
@@ -206,35 +224,15 @@ class MaintainersParser:
         # Handle profile entries - either as files or as https refs
         #
         if field == "P":
-            match = self.re_doc.match(details)
-            if match:
-                fname = match.group(1)
-                ename = match.group(2)
-
-                entry = os.path.relpath(self.base_dir + fname, self.app_dir)
-                entry = entry.removesuffix(".rst")
-                #
-                # When SPHINXDIRS is used, it will try to reference files
-                # outside srctree, causing warnings. To avoid that, point
-                # to the latest official documentation
-                #
-
-                if entry.startswith("../"):
-                    entry = KERNELDOC_URL + ename + ".html"
-                else:
-                    entry = "/" + entry
-
-                if "*" in entry:
-                    for e in glob(entry):
-                        if "html" not in e:
-                            self.profile_toc.add(e)
+            entries = self.get_entries(details)
+            if entries:
+                for e, link in entries.items():
+                    if "html" not in link:
+                        self.profile_toc.add(e)
 
-                        self.profile_entries[self.subsystem_name] = e
-                else:
-                    if "html" not in entry:
-                        self.profile_toc.add(entry)
+                    self.profile_entries[self.subsystem_name] = link
 
-                    self.profile_entries[self.subsystem_name] = entry
+                details = ", ".join(entries.values())
             else:
                 match = re.match(r"(https?://.*)", details)
                 if match:
@@ -243,7 +241,9 @@ class MaintainersParser:
                 else:
                     self.profile_entries[self.subsystem_name] = f"``{details}``"
 
-        details = self.linkify(details)
+                details = self.linkify(details)
+        else:
+            details = self.linkify(details)
 
         #
         # Mark paths (and regexes) as literal text for improved
@@ -340,7 +340,7 @@ class MaintainersProfile(Include):
                 output += f"- {name}: {entry}\n"
                 self.warning(f"{profile}: Invalid 'P' tag: {entry}\n")
             else:
-                output += f"- :doc:`{name} <{entry}>`\n"
+                output += f"- {entry}\n"
 
         #
         # Create a hidden TOC table with all profiles. That allows adding
@@ -356,6 +356,9 @@ class MaintainersProfile(Include):
 
         output += "\n"
 
+        # For debugging the pre-rendered results...
+        #print(output, file=open("/tmp/profiles.rst", "w"))
+
         self.state.document.settings.record_dependencies.add(path)
         self.state_machine.insert_input(statemachine.string2lines(output), path)