summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README.md5
-rw-r--r--examples/commit-message-72
-rw-r--r--examples/commit-message-86
-rw-r--r--gitlint/config.py24
-rw-r--r--gitlint/lint.py14
-rw-r--r--gitlint/rules.py6
-rw-r--r--gitlint/tests/samples/commit_message/sample57
-rw-r--r--gitlint/tests/test_config.py31
-rw-r--r--gitlint/tests/test_lint.py22
9 files changed, 86 insertions, 31 deletions
diff --git a/README.md b/README.md
index 5014ab7..c4ddc86 100644
--- a/README.md
+++ b/README.md
@@ -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)]