1*fb9948a3SEd Tanousimport re 2*fb9948a3SEd Tanousfrom gitlint.rules import CommitRule, RuleViolation 3*fb9948a3SEd Tanousfrom gitlint.options import IntOption 4*fb9948a3SEd Tanous 5*fb9948a3SEd Tanous 6*fb9948a3SEd Tanousclass BodyMaxLineLengthWithExceptions(CommitRule): 7*fb9948a3SEd Tanous name = "body-max-line-length-with-exceptions" 8*fb9948a3SEd Tanous id = "UC1" 9*fb9948a3SEd Tanous 10*fb9948a3SEd Tanous options_spec = [IntOption("line-length", 80, "Max line length")] 11*fb9948a3SEd Tanous line_length_violation_message = """Line exceeds max length ({0}>{1}). 12*fb9948a3SEd Tanous It's possible you intended to use one of the following exceptions: 13*fb9948a3SEd Tanous 1. Put logs or shell script in a quoted section with triple quotes (''') before and after the section 14*fb9948a3SEd Tanous 2. Put a long link at the bottom in a footnote. example: [1] https://my_long_link.com 15*fb9948a3SEd Tanous Line that was too long: 16*fb9948a3SEd Tanous""" 17*fb9948a3SEd Tanous tabs_violation_message = "Line contains hard tab characters (\\t)" 18*fb9948a3SEd Tanous 19*fb9948a3SEd Tanous def validate(self, commit): 20*fb9948a3SEd Tanous in_block_comment = False 21*fb9948a3SEd Tanous for line in commit.message.body: 22*fb9948a3SEd Tanous # allow a quoted string to be over the line limit 23*fb9948a3SEd Tanous if ( 24*fb9948a3SEd Tanous line.startswith("'''") 25*fb9948a3SEd Tanous or line.startswith('"""') 26*fb9948a3SEd Tanous or line.startswith("```") 27*fb9948a3SEd Tanous ): 28*fb9948a3SEd Tanous in_block_comment = not in_block_comment 29*fb9948a3SEd Tanous 30*fb9948a3SEd Tanous if in_block_comment: 31*fb9948a3SEd Tanous continue 32*fb9948a3SEd Tanous 33*fb9948a3SEd Tanous if "\t" in line: 34*fb9948a3SEd Tanous return [RuleViolation(self.id, self.tabs_violation_message, line)] 35*fb9948a3SEd Tanous 36*fb9948a3SEd Tanous # allow footnote url links to be as long as needed example 37*fb9948a3SEd Tanous # [1] http://www.myspace.com 38*fb9948a3SEd Tanous ret = re.match(r"^\[\d+\]:? ", line) 39*fb9948a3SEd Tanous if ret is not None: 40*fb9948a3SEd Tanous continue 41*fb9948a3SEd Tanous 42*fb9948a3SEd Tanous # allow signed-off-by 43*fb9948a3SEd Tanous if line.startswith("Signed-off-by:"): 44*fb9948a3SEd Tanous continue 45*fb9948a3SEd Tanous 46*fb9948a3SEd Tanous max_length = self.options["line-length"].value 47*fb9948a3SEd Tanous if len(line) > max_length: 48*fb9948a3SEd Tanous return [ 49*fb9948a3SEd Tanous RuleViolation( 50*fb9948a3SEd Tanous self.id, 51*fb9948a3SEd Tanous self.line_length_violation_message.format( 52*fb9948a3SEd Tanous len(line), max_length 53*fb9948a3SEd Tanous ), 54*fb9948a3SEd Tanous line, 55*fb9948a3SEd Tanous ) 56*fb9948a3SEd Tanous ] 57*fb9948a3SEd Tanous return None 58