diff options
-rw-r--r-- | README.md | 5 | ||||
-rw-r--r-- | examples/commit-message-7 | 2 | ||||
-rw-r--r-- | examples/commit-message-8 | 6 | ||||
-rw-r--r-- | gitlint/config.py | 24 | ||||
-rw-r--r-- | gitlint/lint.py | 14 | ||||
-rw-r--r-- | gitlint/rules.py | 6 | ||||
-rw-r--r-- | gitlint/tests/samples/commit_message/sample5 | 7 | ||||
-rw-r--r-- | gitlint/tests/test_config.py | 31 | ||||
-rw-r--r-- | gitlint/tests/test_lint.py | 22 |
9 files changed, 86 insertions, 31 deletions
@@ -184,7 +184,8 @@ I want gitlint to ignore this entire commit message. gitlint-ignore: all ``` -```gitlint-ignore: all``` can occur on any line, as long as it is at the start of the line. +```gitlint-ignore: all``` can occur on any line, as long as it is at the start of the line. You can also specify +specific rules to be ignore as follows: ```gitlint-ignore: T1, body-hard-tab```. **NOTE: gitlint currently does not support disabling \*specific\* rules on a per commit basis** @@ -260,8 +261,6 @@ python setup.py --long-description | rst2html.py > output.html - More rule options: - title-must-not-contain-word: case sensitive match - title-trailing-punctuation: define punctuation -- Config improvements: - - gitlint ignore for specific rules in commit message: ```gitlint-ignore: T2,body-hard-tab``` - Rule improvements: - body-changed-file-mention: list all files/directories that need to be mentioned as part of the violation - body-changed-file-mention: distinction between change file and directory in output diff --git a/examples/commit-message-7 b/examples/commit-message-7 index 830081f..6f7c192 100644 --- a/examples/commit-message-7 +++ b/examples/commit-message-7 @@ -1,4 +1,4 @@ This is the title of a commit message that is over 72 characters and contains hard tabs and trailing whitespace and the word wiping This line should not contain text Lines typically need to have a max length, meaning that they can't exceed a preset number of characters, usually 80 or 120. -gitlint-ignore: all. This line will disable gitlint.
\ No newline at end of file +gitlint-ignore: all diff --git a/examples/commit-message-8 b/examples/commit-message-8 new file mode 100644 index 0000000..4ba6e86 --- /dev/null +++ b/examples/commit-message-8 @@ -0,0 +1,6 @@ +This is the title of a commit message that is over 72 characters and contains hard tabs and trailing whitespace and the word wiping +This line should not contain text +Lines typically need to have a max length, meaning that they can't exceed a preset number of characters, usually 80 or 120. + +# This line will be ignored by gitlint because it starts with a #. +gitlint-ignore: B4, title-hard-tab
\ No newline at end of file diff --git a/gitlint/config.py b/gitlint/config.py index 43eb516..a648a01 100644 --- a/gitlint/config.py +++ b/gitlint/config.py @@ -4,9 +4,9 @@ from gitlint import options try: # python 2.x import ConfigParser -except ImportError: +except ImportError: # pragma: no cover # python 3.x - from configparser import ConfigParser + from configparser import ConfigParser # pragma: no cover from collections import OrderedDict import re import os @@ -37,7 +37,6 @@ class LintConfig(object): # Use an ordered dict so that the order in which rules are applied is always the same self._rules = OrderedDict([(rule_cls.id, rule_cls()) for rule_cls in self.default_rule_classes]) self._verbosity = 3 - self.enabled = True self.config_path = config_path @property @@ -51,6 +50,10 @@ class LintConfig(object): self._verbosity = value @property + def rules(self): + return [rule for rule in self._rules.values()] + + @property def body_rules(self): return [rule for rule in self._rules.values() if isinstance(rule, rules.CommitMessageBodyRule)] @@ -62,9 +65,12 @@ class LintConfig(object): del self._rules[rule_id] def disable_rule(self, rule_id_or_name): - rule = self.get_rule(rule_id_or_name) - if rule: - self.disable_rule_by_id(rule.id) + if rule_id_or_name == "all": + self._rules = OrderedDict() + else: + rule = self.get_rule(rule_id_or_name) + if rule: + self.disable_rule_by_id(rule.id) def get_rule(self, rule_id_or_name): # try finding rule by id @@ -108,8 +114,10 @@ class LintConfig(object): - gitlint: disable """ for line in gitcontext.commit_msg.full.split("\n"): - pattern = re.compile(r"^gitlint-ignore:\s*all") - if pattern.search(line): + pattern = re.compile(r"^gitlint-ignore:\s*(.*)") + matches = pattern.match(line) + if matches and len(matches.groups()) == 1: + self.set_general_option('ignore', matches.group(1)) self.enabled = False def apply_config_options(self, config_options): diff --git a/gitlint/lint.py b/gitlint/lint.py index e0144df..d19fb97 100644 --- a/gitlint/lint.py +++ b/gitlint/lint.py @@ -46,14 +46,12 @@ class GitLinter(object): def lint(self, gitcontext): """ Lint a given git context by applying all title, body and general rules. """ violations = [] - if self.config.enabled: - # determine violations by applying all rules - violations.extend( - self._apply_line_rules([gitcontext.commit_msg.title], self.title_line_rules, 1, gitcontext)) - violations.extend(self._apply_line_rules(gitcontext.commit_msg.body, self.body_line_rules, 2, gitcontext)) - violations.extend(self._apply_multiline_rules(self.body_multiline_rules, gitcontext)) - # sort violations by line number - violations.sort(key=lambda v: (v.line_nr, v.rule_id)) # sort violations by line number and rule_id + # determine violations by applying all rules + violations.extend(self._apply_line_rules([gitcontext.commit_msg.title], self.title_line_rules, 1, gitcontext)) + violations.extend(self._apply_line_rules(gitcontext.commit_msg.body, self.body_line_rules, 2, gitcontext)) + violations.extend(self._apply_multiline_rules(self.body_multiline_rules, gitcontext)) + # sort violations by line number + violations.sort(key=lambda v: (v.line_nr, v.rule_id)) # sort violations by line number and rule_id return violations def print_violations(self, violations): diff --git a/gitlint/rules.py b/gitlint/rules.py index c17bc9a..7492d6c 100644 --- a/gitlint/rules.py +++ b/gitlint/rules.py @@ -23,6 +23,12 @@ class Rule(object): def __eq__(self, other): return self.id == other.id and self.name == other.name + def __str__(self): + return "{} {}".format(self.id, self.name) # pragma: no cover + + def __repr__(self): + return self.__str__() # pragma: no cover + @abstractmethod def validate(self): pass # pragma: no cover diff --git a/gitlint/tests/samples/commit_message/sample5 b/gitlint/tests/samples/commit_message/sample5 new file mode 100644 index 0000000..61783db --- /dev/null +++ b/gitlint/tests/samples/commit_message/sample5 @@ -0,0 +1,7 @@ + Commit title containing 'WIP', leading and trailing whitespace and longer than 72 characters. +This line should be empty +This is the first line is meant to test a line that exceeds the maximum line length of 80 characters. +This line has a trailing space. +This line has a trailing tab. +# This is a commented line +gitlint-ignore: T3, T6, body-max-line-length diff --git a/gitlint/tests/test_config.py b/gitlint/tests/test_config.py index f2c1f5c..9828636 100644 --- a/gitlint/tests/test_config.py +++ b/gitlint/tests/test_config.py @@ -140,30 +140,39 @@ class LintConfigTests(BaseTestCase): with self.assertRaisesRegexp(LintConfigError, expected_error_msg): LintConfig.load_from_file(path) - def test_gitcontext_disable_gitlint(self): + def test_gitcontext_ignore_all(self): config = LintConfig() - self.assertTrue(config.enabled) + original_rules = config.rules # nothing gitlint context = GitContext() context.set_commit_msg("test\ngitlint\nfoo") config.apply_config_from_gitcontext(context) - self.assertTrue(config.enabled) + self.assertListEqual(config.rules, original_rules) - # disable gitlint + # ignore all rules context = GitContext() context.set_commit_msg("test\ngitlint-ignore: all\nfoo") config.apply_config_from_gitcontext(context) - self.assertFalse(config.enabled) + self.assertEqual(config.rules, []) - # disable gitlint, no space - config.enabled = True + # ignore all rules, no space + config = LintConfig() context.set_commit_msg("test\ngitlint-ignore:all\nfoo") config.apply_config_from_gitcontext(context) - self.assertFalse(config.enabled) + self.assertEqual(config.rules, []) - # disable gitlint, more spacing - config.enabled = True + # ignore all rules, more spacing + config = LintConfig() context.set_commit_msg("test\ngitlint-ignore: \t all\nfoo") config.apply_config_from_gitcontext(context) - self.assertFalse(config.enabled) + self.assertEqual(config.rules, []) + + def test_gitcontext_ignore_specific(self): + # ignore specific rules + config = LintConfig() + context = GitContext() + context.set_commit_msg("test\ngitlint-ignore: T1, body-hard-tab") + config.apply_config_from_gitcontext(context) + expected_rules = [rule for rule in config.rules if rule.id not in ["T1", "body-hard-tab"]] + self.assertEqual(config.rules, expected_rules) diff --git a/gitlint/tests/test_lint.py b/gitlint/tests/test_lint.py index 6f7f4cf..fe5c109 100644 --- a/gitlint/tests/test_lint.py +++ b/gitlint/tests/test_lint.py @@ -80,6 +80,28 @@ class RuleOptionTests(BaseTestCase): expected = [] self.assertListEqual(violations, expected) + def test_lint_sample5(self): + gitcontext = GitContext() + gitcontext.set_commit_msg(self.get_sample("commit_message/sample5")) + lintconfig = LintConfig() + lintconfig.apply_config_from_gitcontext(gitcontext) + linter = GitLinter(lintconfig) + violations = linter.lint(gitcontext) + title = " Commit title containing 'WIP', \tleading and trailing whitespace and longer than 72 characters." + # expect only certain violations because sample5 has a 'gitlint: T3,' + expected = [RuleViolation("T1", "Title exceeds max length (95>72)", title, 1), + RuleViolation("T4", "Title contains hard tab characters (\\t)", title, 1), + RuleViolation("T5", "Title contains the word 'WIP' (case-insensitive)", title, 1), + RuleViolation("B4", "Second line is not empty", "This line should be empty", 2), + RuleViolation("B2", "Line has trailing whitespace", + "This line has a trailing space. ", 4), + RuleViolation("B2", "Line has trailing whitespace", "This line has a trailing tab.\t", + 5), + RuleViolation("B3", "Line contains hard tab characters (\\t)", + "This line has a trailing tab.\t", 5), + ] + self.assertListEqual(violations, expected) + def test_print_violations(self): violations = [RuleViolation("RULE_ID_1", "Error Message 1", "Violating Content 1", 1), RuleViolation("RULE_ID_2", "Error Message 2", "Violating Content 2", 2)] |