Skip to content

This version keeps the logic the same but improves readability with structured comments and simplified condition checks. #1562

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 29 additions & 43 deletions tools/gitlint-extra-rules.py
Original file line number Diff line number Diff line change
@@ -1,62 +1,48 @@
from typing import Any, List, Optional

from gitlint.options import ListOption
from gitlint.rules import CommitRule, RuleViolation


class EndsWithDot(CommitRule):
"""
Rule to ensure that the commit message title ends with a period ('.').
"""
name = "title-doesn't-end-with-dot"
id = "ZT1"

def validate(self, commit: Any) -> Optional[List[RuleViolation]]:
error = "Title does not end with a '.' character"
if not commit.message.title.endswith("."):
return [RuleViolation(self.id, error, line_nr=1)]
return [RuleViolation(self.id, "Title must end with a '.'", line_nr=1)]
return None


class AreaFormatting(CommitRule):
"""
Rule to enforce a structured format for commit message titles:
- The title must start with an area (lowercase, followed by ': ')
- Certain exclusions (e.g., 'WIP') are allowed in uppercase.
- The summary (after the colon) must start with an uppercase letter.
"""
name = "area-formatting"
id = "ZT2"

options_spec = [
ListOption("exclusions", ["WIP"], "Exclusions to area lower-case rule")
]
options_spec = [ListOption("exclusions", ["WIP"], "Allowed uppercase exclusions")]

def validate(self, commit: Any) -> Optional[List[RuleViolation]]:
title_components = commit.message.title.split(": ")

title_parts = commit.message.title.split(": ")
violations = []

# Return just this violation, since latter checks assume an area
error = (
"Title should start with at least one area, followed by a colon and space"
)
if len(title_components) < 2:
return [RuleViolation(self.id, error, line_nr=1)]


# Ensure the title contains at least an area and a summary
if len(title_parts) < 2:
return [RuleViolation(self.id, "Title must start with an area, followed by ': '", line_nr=1)]

exclusions = self.options["exclusions"].value
exclusions_text = ", or ".join(exclusions)
if exclusions_text:
exclusions_text = f" (or {exclusions_text})"
error = (
f"Areas at start of title should be lower case{exclusions_text}, "
"followed by ': '"
)

def deny_capital_text(text: str) -> bool:
if text in exclusions:
return False
if not text.islower():
return True
return False

for area in title_components[:-1]:
if any(deny_capital_text(word) for word in area.split("/")) or " " in area:
violations += [RuleViolation(self.id, error, line_nr=1)]

error = "Summary of change, after area(s), should be capitalized"
if not title_components[-1][0].isupper():
violations += [RuleViolation(self.id, error, line_nr=1)]

return violations
area_part = title_parts[0]
summary_part = title_parts[1]

# Check if the area part is correctly formatted
if area_part not in exclusions and not area_part.islower():
violations.append(RuleViolation(self.id, "Area must be lowercase unless excluded", line_nr=1))

# Ensure the summary starts with an uppercase letter
if not summary_part[0].isupper():
violations.append(RuleViolation(self.id, "Summary must start with an uppercase letter", line_nr=1))

return violations if violations else None