Skip to content

Commit ea7683f

Browse files
authored
fix: handle commit message starting with # (#59)
- Removed comments only on `--file` (since the commit message from hash doesn't contain comments). This improves performance. - Displayed full commit on 'Input' section of output. - Created function `remove_diff_from_commit_message` for removing diff from the commits. - Updated README doc for not using commit messages that start with '#'. - Allowed codecov checks for coverage.
1 parent bb8a3b7 commit ea7683f

File tree

9 files changed

+118
-48
lines changed

9 files changed

+118
-48
lines changed

README.md

+7-1
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,10 @@ For more details, please refer to the Conventional Commits specification at http
5757
pre-commit install --hook-type commit-msg
5858
```
5959

60-
> **_NOTE:_** Installing using only `pre-commit install` will not work.
60+
Installing using only `pre-commit install` will not work.
61+
62+
> **_NOTE:_** Avoid using commit messages that start with '#'.
63+
> This might result in unexpected behavior with commitlint.
6164
6265
### For GitHub Actions
6366

@@ -151,6 +154,9 @@ Check commit message from file:
151154
$ commitlint --file /foo/bar/commit-message.txt
152155
```
153156

157+
> **_NOTE:_** For `--file` option, avoid using commit messages that start with '#'.
158+
> This might result in unexpected behavior with commitlint.
159+
154160
Check commit message of a hash:
155161

156162
```shell

codecov.yml

-7
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,3 @@
22

33
# Disabling comments
44
comment: false
5-
6-
# Disabling Github checks
7-
github_checks: false
8-
coverage:
9-
status:
10-
project: off
11-
patch: off

src/commitlint/cli.py

+16-12
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
from .exceptions import CommitlintException
2525
from .git_helpers import get_commit_message_of_hash, get_commit_messages_of_hash_range
2626
from .linter import lint_commit_message
27-
from .linter.utils import remove_comments
27+
from .linter.utils import remove_diff_from_commit_message
2828
from .messages import VALIDATION_FAILED, VALIDATION_SUCCESSFUL
2929

3030

@@ -93,9 +93,7 @@ def get_args() -> argparse.Namespace:
9393

9494

9595
def _show_errors(
96-
commit_message: str,
97-
errors: List[str],
98-
skip_detail: bool = False,
96+
commit_message: str, errors: List[str], skip_detail: bool = False
9997
) -> None:
10098
"""
10199
Display a formatted error message for a list of errors.
@@ -104,10 +102,10 @@ def _show_errors(
104102
commit_message (str): The commit message to display.
105103
errors (List[str]): A list of error messages to be displayed.
106104
skip_detail (bool): Whether to skip the detailed error message.
107-
108105
"""
109106
error_count = len(errors)
110-
commit_message = remove_comments(commit_message)
107+
108+
commit_message = remove_diff_from_commit_message(commit_message)
111109

112110
console.error(f"⧗ Input:\n{commit_message}\n")
113111

@@ -141,24 +139,28 @@ def _get_commit_message_from_file(filepath: str) -> str:
141139
return commit_message
142140

143141

144-
def _handle_commit_message(commit_message: str, skip_detail: bool) -> None:
142+
def _handle_commit_message(
143+
commit_message: str, skip_detail: bool, strip_comments: bool = False
144+
) -> None:
145145
"""
146146
Handles a single commit message, checks its validity, and prints the result.
147147
148148
Args:
149149
commit_message (str): The commit message to be handled.
150150
skip_detail (bool): Whether to skip the detailed error linting.
151+
strip_comments (bool, optional): Whether to remove comments from the
152+
commit message (default is False).
151153
152154
Raises:
153155
SystemExit: If the commit message is invalid.
154156
"""
155-
success, errors = lint_commit_message(commit_message, skip_detail=skip_detail)
157+
success, errors = lint_commit_message(commit_message, skip_detail, strip_comments)
156158

157159
if success:
158160
console.success(VALIDATION_SUCCESSFUL)
159161
return
160162

161-
_show_errors(commit_message, errors, skip_detail=skip_detail)
163+
_show_errors(commit_message, errors, skip_detail)
162164
sys.exit(1)
163165

164166

@@ -177,13 +179,13 @@ def _handle_multiple_commit_messages(
177179
has_error = False
178180

179181
for commit_message in commit_messages:
180-
success, errors = lint_commit_message(commit_message, skip_detail=skip_detail)
182+
success, errors = lint_commit_message(commit_message, skip_detail)
181183
if success:
182184
console.verbose("lint success")
183185
continue
184186

185187
has_error = True
186-
_show_errors(commit_message, errors, skip_detail=skip_detail)
188+
_show_errors(commit_message, errors, skip_detail)
187189
console.error("")
188190

189191
if has_error:
@@ -207,7 +209,9 @@ def main() -> None:
207209
if args.file:
208210
console.verbose("checking commit from file")
209211
commit_message = _get_commit_message_from_file(args.file)
210-
_handle_commit_message(commit_message, skip_detail=args.skip_detail)
212+
_handle_commit_message(
213+
commit_message, skip_detail=args.skip_detail, strip_comments=True
214+
)
211215
elif args.hash:
212216
console.verbose("checking commit from hash")
213217
commit_message = get_commit_message_of_hash(args.hash)

src/commitlint/linter/_linter.py

+6-3
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717

1818
def lint_commit_message(
19-
commit_message: str, skip_detail: bool = False
19+
commit_message: str, skip_detail: bool = False, strip_comments: bool = False
2020
) -> Tuple[bool, List[str]]:
2121
"""
2222
Lints a commit message.
@@ -25,6 +25,8 @@ def lint_commit_message(
2525
commit_message (str): The commit message to be linted.
2626
skip_detail (bool, optional): Whether to skip the detailed error linting
2727
(default is False).
28+
strip_comments (bool, optional): Whether to remove comments from the
29+
commit message (default is False).
2830
2931
Returns:
3032
Tuple[bool, List[str]]: Returns success as a first element and list of errors
@@ -35,8 +37,9 @@ def lint_commit_message(
3537

3638
# perform processing and pre checks
3739
# removing unnecessary commit comments
38-
console.verbose("removing comments from the commit message")
39-
commit_message = remove_comments(commit_message)
40+
if strip_comments:
41+
console.verbose("removing comments from the commit message")
42+
commit_message = remove_comments(commit_message)
4043

4144
# checking if commit message should be ignored
4245
console.verbose("checking if the commit message is in ignored list")

src/commitlint/linter/utils.py

+25-14
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,29 @@ def is_ignored(commit_message: str) -> bool:
2424
return bool(re.match(IGNORE_COMMIT_PATTERNS, commit_message))
2525

2626

27-
def remove_comments(msg: str) -> str:
27+
def remove_comments(commit_message: str) -> str:
2828
"""Removes comments from the commit message.
2929
30-
For `git commit --verbose`, excluding the diff generated message,
30+
Args:
31+
commit_message(str): The commit message to remove comments.
32+
33+
Returns:
34+
str: The commit message without comments.
35+
"""
36+
commit_message = remove_diff_from_commit_message(commit_message)
37+
38+
lines: List[str] = []
39+
for line in commit_message.split("\n"):
40+
if not line.startswith("#"):
41+
lines.append(line)
42+
43+
return "\n".join(lines)
44+
45+
46+
def remove_diff_from_commit_message(commit_message: str) -> str:
47+
"""Removes commit diff from the commit message.
48+
49+
For `git commit --verbose`, removing the diff generated message,
3150
for example:
3251
3352
```bash
@@ -40,18 +59,10 @@ def remove_comments(msg: str) -> str:
4059
```
4160
4261
Args:
43-
msg(str): The commit message to remove comments.
62+
commit_message (str): The commit message to remove diff.
4463
4564
Returns:
46-
str: The commit message without comments.
65+
str: The commit message without diff.
4766
"""
48-
49-
lines: List[str] = []
50-
for line in msg.split("\n"):
51-
if "# ------------------------ >8 ------------------------" in line:
52-
# ignoring all the verbose message below this line
53-
break
54-
if not line.startswith("#"):
55-
lines.append(line)
56-
57-
return "\n".join(lines)
67+
verbose_commit_separator = "# ------------------------ >8 ------------------------"
68+
return commit_message.split(verbose_commit_separator)[0].strip()

tests/fixtures/linter.py

-7
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,6 @@
4444
("feat: add new feature\n\nthis is body\n\ntest", True, []),
4545
("feat: add new feature\n", True, []),
4646
("build(deps-dev): bump @babel/traverse from 7.22.17 to 7.24.0", True, []),
47-
("feat(scope): add new feature\n#this is a comment", True, []),
48-
(
49-
"fix: fixed a bug\n\nthis is body\n"
50-
"# ------------------------ >8 ------------------------\nDiff message",
51-
True,
52-
[],
53-
),
5447
("feat!: breaking feature", True, []),
5548
# ignored commits (success)
5649
("Merge pull request #123", True, []),

tests/test_cli.py

+14
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,20 @@ def test__main__valid_commit_message_with_file(
189189
main()
190190
mock_output_success.assert_called_with(f"{VALIDATION_SUCCESSFUL}")
191191

192+
@patch(
193+
"commitlint.cli.get_args",
194+
return_value=MagicMock(file="path/to/file.txt", skip_detail=False, quiet=False),
195+
)
196+
@patch(
197+
"builtins.open",
198+
mock_open(read_data="feat: valid commit message 2\n#this is a comment"),
199+
)
200+
def test__main__valid_commit_message_and_comments_with_file(
201+
self, _mock_get_args, _mock_output_error, mock_output_success
202+
):
203+
main()
204+
mock_output_success.assert_called_with(f"{VALIDATION_SUCCESSFUL}")
205+
192206
@patch(
193207
"commitlint.cli.get_args",
194208
return_value=MagicMock(file="path/to/file.txt", skip_detail=False, quiet=False),

tests/test_linter/test__linter.py

+21-4
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
# type: ignore
22
# pylint: disable=all
33

4+
from unittest.mock import patch
5+
46
import pytest
57

68
from commitlint.constants import COMMIT_HEADER_MAX_LENGTH
79
from commitlint.linter import lint_commit_message
8-
from commitlint.messages import (
9-
HEADER_LENGTH_ERROR,
10-
INCORRECT_FORMAT_ERROR,
11-
)
10+
from commitlint.messages import HEADER_LENGTH_ERROR, INCORRECT_FORMAT_ERROR
11+
1212
from ..fixtures.linter import LINTER_FIXTURE_PARAMS
1313

1414

@@ -30,6 +30,23 @@ def test__lint_commit_message__skip_detail(fixture_data):
3030
assert success == expected_success
3131

3232

33+
def test__lint_commit_message__remove_comments_if_strip_comments_is_True():
34+
commit_message = "feat(scope): add new feature\n#this is a comment"
35+
success, errors = lint_commit_message(commit_message, strip_comments=True)
36+
assert success is True
37+
assert errors == []
38+
39+
40+
@patch("commitlint.linter._linter.remove_comments")
41+
def test__lint_commit_message__calls_remove_comments_if_strip_comments_is_True(
42+
mock_remove_comments,
43+
):
44+
commit_message = "feat(scope): add new feature"
45+
mock_remove_comments.return_value = commit_message
46+
lint_commit_message(commit_message, strip_comments=True)
47+
mock_remove_comments.assert_called_once()
48+
49+
3350
def test__lint_commit_message__skip_detail_returns_header_length_error_message():
3451
commit_message = "Test " + "a" * (COMMIT_HEADER_MAX_LENGTH + 1)
3552
success, errors = lint_commit_message(commit_message, skip_detail=True)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# type: ignore
2+
# pylint: disable=all
3+
4+
from commitlint.linter.utils import remove_diff_from_commit_message
5+
6+
7+
def test__remove_diff_from_commit_message__without_diff():
8+
input_msg = "Commit message without diff"
9+
expected_output = "Commit message without diff"
10+
result = remove_diff_from_commit_message(input_msg)
11+
assert result == expected_output
12+
13+
14+
def test__remove_diff_from_commit_message__with_diff():
15+
input_msg = (
16+
"Fix a bug\n"
17+
"# ------------------------ >8 ------------------------\n"
18+
"Diff message"
19+
)
20+
expected_output = "Fix a bug"
21+
result = remove_diff_from_commit_message(input_msg)
22+
assert result == expected_output
23+
24+
25+
def test__remove_diff_from_commit_message__strips_commit_message():
26+
input_msg = "Commit message\n "
27+
expected_output = "Commit message"
28+
result = remove_diff_from_commit_message(input_msg)
29+
assert result == expected_output

0 commit comments

Comments
 (0)