git-commit-guard 0.8.0__tar.gz → 0.10.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- git_commit_guard-0.10.0/.github/workflows/lint-python.yml +24 -0
- git_commit_guard-0.10.0/.github/workflows/release.yml +33 -0
- {git_commit_guard-0.8.0 → git_commit_guard-0.10.0}/PKG-INFO +57 -16
- {git_commit_guard-0.8.0 → git_commit_guard-0.10.0}/README.md +56 -15
- git_commit_guard-0.10.0/ruff.toml +13 -0
- {git_commit_guard-0.8.0 → git_commit_guard-0.10.0}/src/git_commit_guard/__init__.py +134 -19
- {git_commit_guard-0.8.0 → git_commit_guard-0.10.0}/tests/test_git_commit_guard.py +358 -3
- git_commit_guard-0.8.0/htmlcov/.gitignore +0 -2
- git_commit_guard-0.8.0/htmlcov/class_index.html +0 -161
- git_commit_guard-0.8.0/htmlcov/coverage_html_cb_dd2e7eb5.js +0 -735
- git_commit_guard-0.8.0/htmlcov/favicon_32_cb_c827f16f.png +0 -0
- git_commit_guard-0.8.0/htmlcov/function_index.html +0 -331
- git_commit_guard-0.8.0/htmlcov/index.html +0 -117
- git_commit_guard-0.8.0/htmlcov/keybd_closed_cb_900cfef5.png +0 -0
- git_commit_guard-0.8.0/htmlcov/status.json +0 -1
- git_commit_guard-0.8.0/htmlcov/style_cb_9ff733b0.css +0 -389
- git_commit_guard-0.8.0/htmlcov/z_262b75d81d1cf686___init___py.html +0 -454
- {git_commit_guard-0.8.0 → git_commit_guard-0.10.0}/.github/workflows/lint-commits.yml +0 -0
- {git_commit_guard-0.8.0 → git_commit_guard-0.10.0}/.github/workflows/lint-md.yml +0 -0
- {git_commit_guard-0.8.0 → git_commit_guard-0.10.0}/.github/workflows/test.yml +0 -0
- {git_commit_guard-0.8.0 → git_commit_guard-0.10.0}/.gitignore +0 -0
- {git_commit_guard-0.8.0 → git_commit_guard-0.10.0}/.pre-commit-hooks.yaml +0 -0
- {git_commit_guard-0.8.0 → git_commit_guard-0.10.0}/.python-version +0 -0
- {git_commit_guard-0.8.0 → git_commit_guard-0.10.0}/LICENSE +0 -0
- {git_commit_guard-0.8.0 → git_commit_guard-0.10.0}/pyproject.toml +0 -0
- {git_commit_guard-0.8.0 → git_commit_guard-0.10.0}/tests/__init__.py +0 -0
- {git_commit_guard-0.8.0 → git_commit_guard-0.10.0}/uv.lock +0 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Lint Python
|
|
3
|
+
on: # yamllint disable-line rule:truthy
|
|
4
|
+
pull_request:
|
|
5
|
+
permissions:
|
|
6
|
+
contents: read
|
|
7
|
+
jobs:
|
|
8
|
+
lint-python:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
permissions:
|
|
11
|
+
checks: write
|
|
12
|
+
pull-requests: write
|
|
13
|
+
steps:
|
|
14
|
+
- name: Checkout code
|
|
15
|
+
# yamllint disable-line rule:line-length
|
|
16
|
+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
17
|
+
with:
|
|
18
|
+
persist-credentials: false
|
|
19
|
+
- name: Run ruff
|
|
20
|
+
# yamllint disable-line rule:line-length
|
|
21
|
+
uses: benner/action-ruff@b36eb590165f0ea36700bb92de15235c121f24f0 # v0.1.0
|
|
22
|
+
with:
|
|
23
|
+
fail_level: error
|
|
24
|
+
reporter: github-pr-review
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Release
|
|
3
|
+
on: # yamllint disable-line rule:truthy
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- 'v*'
|
|
7
|
+
permissions:
|
|
8
|
+
contents: write
|
|
9
|
+
jobs:
|
|
10
|
+
release:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
steps:
|
|
13
|
+
- name: Checkout code
|
|
14
|
+
# yamllint disable-line rule:line-length
|
|
15
|
+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
16
|
+
with:
|
|
17
|
+
persist-credentials: false
|
|
18
|
+
fetch-depth: 0
|
|
19
|
+
- name: Generate release notes
|
|
20
|
+
id: git-cliff
|
|
21
|
+
# yamllint disable-line rule:line-length
|
|
22
|
+
uses: orhun/git-cliff-action@c93ef52f3d0ddcdcc9bd5447d98d458a11cd4f72 # v4.7.1
|
|
23
|
+
with:
|
|
24
|
+
args: --current
|
|
25
|
+
- name: Create GitHub Release
|
|
26
|
+
env:
|
|
27
|
+
GH_TOKEN: ${{ github.token }}
|
|
28
|
+
TAG: ${{ github.ref_name }}
|
|
29
|
+
NOTES_FILE: ${{ steps.git-cliff.outputs.changelog }}
|
|
30
|
+
run: |-
|
|
31
|
+
gh release create "$TAG" \
|
|
32
|
+
--title "$TAG" \
|
|
33
|
+
--notes-file "$NOTES_FILE"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: git-commit-guard
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.10.0
|
|
4
4
|
Summary: Opinionated conventional commit message linter with imperative mood detection
|
|
5
5
|
Project-URL: Homepage, https://github.com/benner/commit-guard
|
|
6
6
|
Project-URL: Repository, https://github.com/benner/commit-guard
|
|
@@ -101,6 +101,28 @@ Available checks:
|
|
|
101
101
|
* `signed-off` - `Signed-off-by:` trailer exists
|
|
102
102
|
* `signature` - Verify GPG or SSH signature
|
|
103
103
|
|
|
104
|
+
### Subject length
|
|
105
|
+
|
|
106
|
+
The default maximum subject line length is 72 characters. Override with
|
|
107
|
+
`--max-subject-length`:
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
commit-guard --max-subject-length 100
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Type validation
|
|
114
|
+
|
|
115
|
+
By default the standard conventional commit types are accepted. Use `--types`
|
|
116
|
+
to replace the allowed set entirely:
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
# restrict to a subset
|
|
120
|
+
commit-guard --types feat,fix,chore
|
|
121
|
+
|
|
122
|
+
# add a project-specific type
|
|
123
|
+
commit-guard --types feat,fix,docs,style,refactor,perf,test,build,ci,chore,revert,wip
|
|
124
|
+
```
|
|
125
|
+
|
|
104
126
|
### Scope validation
|
|
105
127
|
|
|
106
128
|
By default any scope is accepted and scope is optional. Use `--scopes` to
|
|
@@ -121,15 +143,17 @@ commit-guard --scopes auth,api --require-scope
|
|
|
121
143
|
### Configuration file
|
|
122
144
|
|
|
123
145
|
Place `.commit-guard.toml` in your project root (or any parent directory) to
|
|
124
|
-
set defaults for `enable`, `disable`, `scopes`,
|
|
125
|
-
commit-guard searches upward from the working directory
|
|
126
|
-
found.
|
|
146
|
+
set defaults for `enable`, `disable`, `scopes`, `require-scope`, `types`, and
|
|
147
|
+
`max-subject-length`. commit-guard searches upward from the working directory
|
|
148
|
+
and uses the first file found.
|
|
127
149
|
|
|
128
150
|
```toml
|
|
129
151
|
# .commit-guard.toml
|
|
130
152
|
disable = ["signature", "body"]
|
|
131
153
|
scopes = ["auth", "api", "db"]
|
|
132
154
|
require-scope = true
|
|
155
|
+
types = ["feat", "fix", "chore", "wip"]
|
|
156
|
+
max-subject-length = 100
|
|
133
157
|
```
|
|
134
158
|
|
|
135
159
|
```toml
|
|
@@ -137,21 +161,37 @@ require-scope = true
|
|
|
137
161
|
enable = ["subject", "imperative"]
|
|
138
162
|
```
|
|
139
163
|
|
|
140
|
-
CLI flags (`--enable`, `--disable`, `--scopes`, `--require-scope
|
|
141
|
-
precedence and ignore config file values when
|
|
164
|
+
CLI flags (`--enable`, `--disable`, `--scopes`, `--require-scope`, `--types`,
|
|
165
|
+
`--max-subject-length`) take full precedence and ignore config file values when
|
|
166
|
+
provided.
|
|
142
167
|
|
|
143
168
|
### Checking a range of commits
|
|
144
169
|
|
|
170
|
+
Use `--range` to check all commits in a revision range. All commits are
|
|
171
|
+
checked and a single non-zero exit code is returned if any fail:
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
# check all commits in a PR
|
|
175
|
+
commit-guard --range origin/main..HEAD
|
|
176
|
+
|
|
177
|
+
# check between two tags
|
|
178
|
+
commit-guard --range v1.0..v2.0
|
|
179
|
+
|
|
180
|
+
# only subject checks on a range
|
|
181
|
+
commit-guard --range origin/main..HEAD --enable subject,imperative
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
Merge commits are excluded by default. Use `--include-merges` to check them:
|
|
185
|
+
|
|
145
186
|
```bash
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
commit-guard "$rev" || git log -1 --oneline "$rev"
|
|
149
|
-
done
|
|
187
|
+
commit-guard --range origin/main..HEAD --include-merges
|
|
188
|
+
```
|
|
150
189
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
190
|
+
An empty range (no commits) exits non-zero by default — this catches
|
|
191
|
+
misconfigured range specs in CI. Use `--allow-empty` to exit 0 instead:
|
|
192
|
+
|
|
193
|
+
```bash
|
|
194
|
+
commit-guard --range origin/main..HEAD --allow-empty
|
|
155
195
|
```
|
|
156
196
|
|
|
157
197
|
### pre-commit
|
|
@@ -206,8 +246,9 @@ body
|
|
|
206
246
|
trailers
|
|
207
247
|
```
|
|
208
248
|
|
|
209
|
-
|
|
210
|
-
`build`, `ci`, `chore`, `revert`.
|
|
249
|
+
Default types: `feat`, `fix`, `docs`, `style`, `refactor`, `perf`, `test`,
|
|
250
|
+
`build`, `ci`, `chore`, `revert`. Override with `--types` or the `types` config
|
|
251
|
+
key.
|
|
211
252
|
|
|
212
253
|
Scope is optional. Mark breaking changes with `!` before
|
|
213
254
|
the colon.
|
|
@@ -80,6 +80,28 @@ Available checks:
|
|
|
80
80
|
* `signed-off` - `Signed-off-by:` trailer exists
|
|
81
81
|
* `signature` - Verify GPG or SSH signature
|
|
82
82
|
|
|
83
|
+
### Subject length
|
|
84
|
+
|
|
85
|
+
The default maximum subject line length is 72 characters. Override with
|
|
86
|
+
`--max-subject-length`:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
commit-guard --max-subject-length 100
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Type validation
|
|
93
|
+
|
|
94
|
+
By default the standard conventional commit types are accepted. Use `--types`
|
|
95
|
+
to replace the allowed set entirely:
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
# restrict to a subset
|
|
99
|
+
commit-guard --types feat,fix,chore
|
|
100
|
+
|
|
101
|
+
# add a project-specific type
|
|
102
|
+
commit-guard --types feat,fix,docs,style,refactor,perf,test,build,ci,chore,revert,wip
|
|
103
|
+
```
|
|
104
|
+
|
|
83
105
|
### Scope validation
|
|
84
106
|
|
|
85
107
|
By default any scope is accepted and scope is optional. Use `--scopes` to
|
|
@@ -100,15 +122,17 @@ commit-guard --scopes auth,api --require-scope
|
|
|
100
122
|
### Configuration file
|
|
101
123
|
|
|
102
124
|
Place `.commit-guard.toml` in your project root (or any parent directory) to
|
|
103
|
-
set defaults for `enable`, `disable`, `scopes`,
|
|
104
|
-
commit-guard searches upward from the working directory
|
|
105
|
-
found.
|
|
125
|
+
set defaults for `enable`, `disable`, `scopes`, `require-scope`, `types`, and
|
|
126
|
+
`max-subject-length`. commit-guard searches upward from the working directory
|
|
127
|
+
and uses the first file found.
|
|
106
128
|
|
|
107
129
|
```toml
|
|
108
130
|
# .commit-guard.toml
|
|
109
131
|
disable = ["signature", "body"]
|
|
110
132
|
scopes = ["auth", "api", "db"]
|
|
111
133
|
require-scope = true
|
|
134
|
+
types = ["feat", "fix", "chore", "wip"]
|
|
135
|
+
max-subject-length = 100
|
|
112
136
|
```
|
|
113
137
|
|
|
114
138
|
```toml
|
|
@@ -116,21 +140,37 @@ require-scope = true
|
|
|
116
140
|
enable = ["subject", "imperative"]
|
|
117
141
|
```
|
|
118
142
|
|
|
119
|
-
CLI flags (`--enable`, `--disable`, `--scopes`, `--require-scope
|
|
120
|
-
precedence and ignore config file values when
|
|
143
|
+
CLI flags (`--enable`, `--disable`, `--scopes`, `--require-scope`, `--types`,
|
|
144
|
+
`--max-subject-length`) take full precedence and ignore config file values when
|
|
145
|
+
provided.
|
|
121
146
|
|
|
122
147
|
### Checking a range of commits
|
|
123
148
|
|
|
149
|
+
Use `--range` to check all commits in a revision range. All commits are
|
|
150
|
+
checked and a single non-zero exit code is returned if any fail:
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
# check all commits in a PR
|
|
154
|
+
commit-guard --range origin/main..HEAD
|
|
155
|
+
|
|
156
|
+
# check between two tags
|
|
157
|
+
commit-guard --range v1.0..v2.0
|
|
158
|
+
|
|
159
|
+
# only subject checks on a range
|
|
160
|
+
commit-guard --range origin/main..HEAD --enable subject,imperative
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
Merge commits are excluded by default. Use `--include-merges` to check them:
|
|
164
|
+
|
|
124
165
|
```bash
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
commit-guard "$rev" || git log -1 --oneline "$rev"
|
|
128
|
-
done
|
|
166
|
+
commit-guard --range origin/main..HEAD --include-merges
|
|
167
|
+
```
|
|
129
168
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
169
|
+
An empty range (no commits) exits non-zero by default — this catches
|
|
170
|
+
misconfigured range specs in CI. Use `--allow-empty` to exit 0 instead:
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
commit-guard --range origin/main..HEAD --allow-empty
|
|
134
174
|
```
|
|
135
175
|
|
|
136
176
|
### pre-commit
|
|
@@ -185,8 +225,9 @@ body
|
|
|
185
225
|
trailers
|
|
186
226
|
```
|
|
187
227
|
|
|
188
|
-
|
|
189
|
-
`build`, `ci`, `chore`, `revert`.
|
|
228
|
+
Default types: `feat`, `fix`, `docs`, `style`, `refactor`, `perf`, `test`,
|
|
229
|
+
`build`, `ci`, `chore`, `revert`. Override with `--types` or the `types` config
|
|
230
|
+
key.
|
|
190
231
|
|
|
191
232
|
Scope is optional. Mark breaking changes with `!` before
|
|
192
233
|
the colon.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
target-version = "py312"
|
|
2
|
+
|
|
3
|
+
[lint]
|
|
4
|
+
select = ["ALL"]
|
|
5
|
+
ignore = [
|
|
6
|
+
"ANN", # flake8-annotations (ANN)
|
|
7
|
+
"COM812", # missing-trailing-comma
|
|
8
|
+
"D", # pydocstyle (D)
|
|
9
|
+
"RET504", # Unnecessary assignment to X before `return` statement
|
|
10
|
+
]
|
|
11
|
+
|
|
12
|
+
[lint.per-file-ignores]
|
|
13
|
+
"tests/**" = ["S101"] # assert is expected in tests
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import re
|
|
2
2
|
import subprocess
|
|
3
3
|
import sys
|
|
4
|
+
import tomllib
|
|
4
5
|
from argparse import ArgumentParser
|
|
5
6
|
from dataclasses import dataclass, field
|
|
6
7
|
from enum import StrEnum
|
|
7
8
|
from pathlib import Path
|
|
8
9
|
|
|
9
10
|
import nltk
|
|
10
|
-
import tomllib
|
|
11
11
|
from nltk.corpus import wordnet
|
|
12
12
|
|
|
13
13
|
TYPES = frozenset(
|
|
@@ -120,13 +120,21 @@ def _strip_comments(message):
|
|
|
120
120
|
)
|
|
121
121
|
|
|
122
122
|
|
|
123
|
-
def check_subject(
|
|
123
|
+
def check_subject( # noqa: PLR0913 Too many arguments in function definition (6 > 5)
|
|
124
|
+
line,
|
|
125
|
+
result,
|
|
126
|
+
allowed_scopes=frozenset(),
|
|
127
|
+
allowed_types=TYPES,
|
|
128
|
+
max_subject_length=MAX_SUBJECT_LEN,
|
|
129
|
+
*,
|
|
130
|
+
require_scope=False,
|
|
131
|
+
):
|
|
124
132
|
m = SUBJECT_RE.match(line)
|
|
125
133
|
if not m:
|
|
126
134
|
result.error(f"subject does not match 'type(scope): description': {line}")
|
|
127
135
|
return None
|
|
128
136
|
|
|
129
|
-
if m.group("type") not in
|
|
137
|
+
if m.group("type") not in allowed_types:
|
|
130
138
|
result.error(f"unknown type: {m.group('type')}")
|
|
131
139
|
|
|
132
140
|
scope = m.group("scope")
|
|
@@ -140,8 +148,8 @@ def check_subject(line, result, allowed_scopes=frozenset(), *, require_scope=Fal
|
|
|
140
148
|
result.error("description must not start with uppercase")
|
|
141
149
|
if desc.endswith("."):
|
|
142
150
|
result.error("description must not end with period")
|
|
143
|
-
if len(line) >
|
|
144
|
-
result.error(f"subject too long: {len(line)} > {
|
|
151
|
+
if len(line) > max_subject_length:
|
|
152
|
+
result.error(f"subject too long: {len(line)} > {max_subject_length}")
|
|
145
153
|
return desc
|
|
146
154
|
|
|
147
155
|
|
|
@@ -216,6 +224,23 @@ def _get_message(rev):
|
|
|
216
224
|
sys.exit(f"git error: {stderr}")
|
|
217
225
|
|
|
218
226
|
|
|
227
|
+
def _get_range_revs(rev_range, *, include_merges=False):
|
|
228
|
+
cmd = ["git", "log", "--format=%H"]
|
|
229
|
+
if not include_merges:
|
|
230
|
+
cmd.append("--no-merges")
|
|
231
|
+
cmd.append(rev_range)
|
|
232
|
+
try:
|
|
233
|
+
output = subprocess.check_output( # noqa: S603
|
|
234
|
+
cmd,
|
|
235
|
+
text=True,
|
|
236
|
+
stderr=subprocess.PIPE,
|
|
237
|
+
timeout=GIT_TIMEOUT,
|
|
238
|
+
).strip()
|
|
239
|
+
except subprocess.CalledProcessError as e:
|
|
240
|
+
sys.exit(f"git error: {e.stderr.strip()}")
|
|
241
|
+
return output.split("\n") if output else []
|
|
242
|
+
|
|
243
|
+
|
|
219
244
|
@dataclass
|
|
220
245
|
class Args:
|
|
221
246
|
rev: str | None
|
|
@@ -223,6 +248,11 @@ class Args:
|
|
|
223
248
|
enabled: frozenset
|
|
224
249
|
allowed_scopes: frozenset
|
|
225
250
|
require_scope: bool
|
|
251
|
+
allowed_types: frozenset
|
|
252
|
+
max_subject_length: int
|
|
253
|
+
rev_range: str | None
|
|
254
|
+
allow_empty: bool
|
|
255
|
+
include_merges: bool
|
|
226
256
|
|
|
227
257
|
|
|
228
258
|
def _resolve_enabled(args, config, parser):
|
|
@@ -241,6 +271,22 @@ def _resolve_enabled(args, config, parser):
|
|
|
241
271
|
return enabled
|
|
242
272
|
|
|
243
273
|
|
|
274
|
+
def _resolve_max_subject_length(args, config):
|
|
275
|
+
if args.max_subject_length is not None:
|
|
276
|
+
return args.max_subject_length
|
|
277
|
+
if "max-subject-length" in config:
|
|
278
|
+
return config["max-subject-length"]
|
|
279
|
+
return MAX_SUBJECT_LEN
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
def _resolve_types(args, config):
|
|
283
|
+
if args.types:
|
|
284
|
+
return frozenset(t.strip() for t in args.types.split(","))
|
|
285
|
+
if config.get("types"):
|
|
286
|
+
return frozenset(config["types"])
|
|
287
|
+
return TYPES
|
|
288
|
+
|
|
289
|
+
|
|
244
290
|
def _resolve_scopes(args, config):
|
|
245
291
|
if args.scopes:
|
|
246
292
|
allowed_scopes = frozenset(s.strip() for s in args.scopes.split(","))
|
|
@@ -292,12 +338,54 @@ def _parse_args():
|
|
|
292
338
|
default=False,
|
|
293
339
|
help="require a scope in the subject line",
|
|
294
340
|
)
|
|
341
|
+
parser.add_argument(
|
|
342
|
+
"--types",
|
|
343
|
+
metavar="TYPE[,TYPE,...]",
|
|
344
|
+
help="allowed commit types (replaces defaults when set)",
|
|
345
|
+
)
|
|
346
|
+
parser.add_argument(
|
|
347
|
+
"--max-subject-length",
|
|
348
|
+
type=int,
|
|
349
|
+
default=None,
|
|
350
|
+
metavar="N",
|
|
351
|
+
help=f"maximum subject line length (default: {MAX_SUBJECT_LEN})",
|
|
352
|
+
)
|
|
353
|
+
parser.add_argument(
|
|
354
|
+
"--range",
|
|
355
|
+
dest="rev_range",
|
|
356
|
+
metavar="REF..REF",
|
|
357
|
+
help="check all commits in the given revision range",
|
|
358
|
+
)
|
|
359
|
+
parser.add_argument(
|
|
360
|
+
"--allow-empty",
|
|
361
|
+
action="store_true",
|
|
362
|
+
default=False,
|
|
363
|
+
help="exit 0 when --range yields no commits (default: exit 1)",
|
|
364
|
+
)
|
|
365
|
+
parser.add_argument(
|
|
366
|
+
"--include-merges",
|
|
367
|
+
action="store_true",
|
|
368
|
+
default=False,
|
|
369
|
+
help="include merge commits when checking a range (default: excluded)",
|
|
370
|
+
)
|
|
295
371
|
args = parser.parse_args()
|
|
296
372
|
config = _load_config()
|
|
297
373
|
enabled = _resolve_enabled(args, config, parser)
|
|
298
374
|
allowed_scopes, require_scope = _resolve_scopes(args, config)
|
|
375
|
+
allowed_types = _resolve_types(args, config)
|
|
376
|
+
max_subject_length = _resolve_max_subject_length(args, config)
|
|
377
|
+
|
|
378
|
+
if args.allow_empty and not args.rev_range:
|
|
379
|
+
parser.error("--allow-empty requires --range")
|
|
380
|
+
if args.include_merges and not args.rev_range:
|
|
381
|
+
parser.error("--include-merges requires --range")
|
|
299
382
|
|
|
300
|
-
if args.
|
|
383
|
+
if args.rev_range:
|
|
384
|
+
if args.rev is not None or args.message_file:
|
|
385
|
+
parser.error("--range cannot be combined with rev or --message-file")
|
|
386
|
+
rev = None
|
|
387
|
+
message = ""
|
|
388
|
+
elif args.message_file:
|
|
301
389
|
rev = None
|
|
302
390
|
message = _strip_comments(args.message_file.read_text().strip())
|
|
303
391
|
elif args.rev:
|
|
@@ -316,6 +404,11 @@ def _parse_args():
|
|
|
316
404
|
enabled=enabled,
|
|
317
405
|
allowed_scopes=allowed_scopes,
|
|
318
406
|
require_scope=require_scope,
|
|
407
|
+
allowed_types=allowed_types,
|
|
408
|
+
max_subject_length=max_subject_length,
|
|
409
|
+
rev_range=args.rev_range,
|
|
410
|
+
allow_empty=args.allow_empty,
|
|
411
|
+
include_merges=args.include_merges,
|
|
319
412
|
)
|
|
320
413
|
|
|
321
414
|
|
|
@@ -329,19 +422,17 @@ def _report(result):
|
|
|
329
422
|
return 0 if result.ok else 1
|
|
330
423
|
|
|
331
424
|
|
|
332
|
-
def
|
|
333
|
-
|
|
334
|
-
lines = args.message.split("\n")
|
|
335
|
-
|
|
336
|
-
if Check.IMPERATIVE in args.enabled:
|
|
337
|
-
_ensure_nltk_data()
|
|
338
|
-
|
|
339
|
-
result = Result()
|
|
340
|
-
|
|
425
|
+
def _run_checks(args, rev, message, result):
|
|
426
|
+
lines = message.split("\n")
|
|
341
427
|
desc = None
|
|
342
428
|
if Check.SUBJECT in args.enabled:
|
|
343
429
|
desc = check_subject(
|
|
344
|
-
lines[0],
|
|
430
|
+
lines[0],
|
|
431
|
+
result,
|
|
432
|
+
args.allowed_scopes,
|
|
433
|
+
args.allowed_types,
|
|
434
|
+
args.max_subject_length,
|
|
435
|
+
require_scope=args.require_scope,
|
|
345
436
|
)
|
|
346
437
|
if Check.IMPERATIVE in args.enabled:
|
|
347
438
|
if desc is None:
|
|
@@ -352,8 +443,32 @@ def main():
|
|
|
352
443
|
if Check.BODY in args.enabled:
|
|
353
444
|
check_body(lines, result)
|
|
354
445
|
if Check.SIGNED_OFF in args.enabled:
|
|
355
|
-
check_signed_off(
|
|
356
|
-
if Check.SIGNATURE in args.enabled and
|
|
357
|
-
check_signature(
|
|
446
|
+
check_signed_off(message, result)
|
|
447
|
+
if Check.SIGNATURE in args.enabled and rev:
|
|
448
|
+
check_signature(rev, result)
|
|
449
|
+
|
|
450
|
+
|
|
451
|
+
def main():
|
|
452
|
+
args = _parse_args()
|
|
358
453
|
|
|
454
|
+
if Check.IMPERATIVE in args.enabled:
|
|
455
|
+
_ensure_nltk_data()
|
|
456
|
+
|
|
457
|
+
if args.rev_range:
|
|
458
|
+
revs = _get_range_revs(args.rev_range, include_merges=args.include_merges)
|
|
459
|
+
if not revs:
|
|
460
|
+
sys.stderr.write("no commits in range\n")
|
|
461
|
+
return 0 if args.allow_empty else 1
|
|
462
|
+
failed = False
|
|
463
|
+
for rev in revs:
|
|
464
|
+
message = _strip_comments(_get_message(rev))
|
|
465
|
+
sys.stderr.write(f"{rev[:7]} {message.split('\n')[0]}\n")
|
|
466
|
+
result = Result()
|
|
467
|
+
_run_checks(args, rev, message, result)
|
|
468
|
+
if _report(result) != 0:
|
|
469
|
+
failed = True
|
|
470
|
+
return 1 if failed else 0
|
|
471
|
+
|
|
472
|
+
result = Result()
|
|
473
|
+
_run_checks(args, args.rev, args.message, result)
|
|
359
474
|
return _report(result)
|