Skip to content

Commit 7cd62fb

Browse files
bearomorphismLee-W
authored andcommitted
feat(check): add check against default branch
1 parent f30ae2e commit 7cd62fb

File tree

6 files changed

+74
-22
lines changed

6 files changed

+74
-22
lines changed

commitizen/cli.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,13 @@ def __call__(
471471
"help": "a range of git rev to check. e.g, master..HEAD",
472472
"exclusive_group": "group1",
473473
},
474+
{
475+
"name": ["-d", "--use-default-range"],
476+
"action": "store_true",
477+
"default": False,
478+
"help": "check from the default branch to HEAD. e.g, refs/remotes/origin/master..HEAD",
479+
"exclusive_group": "group1",
480+
},
474481
{
475482
"name": ["-m", "--message"],
476483
"help": "commit message that needs to be checked",

commitizen/commands/check.py

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ class CheckArgs(TypedDict, total=False):
2121
message_length_limit: int
2222
allowed_prefixes: list[str]
2323
message: str
24+
use_default_range: bool
2425

2526

2627
class Check:
@@ -40,6 +41,7 @@ def __init__(self, config: BaseConfig, arguments: CheckArgs, *args: object) -> N
4041
self.allow_abort = bool(
4142
arguments.get("allow_abort", config.settings["allow_abort"])
4243
)
44+
self.use_default_range = bool(arguments.get("use_default_range"))
4345
self.max_msg_length = arguments.get("message_length_limit", 0)
4446

4547
# we need to distinguish between None and [], which is a valid value
@@ -50,25 +52,28 @@ def __init__(self, config: BaseConfig, arguments: CheckArgs, *args: object) -> N
5052
else config.settings["allowed_prefixes"]
5153
)
5254

53-
self._valid_command_argument()
54-
55-
self.config: BaseConfig = config
56-
self.encoding = config.settings["encoding"]
57-
self.cz = factory.committer_factory(self.config)
58-
59-
def _valid_command_argument(self) -> None:
6055
num_exclusive_args_provided = sum(
6156
arg is not None
62-
for arg in (self.commit_msg_file, self.commit_msg, self.rev_range)
57+
for arg in (
58+
self.commit_msg_file,
59+
self.commit_msg,
60+
self.rev_range,
61+
)
6362
)
64-
if num_exclusive_args_provided == 0 and not sys.stdin.isatty():
65-
self.commit_msg = sys.stdin.read()
66-
elif num_exclusive_args_provided != 1:
63+
64+
if num_exclusive_args_provided > 1:
6765
raise InvalidCommandArgumentError(
6866
"Only one of --rev-range, --message, and --commit-msg-file is permitted by check command! "
6967
"See 'cz check -h' for more information"
7068
)
7169

70+
if num_exclusive_args_provided == 0 and not sys.stdin.isatty():
71+
self.commit_msg = sys.stdin.read()
72+
73+
self.config: BaseConfig = config
74+
self.encoding = config.settings["encoding"]
75+
self.cz = factory.committer_factory(self.config)
76+
7277
def __call__(self) -> None:
7378
"""Validate if commit messages follows the conventional pattern.
7479
@@ -109,7 +114,10 @@ def _get_commits(self) -> list[git.GitCommit]:
109114
return [git.GitCommit(rev="", title="", body=self._filter_comments(msg))]
110115

111116
# Get commit messages from git log (--rev-range)
112-
return git.get_commits(end=self.rev_range)
117+
return git.get_commits(
118+
git.get_default_branch() if self.use_default_range else None,
119+
self.rev_range,
120+
)
113121

114122
@staticmethod
115123
def _filter_comments(msg: str) -> str:
@@ -134,7 +142,7 @@ def _filter_comments(msg: str) -> str:
134142
The filtered commit message without comments.
135143
"""
136144

137-
lines = []
145+
lines: list[str] = []
138146
for line in msg.split("\n"):
139147
if "# ------------------------ >8 ------------------------" in line:
140148
break

commitizen/git.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,3 +332,10 @@ def _get_log_as_str_list(start: str | None, end: str, args: str) -> list[str]:
332332
if c.return_code != 0:
333333
raise GitCommandError(c.err)
334334
return c.out.split(f"{delimiter}\n")
335+
336+
337+
def get_default_branch() -> str:
338+
c = cmd.run("git symbolic-ref refs/remotes/origin/HEAD")
339+
if c.return_code != 0:
340+
raise GitCommandError(c.err)
341+
return c.out.strip()

docs/commands/check.md

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,35 +27,37 @@ $ cz check --rev-range REV_RANGE
2727

2828
For example, if you'd like to check all commits on a branch, you can use `--rev-range master..HEAD`. Or, if you'd like to check all commits starting from when you first implemented commit message linting, you can use `--rev-range <first_commit_sha>..HEAD`.
2929

