git-commit-guard 0.9.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/release.yml +33 -0
- {git_commit_guard-0.9.0 → git_commit_guard-0.10.0}/PKG-INFO +25 -10
- {git_commit_guard-0.9.0 → git_commit_guard-0.10.0}/README.md +24 -9
- {git_commit_guard-0.9.0 → git_commit_guard-0.10.0}/src/git_commit_guard/__init__.py +81 -13
- {git_commit_guard-0.9.0 → git_commit_guard-0.10.0}/tests/test_git_commit_guard.py +165 -0
- git_commit_guard-0.9.0/htmlcov/.gitignore +0 -2
- git_commit_guard-0.9.0/htmlcov/class_index.html +0 -161
- git_commit_guard-0.9.0/htmlcov/coverage_html_cb_dd2e7eb5.js +0 -735
- git_commit_guard-0.9.0/htmlcov/favicon_32_cb_c827f16f.png +0 -0
- git_commit_guard-0.9.0/htmlcov/function_index.html +0 -331
- git_commit_guard-0.9.0/htmlcov/index.html +0 -117
- git_commit_guard-0.9.0/htmlcov/keybd_closed_cb_900cfef5.png +0 -0
- git_commit_guard-0.9.0/htmlcov/status.json +0 -1
- git_commit_guard-0.9.0/htmlcov/style_cb_9ff733b0.css +0 -389
- git_commit_guard-0.9.0/htmlcov/z_262b75d81d1cf686___init___py.html +0 -454
- {git_commit_guard-0.9.0 → git_commit_guard-0.10.0}/.github/workflows/lint-commits.yml +0 -0
- {git_commit_guard-0.9.0 → git_commit_guard-0.10.0}/.github/workflows/lint-md.yml +0 -0
- {git_commit_guard-0.9.0 → git_commit_guard-0.10.0}/.github/workflows/lint-python.yml +0 -0
- {git_commit_guard-0.9.0 → git_commit_guard-0.10.0}/.github/workflows/test.yml +0 -0
- {git_commit_guard-0.9.0 → git_commit_guard-0.10.0}/.gitignore +0 -0
- {git_commit_guard-0.9.0 → git_commit_guard-0.10.0}/.pre-commit-hooks.yaml +0 -0
- {git_commit_guard-0.9.0 → git_commit_guard-0.10.0}/.python-version +0 -0
- {git_commit_guard-0.9.0 → git_commit_guard-0.10.0}/LICENSE +0 -0
- {git_commit_guard-0.9.0 → git_commit_guard-0.10.0}/pyproject.toml +0 -0
- {git_commit_guard-0.9.0 → git_commit_guard-0.10.0}/ruff.toml +0 -0
- {git_commit_guard-0.9.0 → git_commit_guard-0.10.0}/tests/__init__.py +0 -0
- {git_commit_guard-0.9.0 → git_commit_guard-0.10.0}/uv.lock +0 -0
|
@@ -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
|
|
@@ -167,16 +167,31 @@ provided.
|
|
|
167
167
|
|
|
168
168
|
### Checking a range of commits
|
|
169
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
|
+
|
|
186
|
+
```bash
|
|
187
|
+
commit-guard --range origin/main..HEAD --include-merges
|
|
188
|
+
```
|
|
189
|
+
|
|
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
|
+
|
|
170
193
|
```bash
|
|
171
|
-
|
|
172
|
-
git rev-list --no-merges v1.0..v2.0 | while read -r rev; do
|
|
173
|
-
commit-guard "$rev" || git log -1 --oneline "$rev"
|
|
174
|
-
done
|
|
175
|
-
|
|
176
|
-
# only subject checks on a PR range
|
|
177
|
-
git rev-list --no-merges origin/main..HEAD | while read -r rev; do
|
|
178
|
-
commit-guard "$rev" --enable subject,imperative
|
|
179
|
-
done
|
|
194
|
+
commit-guard --range origin/main..HEAD --allow-empty
|
|
180
195
|
```
|
|
181
196
|
|
|
182
197
|
### pre-commit
|
|
@@ -146,16 +146,31 @@ provided.
|
|
|
146
146
|
|
|
147
147
|
### Checking a range of commits
|
|
148
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
|
+
|
|
165
|
+
```bash
|
|
166
|
+
commit-guard --range origin/main..HEAD --include-merges
|
|
167
|
+
```
|
|
168
|
+
|
|
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
|
+
|
|
149
172
|
```bash
|
|
150
|
-
|
|
151
|
-
git rev-list --no-merges v1.0..v2.0 | while read -r rev; do
|
|
152
|
-
commit-guard "$rev" || git log -1 --oneline "$rev"
|
|
153
|
-
done
|
|
154
|
-
|
|
155
|
-
# only subject checks on a PR range
|
|
156
|
-
git rev-list --no-merges origin/main..HEAD | while read -r rev; do
|
|
157
|
-
commit-guard "$rev" --enable subject,imperative
|
|
158
|
-
done
|
|
173
|
+
commit-guard --range origin/main..HEAD --allow-empty
|
|
159
174
|
```
|
|
160
175
|
|
|
161
176
|
### pre-commit
|
|
@@ -224,6 +224,23 @@ def _get_message(rev):
|
|
|
224
224
|
sys.exit(f"git error: {stderr}")
|
|
225
225
|
|
|
226
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
|
+
|
|
227
244
|
@dataclass
|
|
228
245
|
class Args:
|
|
229
246
|
rev: str | None
|
|
@@ -233,6 +250,9 @@ class Args:
|
|
|
233
250
|
require_scope: bool
|
|
234
251
|
allowed_types: frozenset
|
|
235
252
|
max_subject_length: int
|
|
253
|
+
rev_range: str | None
|
|
254
|
+
allow_empty: bool
|
|
255
|
+
include_merges: bool
|
|
236
256
|
|
|
237
257
|
|
|
238
258
|
def _resolve_enabled(args, config, parser):
|
|
@@ -330,6 +350,24 @@ def _parse_args():
|
|
|
330
350
|
metavar="N",
|
|
331
351
|
help=f"maximum subject line length (default: {MAX_SUBJECT_LEN})",
|
|
332
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
|
+
)
|
|
333
371
|
args = parser.parse_args()
|
|
334
372
|
config = _load_config()
|
|
335
373
|
enabled = _resolve_enabled(args, config, parser)
|
|
@@ -337,7 +375,17 @@ def _parse_args():
|
|
|
337
375
|
allowed_types = _resolve_types(args, config)
|
|
338
376
|
max_subject_length = _resolve_max_subject_length(args, config)
|
|
339
377
|
|
|
340
|
-
if args.
|
|
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")
|
|
382
|
+
|
|
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:
|
|
341
389
|
rev = None
|
|
342
390
|
message = _strip_comments(args.message_file.read_text().strip())
|
|
343
391
|
elif args.rev:
|
|
@@ -358,6 +406,9 @@ def _parse_args():
|
|
|
358
406
|
require_scope=require_scope,
|
|
359
407
|
allowed_types=allowed_types,
|
|
360
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,
|
|
361
412
|
)
|
|
362
413
|
|
|
363
414
|
|
|
@@ -371,15 +422,8 @@ def _report(result):
|
|
|
371
422
|
return 0 if result.ok else 1
|
|
372
423
|
|
|
373
424
|
|
|
374
|
-
def
|
|
375
|
-
|
|
376
|
-
lines = args.message.split("\n")
|
|
377
|
-
|
|
378
|
-
if Check.IMPERATIVE in args.enabled:
|
|
379
|
-
_ensure_nltk_data()
|
|
380
|
-
|
|
381
|
-
result = Result()
|
|
382
|
-
|
|
425
|
+
def _run_checks(args, rev, message, result):
|
|
426
|
+
lines = message.split("\n")
|
|
383
427
|
desc = None
|
|
384
428
|
if Check.SUBJECT in args.enabled:
|
|
385
429
|
desc = check_subject(
|
|
@@ -399,8 +443,32 @@ def main():
|
|
|
399
443
|
if Check.BODY in args.enabled:
|
|
400
444
|
check_body(lines, result)
|
|
401
445
|
if Check.SIGNED_OFF in args.enabled:
|
|
402
|
-
check_signed_off(
|
|
403
|
-
if Check.SIGNATURE in args.enabled and
|
|
404
|
-
check_signature(
|
|
446
|
+
check_signed_off(message, result)
|
|
447
|
+
if Check.SIGNATURE in args.enabled and rev:
|
|
448
|
+
check_signature(rev, result)
|
|
405
449
|
|
|
450
|
+
|
|
451
|
+
def main():
|
|
452
|
+
args = _parse_args()
|
|
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)
|
|
406
474
|
return _report(result)
|
|
@@ -11,6 +11,7 @@ from git_commit_guard import (
|
|
|
11
11
|
_download_if_missing,
|
|
12
12
|
_ensure_nltk_data,
|
|
13
13
|
_get_message,
|
|
14
|
+
_get_range_revs,
|
|
14
15
|
_load_config,
|
|
15
16
|
_parse_checks,
|
|
16
17
|
_parse_config_checks,
|
|
@@ -831,3 +832,167 @@ class TestMain:
|
|
|
831
832
|
),
|
|
832
833
|
):
|
|
833
834
|
assert main() == 0
|
|
835
|
+
|
|
836
|
+
def test_range_all_pass(self):
|
|
837
|
+
with (
|
|
838
|
+
patch(
|
|
839
|
+
"sys.argv",
|
|
840
|
+
["cg", "--range", "origin/main..HEAD", "--disable", "signature"],
|
|
841
|
+
),
|
|
842
|
+
patch(
|
|
843
|
+
"git_commit_guard._get_range_revs",
|
|
844
|
+
return_value=["abc1234", "def5678"],
|
|
845
|
+
),
|
|
846
|
+
patch("git_commit_guard._get_message", return_value=_VALID_MSG),
|
|
847
|
+
):
|
|
848
|
+
assert main() == 0
|
|
849
|
+
|
|
850
|
+
def test_range_one_fails(self):
|
|
851
|
+
messages = {"abc1234": _VALID_MSG, "def5678": "not a valid commit message"}
|
|
852
|
+
with (
|
|
853
|
+
patch(
|
|
854
|
+
"sys.argv",
|
|
855
|
+
[
|
|
856
|
+
"cg",
|
|
857
|
+
"--range",
|
|
858
|
+
"origin/main..HEAD",
|
|
859
|
+
"--disable",
|
|
860
|
+
"signature,body,signed-off,imperative",
|
|
861
|
+
],
|
|
862
|
+
),
|
|
863
|
+
patch(
|
|
864
|
+
"git_commit_guard._get_range_revs",
|
|
865
|
+
return_value=["abc1234", "def5678"],
|
|
866
|
+
),
|
|
867
|
+
patch(
|
|
868
|
+
"git_commit_guard._get_message",
|
|
869
|
+
side_effect=lambda rev: messages[rev],
|
|
870
|
+
),
|
|
871
|
+
):
|
|
872
|
+
assert main() == 1
|
|
873
|
+
|
|
874
|
+
def test_range_all_fail_returns_one(self):
|
|
875
|
+
with (
|
|
876
|
+
patch(
|
|
877
|
+
"sys.argv",
|
|
878
|
+
[
|
|
879
|
+
"cg",
|
|
880
|
+
"--range",
|
|
881
|
+
"origin/main..HEAD",
|
|
882
|
+
"--disable",
|
|
883
|
+
"signature,body,signed-off,imperative",
|
|
884
|
+
],
|
|
885
|
+
),
|
|
886
|
+
patch(
|
|
887
|
+
"git_commit_guard._get_range_revs",
|
|
888
|
+
return_value=["abc1234"],
|
|
889
|
+
),
|
|
890
|
+
patch(
|
|
891
|
+
"git_commit_guard._get_message",
|
|
892
|
+
return_value="not a valid commit message",
|
|
893
|
+
),
|
|
894
|
+
):
|
|
895
|
+
assert main() == 1
|
|
896
|
+
|
|
897
|
+
def test_range_empty_returns_one(self, capsys):
|
|
898
|
+
with (
|
|
899
|
+
patch("sys.argv", ["cg", "--range", "origin/main..HEAD"]),
|
|
900
|
+
patch("git_commit_guard._get_range_revs", return_value=[]),
|
|
901
|
+
):
|
|
902
|
+
assert main() == 1
|
|
903
|
+
assert "no commits in range" in capsys.readouterr().err
|
|
904
|
+
|
|
905
|
+
def test_range_empty_with_allow_empty_returns_zero(self, capsys):
|
|
906
|
+
with (
|
|
907
|
+
patch("sys.argv", ["cg", "--range", "origin/main..HEAD", "--allow-empty"]),
|
|
908
|
+
patch("git_commit_guard._get_range_revs", return_value=[]),
|
|
909
|
+
):
|
|
910
|
+
assert main() == 0
|
|
911
|
+
assert "no commits in range" in capsys.readouterr().err
|
|
912
|
+
|
|
913
|
+
def test_allow_empty_without_range_exits(self):
|
|
914
|
+
with (
|
|
915
|
+
patch("sys.argv", ["cg", "--allow-empty"]),
|
|
916
|
+
pytest.raises(SystemExit),
|
|
917
|
+
):
|
|
918
|
+
main()
|
|
919
|
+
|
|
920
|
+
def test_include_merges_without_range_exits(self):
|
|
921
|
+
with (
|
|
922
|
+
patch("sys.argv", ["cg", "--include-merges"]),
|
|
923
|
+
pytest.raises(SystemExit),
|
|
924
|
+
):
|
|
925
|
+
main()
|
|
926
|
+
|
|
927
|
+
def test_range_include_merges_flag(self):
|
|
928
|
+
with (
|
|
929
|
+
patch(
|
|
930
|
+
"sys.argv",
|
|
931
|
+
[
|
|
932
|
+
"cg",
|
|
933
|
+
"--range",
|
|
934
|
+
"origin/main..HEAD",
|
|
935
|
+
"--include-merges",
|
|
936
|
+
"--disable",
|
|
937
|
+
"signature",
|
|
938
|
+
],
|
|
939
|
+
),
|
|
940
|
+
patch(
|
|
941
|
+
"git_commit_guard._get_range_revs",
|
|
942
|
+
return_value=["abc1234"],
|
|
943
|
+
) as mock,
|
|
944
|
+
patch("git_commit_guard._get_message", return_value=_VALID_MSG),
|
|
945
|
+
):
|
|
946
|
+
main()
|
|
947
|
+
mock.assert_called_once_with("origin/main..HEAD", include_merges=True)
|
|
948
|
+
|
|
949
|
+
def test_range_conflicts_with_rev(self):
|
|
950
|
+
with (
|
|
951
|
+
patch("sys.argv", ["cg", "abc123", "--range", "origin/main..HEAD"]),
|
|
952
|
+
pytest.raises(SystemExit),
|
|
953
|
+
):
|
|
954
|
+
main()
|
|
955
|
+
|
|
956
|
+
def test_range_conflicts_with_message_file(self, tmp_path):
|
|
957
|
+
f = tmp_path / "msg"
|
|
958
|
+
f.write_text(_VALID_MSG)
|
|
959
|
+
with (
|
|
960
|
+
patch(
|
|
961
|
+
"sys.argv",
|
|
962
|
+
["cg", "--message-file", str(f), "--range", "origin/main..HEAD"],
|
|
963
|
+
),
|
|
964
|
+
pytest.raises(SystemExit),
|
|
965
|
+
):
|
|
966
|
+
main()
|
|
967
|
+
|
|
968
|
+
|
|
969
|
+
class TestGetRangeRevs:
|
|
970
|
+
def test_returns_shas(self):
|
|
971
|
+
with patch(
|
|
972
|
+
"git_commit_guard.subprocess.check_output",
|
|
973
|
+
return_value="abc1234\ndef5678",
|
|
974
|
+
):
|
|
975
|
+
assert _get_range_revs("origin/main..HEAD") == ["abc1234", "def5678"]
|
|
976
|
+
|
|
977
|
+
def test_excludes_merges_by_default(self):
|
|
978
|
+
with patch("git_commit_guard.subprocess.check_output", return_value="") as mock:
|
|
979
|
+
_get_range_revs("origin/main..HEAD")
|
|
980
|
+
assert "--no-merges" in mock.call_args[0][0]
|
|
981
|
+
|
|
982
|
+
def test_includes_merges_when_requested(self):
|
|
983
|
+
with patch("git_commit_guard.subprocess.check_output", return_value="") as mock:
|
|
984
|
+
_get_range_revs("origin/main..HEAD", include_merges=True)
|
|
985
|
+
assert "--no-merges" not in mock.call_args[0][0]
|
|
986
|
+
|
|
987
|
+
def test_empty_range_returns_empty_list(self):
|
|
988
|
+
with patch("git_commit_guard.subprocess.check_output", return_value=""):
|
|
989
|
+
assert _get_range_revs("origin/main..HEAD") == []
|
|
990
|
+
|
|
991
|
+
def test_invalid_range_exits(self):
|
|
992
|
+
err = subprocess.CalledProcessError(128, "git")
|
|
993
|
+
err.stderr = "fatal: bad revision 'bogus'"
|
|
994
|
+
with (
|
|
995
|
+
patch("git_commit_guard.subprocess.check_output", side_effect=err),
|
|
996
|
+
pytest.raises(SystemExit, match="git error"),
|
|
997
|
+
):
|
|
998
|
+
_get_range_revs("bogus")
|
|
@@ -1,161 +0,0 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
|
5
|
-
<title>Coverage report</title>
|
|
6
|
-
<link rel="icon" sizes="32x32" href="favicon_32_cb_c827f16f.png">
|
|
7
|
-
<link rel="stylesheet" href="style_cb_9ff733b0.css" type="text/css">
|
|
8
|
-
<script src="coverage_html_cb_dd2e7eb5.js" defer></script>
|
|
9
|
-
</head>
|
|
10
|
-
<body class="indexfile">
|
|
11
|
-
<header>
|
|
12
|
-
<div class="content">
|
|
13
|
-
<h1>Coverage report:
|
|
14
|
-
<span class="pc_cov">99%</span>
|
|
15
|
-
</h1>
|
|
16
|
-
<aside id="help_panel_wrapper">
|
|
17
|
-
<input id="help_panel_state" type="checkbox">
|
|
18
|
-
<label for="help_panel_state">
|
|
19
|
-
<img id="keyboard_icon" src="keybd_closed_cb_900cfef5.png" alt="Show/hide keyboard shortcuts">
|
|
20
|
-
</label>
|
|
21
|
-
<div id="help_panel">
|
|
22
|
-
<p class="legend">Shortcuts on this page</p>
|
|
23
|
-
<div class="keyhelp">
|
|
24
|
-
<p>
|
|
25
|
-
<kbd>f</kbd>
|
|
26
|
-
<kbd>n</kbd>
|
|
27
|
-
<kbd>s</kbd>
|
|
28
|
-
<kbd>m</kbd>
|
|
29
|
-
<kbd>x</kbd>
|
|
30
|
-
<kbd>c</kbd>
|
|
31
|
-
change column sorting
|
|
32
|
-
</p>
|
|
33
|
-
<p>
|
|
34
|
-
<kbd>[</kbd>
|
|
35
|
-
<kbd>]</kbd>
|
|
36
|
-
prev/next file
|
|
37
|
-
</p>
|
|
38
|
-
<p>
|
|
39
|
-
<kbd>?</kbd> show/hide this help
|
|
40
|
-
</p>
|
|
41
|
-
</div>
|
|
42
|
-
</div>
|
|
43
|
-
</aside>
|
|
44
|
-
<form id="filter_container">
|
|
45
|
-
<input id="filter" type="text" value="" placeholder="filter...">
|
|
46
|
-
<div>
|
|
47
|
-
<input id="hide100" type="checkbox" >
|
|
48
|
-
<label for="hide100">hide covered</label>
|
|
49
|
-
</div>
|
|
50
|
-
</form>
|
|
51
|
-
<h2>
|
|
52
|
-
<a class="button" href="index.html">Files</a>
|
|
53
|
-
<a class="button" href="function_index.html">Functions</a>
|
|
54
|
-
<a class="button current">Classes</a>
|
|
55
|
-
</h2>
|
|
56
|
-
<p class="text">
|
|
57
|
-
<a class="nav" href="https://coverage.readthedocs.io/en/7.13.5">coverage.py v7.13.5</a>,
|
|
58
|
-
created at 2026-04-18 23:09 +0300
|
|
59
|
-
</p>
|
|
60
|
-
</div>
|
|
61
|
-
</header>
|
|
62
|
-
<main id="index">
|
|
63
|
-
<table class="index" data-sortable>
|
|
64
|
-
<thead>
|
|
65
|
-
<tr class="tablehead" title="Click to sort">
|
|
66
|
-
<th id="file" class="name" aria-sort="none" data-shortcut="f">File<span class="arrows"></span></th>
|
|
67
|
-
<th id="region" class="name" aria-sort="none" data-default-sort-order="ascending" data-shortcut="n">class<span class="arrows"></span></th>
|
|
68
|
-
<th class="spacer"> </th>
|
|
69
|
-
<th id="statements" aria-sort="none" data-default-sort-order="descending" data-shortcut="s">statements<span class="arrows"></span></th>
|
|
70
|
-
<th id="missing" aria-sort="none" data-default-sort-order="descending" data-shortcut="m">missing<span class="arrows"></span></th>
|
|
71
|
-
<th id="excluded" aria-sort="none" data-default-sort-order="descending" data-shortcut="x">excluded<span class="arrows"></span></th>
|
|
72
|
-
<th class="spacer"> </th>
|
|
73
|
-
<th id="coverage" aria-sort="none" data-shortcut="c">coverage<span class="arrows"></span></th>
|
|
74
|
-
</tr>
|
|
75
|
-
</thead>
|
|
76
|
-
<tbody>
|
|
77
|
-
<tr class="region">
|
|
78
|
-
<td class="name"><a href="z_262b75d81d1cf686___init___py.html#t44">src / git_commit_guard / __init__.py</a></td>
|
|
79
|
-
<td class="name"><a href="z_262b75d81d1cf686___init___py.html#t44"><data value='Check'>Check</data></a></td>
|
|
80
|
-
<td class="spacer"> </td>
|
|
81
|
-
<td>0</td>
|
|
82
|
-
<td>0</td>
|
|
83
|
-
<td>0</td>
|
|
84
|
-
<td class="spacer"> </td>
|
|
85
|
-
<td data-ratio="0 0">100%</td>
|
|
86
|
-
</tr>
|
|
87
|
-
<tr class="region">
|
|
88
|
-
<td class="name"><a href="z_262b75d81d1cf686___init___py.html#t72">src / git_commit_guard / __init__.py</a></td>
|
|
89
|
-
<td class="name"><a href="z_262b75d81d1cf686___init___py.html#t72"><data value='Level'>Level</data></a></td>
|
|
90
|
-
<td class="spacer"> </td>
|
|
91
|
-
<td>0</td>
|
|
92
|
-
<td>0</td>
|
|
93
|
-
<td>0</td>
|
|
94
|
-
<td class="spacer"> </td>
|
|
95
|
-
<td data-ratio="0 0">100%</td>
|
|
96
|
-
</tr>
|
|
97
|
-
<tr class="region">
|
|
98
|
-
<td class="name"><a href="z_262b75d81d1cf686___init___py.html#t86">src / git_commit_guard / __init__.py</a></td>
|
|
99
|
-
<td class="name"><a href="z_262b75d81d1cf686___init___py.html#t86"><data value='Result'>Result</data></a></td>
|
|
100
|
-
<td class="spacer"> </td>
|
|
101
|
-
<td>4</td>
|
|
102
|
-
<td>0</td>
|
|
103
|
-
<td>0</td>
|
|
104
|
-
<td class="spacer"> </td>
|
|
105
|
-
<td data-ratio="4 4">100%</td>
|
|
106
|
-
</tr>
|
|
107
|
-
<tr class="region">
|
|
108
|
-
<td class="name"><a href="z_262b75d81d1cf686___init___py.html#t218">src / git_commit_guard / __init__.py</a></td>
|
|
109
|
-
<td class="name"><a href="z_262b75d81d1cf686___init___py.html#t218"><data value='Args'>Args</data></a></td>
|
|
110
|
-
<td class="spacer"> </td>
|
|
111
|
-
<td>0</td>
|
|
112
|
-
<td>0</td>
|
|
113
|
-
<td>0</td>
|
|
114
|
-
<td class="spacer"> </td>
|
|
115
|
-
<td data-ratio="0 0">100%</td>
|
|
116
|
-
</tr>
|
|
117
|
-
<tr class="region">
|
|
118
|
-
<td class="name"><a href="z_262b75d81d1cf686___init___py.html">src / git_commit_guard / __init__.py</a></td>
|
|
119
|
-
<td class="name"><a href="z_262b75d81d1cf686___init___py.html"><data value=''><span class='no-noun'>(no class)</span></data></a></td>
|
|
120
|
-
<td class="spacer"> </td>
|
|
121
|
-
<td>212</td>
|
|
122
|
-
<td>2</td>
|
|
123
|
-
<td>0</td>
|
|
124
|
-
<td class="spacer"> </td>
|
|
125
|
-
<td data-ratio="210 212">99%</td>
|
|
126
|
-
</tr>
|
|
127
|
-
</tbody>
|
|
128
|
-
<tfoot>
|
|
129
|
-
<tr class="total">
|
|
130
|
-
<td class="name">Total</td>
|
|
131
|
-
<td class="name"> </td>
|
|
132
|
-
<td class="spacer"> </td>
|
|
133
|
-
<td>216</td>
|
|
134
|
-
<td>2</td>
|
|
135
|
-
<td>0</td>
|
|
136
|
-
<td class="spacer"> </td>
|
|
137
|
-
<td data-ratio="214 216">99%</td>
|
|
138
|
-
</tr>
|
|
139
|
-
</tfoot>
|
|
140
|
-
</table>
|
|
141
|
-
<p id="no_rows">
|
|
142
|
-
No items found using the specified filter.
|
|
143
|
-
</p>
|
|
144
|
-
</main>
|
|
145
|
-
<footer>
|
|
146
|
-
<div class="content">
|
|
147
|
-
<p>
|
|
148
|
-
<a class="nav" href="https://coverage.readthedocs.io/en/7.13.5">coverage.py v7.13.5</a>,
|
|
149
|
-
created at 2026-04-18 23:09 +0300
|
|
150
|
-
</p>
|
|
151
|
-
</div>
|
|
152
|
-
<aside class="hidden">
|
|
153
|
-
<a id="prevFileLink" class="nav" href=""></a>
|
|
154
|
-
<a id="nextFileLink" class="nav" href=""></a>
|
|
155
|
-
<button type="button" class="button_prev_file" data-shortcut="["></button>
|
|
156
|
-
<button type="button" class="button_next_file" data-shortcut="]"></button>
|
|
157
|
-
<button type="button" class="button_show_hide_help" data-shortcut="?"></button>
|
|
158
|
-
</aside>
|
|
159
|
-
</footer>
|
|
160
|
-
</body>
|
|
161
|
-
</html>
|