Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
if lower > upper:
# Should not happen
raise Exception("Cannot find imperative mood of {}".format(key))
mid = (lower + upper) // 2
imperative_form = words[mid]
if key[:3] == imperative_form[:3]:
return imperative_form
elif key < imperative_form:
upper = mid - 1
elif key > imperative_form:
lower = mid + 1
class ImperativeMood(LineRule):
""" This rule will enforce that the commit message title uses imperative
mood. This is done by checking if the first word is in `WORD_SET`, if so
show the word in the correct mood. """
name = "title-imperative-mood"
id = "Z1"
target = CommitMessageTitle
error_msg = ('The first word in commit title should be in imperative mood '
'("{word}" -> "{imperative}"): "{title}"')
def validate(self, line, commit):
# type: (Text, gitlint.commit) -> List[RuleViolation]
violations = []
# Ignore the section tag (ie `<section>: .`)</section>
import re
from gitlint.options import ListOption
from gitlint.rules import CommitMessageTitle, LineRule, RuleViolation
from gitlint.utils import ustr
RULE_REGEX = re.compile(r"[^(]+?(\([^)]+?\))?: .+")
class ConventionalCommit(LineRule):
""" This rule enforces the spec at https://www.conventionalcommits.org/. """
name = "contrib-title-conventional-commits"
id = "CT1"
target = CommitMessageTitle
options_spec = [
ListOption(
"types",
["fix", "feat", "chore", "docs", "style", "refactor", "perf", "test", "revert", "ci", "build"],
"Comma separated list of allowed commit types.",
)
]
def validate(self, line, _commit):
violations = []
return sstr(self) # pragma: no cover
def __unicode__(self):
return u"{0}: {1} {2}: \"{3}\"".format(self.line_nr, self.rule_id, self.message,
self.content) # pragma: no cover
def __repr__(self):
return self.__str__() # pragma: no cover
class UserRuleError(Exception):
""" Error used to indicate that an error occurred while trying to load a user rule """
pass
class MaxLineLength(LineRule):
name = "max-line-length"
id = "R1"
options_spec = [IntOption('line-length', 80, "Max line length")]
violation_message = "Line exceeds max length ({0}>{1})"
def validate(self, line, _commit):
max_length = self.options['line-length'].value
if len(line) > max_length:
return [RuleViolation(self.id, self.violation_message.format(len(line), max_length), line)]
class TrailingWhiteSpace(LineRule):
name = "trailing-whitespace"
id = "R2"
violation_message = "Line has trailing whitespace"
class TitleMaxLength(MaxLineLength):
name = "title-max-length"
id = "T1"
target = CommitMessageTitle
options_spec = [IntOption('line-length', 72, "Max line length")]
violation_message = "Title exceeds max length ({0}>{1})"
class TitleTrailingWhitespace(TrailingWhiteSpace):
name = "title-trailing-whitespace"
id = "T2"
target = CommitMessageTitle
violation_message = "Title has trailing whitespace"
class TitleTrailingPunctuation(LineRule):
name = "title-trailing-punctuation"
id = "T3"
target = CommitMessageTitle
def validate(self, title, _commit):
punctuation_marks = '?:!.,;'
for punctuation_mark in punctuation_marks:
if title.endswith(punctuation_mark):
return [RuleViolation(self.id, u"Title has trailing punctuation ({0})".format(punctuation_mark), title)]
class TitleHardTab(HardTab):
name = "title-hard-tab"
id = "T4"
target = CommitMessageTitle
violation_message = "Title contains hard tab characters (\\t)"
def title_line_rules(self):
return [rule for rule in self.config.rules if
isinstance(rule, gitlint_rules.LineRule) and
rule.target == gitlint_rules.CommitMessageTitle and not self.should_ignore_rule(rule)]
# A rule MUST have an *unique* id, we recommend starting with UC (for User-defined Commit-rule).
id = "UC2"
def validate(self, commit):
flags = re.UNICODE
flags |= re.IGNORECASE
for line in commit.message.body:
if line.lower().startswith("signed-off-by"):
if not re.search(r"(^)Signed-off-by: ([-'\w.]+) ([-'\w.]+) (.*)", line, flags=flags):
return [RuleViolation(self.id, "Signed-off-by: must have a full name", line_nr=1)]
else:
return
return [RuleViolation(self.id, "Body does not contain a 'Signed-off-by:' line", line_nr=1)]
class TitleMaxLengthRevert(LineRule):
name = "title-max-length-no-revert"
id = "UC5"
target = CommitMessageTitle
options_spec = [IntOption('line-length', 72, "Max line length")]
violation_message = "Title exceeds max length ({0}>{1})"
def validate(self, line, _commit):
max_length = self.options['line-length'].value
if len(line) > max_length and not line.startswith("Revert"):
return [RuleViolation(self.id, self.violation_message.format(len(line), max_length), line)]
class TitleStartsWithSubsystem(LineRule):
name = "title-starts-with-subsystem"
id = "UC3"
target = CommitMessageTitle
options_spec = [StrOption('regex', ".*", "Regex the title should match")]
first_word = words[0].lower()
if first_word in WORD_SET:
imperative = head_binary_search(first_word, imperative_forms)
violation = RuleViolation(self.id, self.error_msg.format(
word=first_word,
imperative=imperative,
title=commit.message.title
))
violations.append(violation)
return violations
class TitleMatchRegexAllowException(LineRule):
"""Allows revert commits contrary to the built-in title-match-regex rule"""
name = 'title-match-regex-allow-exception'
id = 'Z2'
target = CommitMessageTitle
options_spec = [StrOption('regex', ".*", "Regex the title should match")]
def validate(self, title, commit):
# type: (Text, gitlint.commit) -> List[RuleViolation]
regex = self.options['regex'].value
pattern = re.compile(regex, re.UNICODE)
if not pattern.search(title) and not title.startswith("Revert \""):
violation_msg = u"Title does not match regex ({0})".format(regex)
return [RuleViolation(self.id, violation_msg, title)]
if len(line) > max_length:
return [RuleViolation(self.id, self.violation_message.format(len(line), max_length), line)]
class TrailingWhiteSpace(LineRule):
name = "trailing-whitespace"
id = "R2"
violation_message = "Line has trailing whitespace"
def validate(self, line, _commit):
pattern = re.compile(r"\s$", re.UNICODE)
if pattern.search(line):
return [RuleViolation(self.id, self.violation_message, line)]
class HardTab(LineRule):
name = "hard-tab"
id = "R3"
violation_message = "Line contains hard tab characters (\\t)"
def validate(self, line, _commit):
if "\t" in line:
return [RuleViolation(self.id, self.violation_message, line)]
class LineMustNotContainWord(LineRule):
""" Violation if a line contains one of a list of words (NOTE: using a word in the list inside another word is not
a violation, e.g: WIPING is not a violation if 'WIP' is a word that is not allowed.) """
name = "line-must-not-contain"
id = "R5"
options_spec = [ListOption('words', [], "Comma separated list of words that should not be found")]
violation_message = u"Line contains {0}"