30+
You can also use `--use-default-range` to check all commits from the default branch up to HEAD. This is equivalent to using `--rev-range <default_branch>..HEAD`.
31+
3032
For more information on how git commit ranges work, you can check the [git documentation](https://git-scm.com/book/en/v2/Git-Tools-Revision-Selection#_commit_ranges).
3133

3234
### Commit Message
3335

3436
There are two ways you can provide your plain message and check it.
3537

36-
#### Method 1: use -m or --message
38+
#### Method 1: use `-m` or `--message`
3739

3840
```bash
3941
$ cz check --message MESSAGE
4042
```
4143

42-
In this option, MESSAGE is the commit message to be checked.
44+
In this option, `MESSAGE` is the commit message to be checked.
4345

4446
#### Method 2: use pipe to pipe it to `cz check`
4547

4648
```bash
4749
$ echo MESSAGE | cz check
4850
```
4951

50-
In this option, MESSAGE is piped to cz check and will be checked.
52+
In this option, `MESSAGE` is piped to `cz check` and will be checked.
5153

5254
### Commit Message File
5355

5456
```bash
5557
$ cz check --commit-msg-file COMMIT_MSG_FILE
5658
```
5759

58-
In this option, COMMIT_MSG_FILE is the path of the temporary file that contains the commit message.
60+
In this option, `COMMIT_MSG_FILE` is the path of the temporary file that contains the commit message.
5961
This argument can be useful when cooperating with git hooks. Please check [Automatically check message before commit](../tutorials/auto_check.md) for more information about how to use this argument with git hooks.
6062

6163
### Allow Abort
@@ -65,12 +67,18 @@ cz check --message MESSAGE --allow-abort
6567
```
6668

6769
Empty commit messages typically instruct Git to abort a commit, so you can pass `--allow-abort` to
68-
permit them. Since `git commit` accepts an `--allow-empty-message` flag (primarily for wrapper scripts), you may wish to disallow such commits in CI. `--allow-abort` may be used in conjunction with any of the other options.
70+
permit them. Since `git commit` accepts the `--allow-empty-message` flag (primarily for wrapper scripts), you may wish to disallow such commits in CI. `--allow-abort` may be used in conjunction with any of the other options.
6971

7072
### Allowed Prefixes
7173

7274
If the commit message starts with some specific prefixes, `cz check` returns `True` without checking the regex.
73-
By default, the following prefixes are allowed: `Merge`, `Revert`, `Pull request`, `fixup!` and `squash!`.
75+
By default, the following prefixes are allowed:
76+
77+
- `Merge`
78+
- `Revert`
79+
- `Pull request`
80+
- `fixup!`
81+
- `squash!`
7482

7583
```bash
7684
cz check --message MESSAGE --allowed-prefixes 'Merge' 'Revert' 'Custom Prefix'
@@ -83,5 +91,5 @@ For example, `cz check --message MESSAGE -l 3` would fail the check, since `MESS
8391
By default, the limit is set to 0, which means no limit on the length.
8492

8593
**Note that the limit applies only to the first line of the message.**
86-
Specifically, for `ConventionalCommitsCz` the length only counts from the type of change to the subject,
87-
while the body and the footer are not counted.
94+
95+
Specifically, for `ConventionalCommitsCz` the length only counts from the type of change to the subject, while the body and the footer are not counted.

tests/commands/test_check_command/test_check_command_shows_description_when_use_help_option.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
usage: cz check [-h] [--commit-msg-file COMMIT_MSG_FILE |
2-
--rev-range REV_RANGE | -m MESSAGE] [--allow-abort]
2+
--rev-range REV_RANGE | -d | -m MESSAGE] [--allow-abort]
33
[--allowed-prefixes [ALLOWED_PREFIXES ...]]
44
[-l MESSAGE_LENGTH_LIMIT]
55

@@ -13,6 +13,9 @@ options:
1313
MSG_FILE=$1
1414
--rev-range REV_RANGE
1515
a range of git rev to check. e.g, master..HEAD
16+
-d, --use-default-range
17+
check from the default branch to HEAD. e.g,
18+
refs/remotes/origin/master..HEAD
1619
-m, --message MESSAGE
1720
commit message that needs to be checked
1821
--allow-abort allow empty commit messages, which typically abort a

tests/test_git.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -480,3 +480,22 @@ def test_create_commit_cmd_string(mocker, os_name, committer_date, expected_cmd)
480480
mocker.patch("os.name", os_name)
481481
result = git._create_commit_cmd_string("", committer_date, "temp.txt")
482482
assert result == expected_cmd
483+
484+
485+
def test_get_default_branch_success(mocker: MockFixture):
486+
mocker.patch(
487+
"commitizen.cmd.run", return_value=FakeCommand(out="refs/remotes/origin/main\n")
488+
)
489+
assert git.get_default_branch() == "refs/remotes/origin/main"
490+
491+
492+
def test_get_default_branch_error(mocker: MockFixture):
493+
mocker.patch(
494+
"commitizen.cmd.run",
495+
return_value=FakeCommand(
496+
err="fatal: ref refs/remotes/origin/HEAD is not a symbolic ref",
497+
return_code=1,
498+
),
499+
)
500+
with pytest.raises(exceptions.GitCommandError):
501+
git.get_default_branch()

0 commit comments

Comments
 (0)