1# SPDX-License-Identifier: Apache-2.0 2 3from gitlint.rules import LineRule, RuleViolation, CommitMessageTitle 4import re 5 6 7class TitleStartsWithComponent(LineRule): 8 """A rule to enforce valid commit message title 9 10 Valid title format: 11 component1[, component2, componentN]: submodule: summary 12 13 Title should have at least one component 14 Components are separated by comma+space: ", " 15 Components are validated to be in valid_components 16 Components list is ended by a colon 17 Submodules are not validated 18 19 """ 20 21 # A rule MUST have a human friendly name 22 name = "title-has-valid-component" 23 24 # A rule MUST have a *unique* id. 25 # We recommend starting with UL (for User-defined Line-rule) 26 id = "UL1" 27 28 # A line-rule MUST have a target (not required for CommitRules). 29 target = CommitMessageTitle 30 31 def validate(self, line, _commit): 32 valid_components = ( 33 'api_client', 34 'arch', 35 'block', 36 'build', 37 'ch-remote', 38 'ci', 39 'devices', 40 'docs', 41 'event_monitor', 42 'fuzz', 43 'github', 44 'gitignore', 45 'gitlint', 46 'hypervisor', 47 'main', 48 'misc', 49 'net_gen', 50 'net_util', 51 'openapi', 52 'option_parser', 53 'pci', 54 'performance-metrics', 55 'rate_limiter', 56 'README', 57 'resources', 58 'scripts', 59 'seccomp', 60 'serial_buffer', 61 'test_data', 62 'test_infra', 63 'tests', 64 'tpm', 65 'tracer', 66 'vhost_user_block', 67 'vhost_user_net', 68 'virtio-devices', 69 'vm-allocator', 70 'vm-device', 71 'vmm', 72 'vm-migration', 73 'vm-virtio') 74 75 ptrn_title = re.compile(r'^(.+?):\s(.+)$') 76 match = ptrn_title.match(line) 77 78 if not match: 79 self.log.debug("Invalid commit title {}", line) 80 return [RuleViolation(self.id, "Commit title does not comply with " 81 "rule: 'component: change summary'")] 82 components = match.group(1) 83 summary = match.group(2) 84 self.log.debug(f"\nComponents: {components}\nSummary: {summary}") 85 86 ptrn_components = re.compile(r',\s') 87 components_list = re.split(ptrn_components, components) 88 self.log.debug("components list: %s" % components_list) 89 90 for component in components_list: 91 if component not in valid_components: 92 return [RuleViolation(self.id, 93 f"Invalid component: {component}, " 94 "\nValid components are: {}".format( 95 " ".join(valid_components)))] 96