xref: /cloud-hypervisor/scripts/gitlint/rules/BodyMaxLineLengthEx.py (revision 77e042237dcfbbfde2da2b3d2b6b7347c8516e9e)
1*77e04223SPhilipp Schuster# SPDX-License-Identifier: Apache-2.0
2*77e04223SPhilipp Schuster
3*77e04223SPhilipp Schusterfrom gitlint.rules import LineRule, RuleViolation, CommitMessageBody
4*77e04223SPhilipp Schusterimport re
5*77e04223SPhilipp Schuster
6*77e04223SPhilipp Schuster
7*77e04223SPhilipp Schusterclass BodyMaxLineLengthEx(LineRule):
8*77e04223SPhilipp Schuster    """A rule to enforce a line limit of 72 characters, except for valid cases."""
9*77e04223SPhilipp Schuster
10*77e04223SPhilipp Schuster    # A rule MUST have a human friendly name
11*77e04223SPhilipp Schuster    name = "body-max-line-length-ex"
12*77e04223SPhilipp Schuster
13*77e04223SPhilipp Schuster    # A rule MUST have a *unique* id.
14*77e04223SPhilipp Schuster    # We recommend starting with UL (for User-defined Line-rule)
15*77e04223SPhilipp Schuster    id = "UL-ll"
16*77e04223SPhilipp Schuster
17*77e04223SPhilipp Schuster    # A line-rule MUST have a target (not required for CommitRules).
18*77e04223SPhilipp Schuster    target = CommitMessageBody
19*77e04223SPhilipp Schuster
20*77e04223SPhilipp Schuster    max_len = 72
21*77e04223SPhilipp Schuster
22*77e04223SPhilipp Schuster    # Updated property as the commit messages is validated line by line.
23*77e04223SPhilipp Schuster    inside_open_codeblock = False
24*77e04223SPhilipp Schuster
25*77e04223SPhilipp Schuster    def validate(self, line, commit):
26*77e04223SPhilipp Schuster        # Pattern allowing:
27*77e04223SPhilipp Schuster        # - [0]: https://foobar
28*77e04223SPhilipp Schuster        # - [0] https://foobar
29*77e04223SPhilipp Schuster        # - https://foobar
30*77e04223SPhilipp Schuster        link_regex = re.compile(r"^((\[[0-9]+\]:?\s?)?https?:\/\/).*$")
31*77e04223SPhilipp Schuster
32*77e04223SPhilipp Schuster        is_codeblock_marker = line.startswith("```")
33*77e04223SPhilipp Schuster
34*77e04223SPhilipp Schuster        inside_open_codeblock_ = self.inside_open_codeblock
35*77e04223SPhilipp Schuster        if is_codeblock_marker:
36*77e04223SPhilipp Schuster            self.inside_open_codeblock = not self.inside_open_codeblock
37*77e04223SPhilipp Schuster
38*77e04223SPhilipp Schuster        if len(line) > self.max_len:
39*77e04223SPhilipp Schuster            is_link = link_regex.match(line)
40*77e04223SPhilipp Schuster
41*77e04223SPhilipp Schuster            if inside_open_codeblock_:
42*77e04223SPhilipp Schuster                return
43*77e04223SPhilipp Schuster
44*77e04223SPhilipp Schuster            if is_link:
45*77e04223SPhilipp Schuster                return
46*77e04223SPhilipp Schuster
47*77e04223SPhilipp Schuster            return [
48*77e04223SPhilipp Schuster                RuleViolation(self.id, f"Line '{line}' exceeds limit of {self.max_len}")
49*77e04223SPhilipp Schuster            ]
50