1 #!/usr/bin/env python 2 # SPDX-License-Identifier: GPL-2.0 3 # -*- coding: utf-8; mode: python -*- 4 # pylint: disable=R0903, C0330, R0914, R0912, 5 6 u""" 7 maintainers-include 8 ~~~~~~~~~~~~~~~~~~~ 9 10 Implementation of the ``maintainers-includ 11 12 :copyright: Copyright (C) 2019 Kees Cook< 13 :license: GPL Version 2, June 1991 see 14 15 The ``maintainers-include`` reST-directive 16 specific to the Linux kernel's standard "M 17 effort to avoid needing to heavily mark up 18 """ 19 20 import sys 21 import re 22 import os.path 23 24 from docutils import statemachine 25 from docutils.utils.error_reporting import Err 26 from docutils.parsers.rst import Directive 27 from docutils.parsers.rst.directives.misc impo 28 29 __version__ = '1.0' 30 31 def setup(app): 32 app.add_directive("maintainers-include", M 33 return dict( 34 version = __version__, 35 parallel_read_safe = True, 36 parallel_write_safe = True 37 ) 38 39 class MaintainersInclude(Include): 40 u"""MaintainersInclude (``maintainers-incl 41 required_arguments = 0 42 43 def parse_maintainers(self, path): 44 """Parse all the MAINTAINERS lines int 45 46 result = list() 47 result.append(".. _maintainers:") 48 result.append("") 49 50 # Poor man's state machine. 51 descriptions = False 52 maintainers = False 53 subsystems = False 54 55 # Field letter to field name mapping. 56 field_letter = None 57 fields = dict() 58 59 prev = None 60 field_prev = "" 61 field_content = "" 62 63 for line in open(path): 64 # Have we reached the end of the p 65 if descriptions and line.startswit 66 descriptions = False 67 # Ensure a blank line followin 68 result.append("") 69 70 # Start subsystem processing? This 71 # between the Maintainers heading 72 if maintainers and not subsystems: 73 if re.search('^[A-Z0-9]', line 74 subsystems = True 75 76 # Drop needless input whitespace. 77 line = line.rstrip() 78 79 # Linkify all non-wildcard refs to 80 pat = r'(Documentation/([^\s\?\*]* 81 m = re.search(pat, line) 82 if m: 83 # maintainers.rst is in a subd 84 line = re.sub(pat, ':doc:`%s < 85 86 # Check state machine for output r 87 output = None 88 if descriptions: 89 # Escape the escapes in prefor 90 output = "| %s" % (line.replac 91 # Look for and record field le 92 # R: Designated *reviewer*: < 93 m = re.search(r"\s(\S):\s", li 94 if m: 95 field_letter = m.group(1) 96 if field_letter and not field_ 97 m = re.search(r"\*([^\*]+) 98 if m: 99 fields[field_letter] = 100 elif subsystems: 101 # Skip empty lines: subsystem 102 if len(line) == 0: 103 continue 104 # Subsystem fields are batched 105 if line[1] != ':': 106 # Render a subsystem entry 107 # SUBSYSTEM NAME 108 # ~~~~~~~~~~~~~~ 109 110 # Flush pending field cont 111 output = field_content + " 112 field_content = "" 113 114 # Collapse whitespace in s 115 heading = re.sub(r"\s+", " 116 output = output + "%s\n%s" 117 field_prev = "" 118 else: 119 # Render a subsystem field 120 # :Field: entry 121 # entry... 122 field, details = line.spli 123 details = details.strip() 124 125 # Mark paths (and regexes) 126 # readability and to escap 127 if field in ['F', 'N', 'X' 128 # But only if not alre 129 if not ':doc:' in deta 130 details = '``%s``' 131 132 # Comma separate email fie 133 if field == field_prev and 134 field_content = field_ 135 136 # Do not repeat field name 137 # will be collapsed togeth 138 if field != field_prev: 139 output = field_content 140 field_content = ":%s:" 141 field_content = field_cont 142 field_prev = field 143 else: 144 output = line 145 146 # Re-split on any added newlines i 147 if output != None: 148 for separated in output.split( 149 result.append(separated) 150 151 # Update the state machine when we 152 if line.startswith('----------'): 153 if prev.startswith('Descriptio 154 descriptions = True 155 if prev.startswith('Maintainer 156 maintainers = True 157 158 # Retain previous line for state m 159 prev = line 160 161 # Flush pending field contents. 162 if field_content != "": 163 for separated in field_content.spl 164 result.append(separated) 165 166 output = "\n".join(result) 167 # For debugging the pre-rendered resul 168 #print(output, file=open("/tmp/MAINTAI 169 170 self.state_machine.insert_input( 171 statemachine.string2lines(output), p 172 173 def run(self): 174 """Include the MAINTAINERS file as par 175 if not self.state.document.settings.fi 176 raise self.warning('"%s" directive 177 178 # Walk up source path directories to f 179 path = self.state_machine.document.att 180 path = os.path.realpath(path) 181 tail = path 182 while tail != "Documentation" and tail 183 (path, tail) = os.path.split(path) 184 185 # Append "MAINTAINERS" 186 path = os.path.join(path, "MAINTAINERS 187 188 try: 189 self.state.document.settings.recor 190 lines = self.parse_maintainers(pat 191 except IOError as error: 192 raise self.severe('Problems with " 193 (self.name, ErrorString( 194 195 return []
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.