summaryrefslogtreecommitdiffstats
path: root/gitlint/lint.py
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2020-03-19 14:00:14 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2020-03-19 14:00:14 +0000
commitdf9615bac55ac6f1c3f516b66279ac0007175030 (patch)
tree84dd81d1c97835271cea7fbdd67c074742365e07 /gitlint/lint.py
parentInitial commit. (diff)
downloadgitlint-df9615bac55ac6f1c3f516b66279ac0007175030.tar.xz
gitlint-df9615bac55ac6f1c3f516b66279ac0007175030.zip
Adding upstream version 0.13.1.upstream/0.13.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'gitlint/lint.py')
-rw-r--r--gitlint/lint.py108
1 files changed, 108 insertions, 0 deletions
diff --git a/gitlint/lint.py b/gitlint/lint.py
new file mode 100644
index 0000000..6ef7174
--- /dev/null
+++ b/gitlint/lint.py
@@ -0,0 +1,108 @@
+# pylint: disable=logging-not-lazy
+import logging
+from gitlint import rules as gitlint_rules
+from gitlint import display
+from gitlint.utils import ustr
+
+LOG = logging.getLogger(__name__)
+logging.basicConfig()
+
+
+class GitLinter(object):
+ """ Main linter class. This is where rules actually get applied. See the lint() method. """
+
+ def __init__(self, config):
+ self.config = config
+
+ self.display = display.Display(config)
+
+ def should_ignore_rule(self, rule):
+ """ Determines whether a rule should be ignored based on the general list of commits to ignore """
+ return rule.id in self.config.ignore or rule.name in self.config.ignore
+
+ @property
+ def configuration_rules(self):
+ return [rule for rule in self.config.rules if
+ isinstance(rule, gitlint_rules.ConfigurationRule) and not self.should_ignore_rule(rule)]
+
+ @property
+ 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)]
+
+ @property
+ def body_line_rules(self):
+ return [rule for rule in self.config.rules if
+ isinstance(rule, gitlint_rules.LineRule) and
+ rule.target == gitlint_rules.CommitMessageBody and not self.should_ignore_rule(rule)]
+
+ @property
+ def commit_rules(self):
+ return [rule for rule in self.config.rules if isinstance(rule, gitlint_rules.CommitRule) and
+ not self.should_ignore_rule(rule)]
+
+ @staticmethod
+ def _apply_line_rules(lines, commit, rules, line_nr_start):
+ """ Iterates over the lines in a given list of lines and validates a given list of rules against each line """
+ all_violations = []
+ line_nr = line_nr_start
+ for line in lines:
+ for rule in rules:
+ violations = rule.validate(line, commit)
+ if violations:
+ for violation in violations:
+ violation.line_nr = line_nr
+ all_violations.append(violation)
+ line_nr += 1
+ return all_violations
+
+ @staticmethod
+ def _apply_commit_rules(rules, commit):
+ """ Applies a set of rules against a given commit and gitcontext """
+ all_violations = []
+ for rule in rules:
+ violations = rule.validate(commit)
+ if violations:
+ all_violations.extend(violations)
+ return all_violations
+
+ def lint(self, commit):
+ """ Lint the last commit in a given git context by applying all ignore, title, body and commit rules. """
+ LOG.debug("Linting commit %s", commit.sha or "[SHA UNKNOWN]")
+ LOG.debug("Commit Object\n" + ustr(commit))
+
+ # Apply config rules
+ for rule in self.configuration_rules:
+ rule.apply(self.config, commit)
+
+ # Skip linting if this is a special commit type that is configured to be ignored
+ ignore_commit_types = ["merge", "squash", "fixup", "revert"]
+ for commit_type in ignore_commit_types:
+ if getattr(commit, "is_{0}_commit".format(commit_type)) and \
+ getattr(self.config, "ignore_{0}_commits".format(commit_type)):
+ return []
+
+ violations = []
+ # determine violations by applying all rules
+ violations.extend(self._apply_line_rules([commit.message.title], commit, self.title_line_rules, 1))
+ violations.extend(self._apply_line_rules(commit.message.body, commit, self.body_line_rules, 2))
+ violations.extend(self._apply_commit_rules(self.commit_rules, commit))
+
+ # Sort violations by line number and rule_id. If there's no line nr specified (=common certain commit rules),
+ # we replace None with -1 so that it always get's placed first. Note that we need this to do this to support
+ # python 3, as None is not allowed in a list that is being sorted.
+ violations.sort(key=lambda v: (-1 if v.line_nr is None else v.line_nr, v.rule_id))
+ return violations
+
+ def print_violations(self, violations):
+ """ Print a given set of violations to the standard error output """
+ for v in violations:
+ line_nr = v.line_nr if v.line_nr else "-"
+ self.display.e(u"{0}: {1}".format(line_nr, v.rule_id), exact=True)
+ self.display.ee(u"{0}: {1} {2}".format(line_nr, v.rule_id, v.message), exact=True)
+ if v.content:
+ self.display.eee(u"{0}: {1} {2}: \"{3}\"".format(line_nr, v.rule_id, v.message, v.content),
+ exact=True)
+ else:
+ self.display.eee(u"{0}: {1} {2}".format(line_nr, v.rule_id, v.message), exact=True)