mailmap-checker 0.1.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.
- mailmap_checker-0.1.0/.github/workflows/ci.yml +67 -0
- mailmap_checker-0.1.0/.github/workflows/release.yml +22 -0
- mailmap_checker-0.1.0/.gitignore +15 -0
- mailmap_checker-0.1.0/.pre-commit-config.yaml +28 -0
- mailmap_checker-0.1.0/.pre-commit-hooks.yaml +8 -0
- mailmap_checker-0.1.0/CHANGELOG.md +17 -0
- mailmap_checker-0.1.0/LICENSE +21 -0
- mailmap_checker-0.1.0/PKG-INFO +164 -0
- mailmap_checker-0.1.0/README.md +138 -0
- mailmap_checker-0.1.0/commitlint.config.js +11 -0
- mailmap_checker-0.1.0/pyproject.toml +117 -0
- mailmap_checker-0.1.0/src/mailmap_checker/__init__.py +1 -0
- mailmap_checker-0.1.0/src/mailmap_checker/checker.py +113 -0
- mailmap_checker-0.1.0/src/mailmap_checker/cli.py +130 -0
- mailmap_checker-0.1.0/src/mailmap_checker/fixer.py +84 -0
- mailmap_checker-0.1.0/src/mailmap_checker/git.py +30 -0
- mailmap_checker-0.1.0/src/mailmap_checker/models.py +70 -0
- mailmap_checker-0.1.0/src/mailmap_checker/parser.py +42 -0
- mailmap_checker-0.1.0/tests/conftest.py +18 -0
- mailmap_checker-0.1.0/tests/test_checker.py +114 -0
- mailmap_checker-0.1.0/tests/test_cli.py +171 -0
- mailmap_checker-0.1.0/tests/test_fixer.py +159 -0
- mailmap_checker-0.1.0/tests/test_git.py +78 -0
- mailmap_checker-0.1.0/tests/test_models.py +126 -0
- mailmap_checker-0.1.0/tests/test_parser.py +88 -0
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
contents: read
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
lint:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v6
|
|
17
|
+
- uses: astral-sh/setup-uv@v6
|
|
18
|
+
- uses: actions/setup-python@v6
|
|
19
|
+
with:
|
|
20
|
+
python-version: "3.13"
|
|
21
|
+
- run: uv sync
|
|
22
|
+
- run: uv run ruff check src tests
|
|
23
|
+
- run: uv run ruff format --check src tests
|
|
24
|
+
|
|
25
|
+
security:
|
|
26
|
+
runs-on: ubuntu-latest
|
|
27
|
+
steps:
|
|
28
|
+
- uses: actions/checkout@v6
|
|
29
|
+
- uses: astral-sh/setup-uv@v6
|
|
30
|
+
- uses: actions/setup-python@v6
|
|
31
|
+
with:
|
|
32
|
+
python-version: "3.13"
|
|
33
|
+
- run: uv sync
|
|
34
|
+
- run: uv run bandit -r src
|
|
35
|
+
|
|
36
|
+
test:
|
|
37
|
+
runs-on: ${{ matrix.os }}
|
|
38
|
+
strategy:
|
|
39
|
+
matrix:
|
|
40
|
+
os: [ubuntu-latest, macos-latest, windows-latest]
|
|
41
|
+
python-version: ["3.10", "3.11", "3.12", "3.13"]
|
|
42
|
+
steps:
|
|
43
|
+
- uses: actions/checkout@v6
|
|
44
|
+
with:
|
|
45
|
+
fetch-depth: 0
|
|
46
|
+
- uses: astral-sh/setup-uv@v6
|
|
47
|
+
- uses: actions/setup-python@v6
|
|
48
|
+
with:
|
|
49
|
+
python-version: ${{ matrix.python-version }}
|
|
50
|
+
- run: uv sync
|
|
51
|
+
- run: uv run pytest --cov --cov-report=term-missing
|
|
52
|
+
|
|
53
|
+
commitlint:
|
|
54
|
+
runs-on: ubuntu-latest
|
|
55
|
+
if: github.event_name == 'pull_request'
|
|
56
|
+
steps:
|
|
57
|
+
- uses: actions/checkout@v6
|
|
58
|
+
with:
|
|
59
|
+
fetch-depth: 0
|
|
60
|
+
- uses: actions/setup-node@v6
|
|
61
|
+
with:
|
|
62
|
+
node-version: 22
|
|
63
|
+
- run: npm install @commitlint/cli @commitlint/config-conventional
|
|
64
|
+
- run: >
|
|
65
|
+
npx commitlint
|
|
66
|
+
--from ${{ github.event.pull_request.base.sha }}
|
|
67
|
+
--to ${{ github.event.pull_request.head.sha }}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
contents: read
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
publish:
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
steps:
|
|
14
|
+
- uses: actions/checkout@v6
|
|
15
|
+
- uses: astral-sh/setup-uv@v6
|
|
16
|
+
- uses: actions/setup-python@v6
|
|
17
|
+
with:
|
|
18
|
+
python-version: "3.13"
|
|
19
|
+
- run: uv build
|
|
20
|
+
- run: uv publish
|
|
21
|
+
env:
|
|
22
|
+
UV_PUBLISH_TOKEN: ${{ secrets.PYPI_PASSWORD }}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
repos:
|
|
2
|
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
3
|
+
rev: v5.0.0
|
|
4
|
+
hooks:
|
|
5
|
+
- id: trailing-whitespace
|
|
6
|
+
- id: end-of-file-fixer
|
|
7
|
+
- id: check-yaml
|
|
8
|
+
|
|
9
|
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
10
|
+
rev: v0.11.4
|
|
11
|
+
hooks:
|
|
12
|
+
- id: ruff
|
|
13
|
+
args: [--fix]
|
|
14
|
+
- id: ruff-format
|
|
15
|
+
|
|
16
|
+
- repo: https://github.com/PyCQA/bandit
|
|
17
|
+
rev: 1.8.3
|
|
18
|
+
hooks:
|
|
19
|
+
- id: bandit
|
|
20
|
+
args: [-r, src]
|
|
21
|
+
|
|
22
|
+
- repo: https://github.com/alessandrojcm/commitlint-pre-commit-hook
|
|
23
|
+
rev: v9.21.0
|
|
24
|
+
hooks:
|
|
25
|
+
- id: commitlint
|
|
26
|
+
stages: [commit-msg]
|
|
27
|
+
additional_dependencies:
|
|
28
|
+
- "@commitlint/config-conventional"
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
- id: mailmap-check
|
|
2
|
+
name: Check .mailmap completeness
|
|
3
|
+
description: Detect unmapped Git identities by comparing .mailmap against the full commit history.
|
|
4
|
+
entry: mailmap-checker check
|
|
5
|
+
language: python
|
|
6
|
+
always_run: true
|
|
7
|
+
pass_filenames: false
|
|
8
|
+
stages: [pre-commit]
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/), and this project adheres to [Semantic Versioning](https://semver.org/).
|
|
6
|
+
|
|
7
|
+
## [0.1.0] - 2026-04-02
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- `check` command — scans Git history and exits non-zero when unmapped identities are found.
|
|
12
|
+
- `init` command — creates a `.mailmap` file and runs a full check.
|
|
13
|
+
- `fix` command — generates suggested `.mailmap` entries (`--dry-run` to preview).
|
|
14
|
+
- Identity grouping via Union-Find: same email (case-insensitive) and same email local-part across domains.
|
|
15
|
+
- Pre-commit hook integration (`mailmap-check`).
|
|
16
|
+
|
|
17
|
+
[0.1.0]: https://github.com/cansarigol/mailmap-checker/releases/tag/v0.1.0
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Can Sarigol
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: mailmap-checker
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Pre-commit hook that checks and maintains .mailmap completeness
|
|
5
|
+
Project-URL: Repository, https://github.com/cansarigol/mailmap-checker
|
|
6
|
+
Project-URL: Changelog, https://github.com/cansarigol/mailmap-checker/blob/main/CHANGELOG.md
|
|
7
|
+
Project-URL: Issues, https://github.com/cansarigol/mailmap-checker/issues
|
|
8
|
+
Author-email: Can Sarigol <ertugrulsarigol@gmail.com>
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: deduplication,git,identity,mailmap,pre-commit
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Environment :: Console
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Operating System :: OS Independent
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
22
|
+
Classifier: Topic :: Software Development :: Quality Assurance
|
|
23
|
+
Classifier: Topic :: Software Development :: Version Control :: Git
|
|
24
|
+
Requires-Python: >=3.10
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
|
|
27
|
+
# mailmap-checker
|
|
28
|
+
|
|
29
|
+
[](https://pypi.org/project/mailmap-checker/)
|
|
30
|
+
[](https://pypi.org/project/mailmap-checker/)
|
|
31
|
+
[](https://github.com/cansarigol/mailmap-checker/actions/workflows/ci.yml)
|
|
32
|
+
[](LICENSE)
|
|
33
|
+
|
|
34
|
+
A pre-commit hook that detects unmapped Git identities by comparing your `.mailmap` against the full commit history. It groups authors by email address and email local-part so duplicates are caught even across domain changes.
|
|
35
|
+
|
|
36
|
+
## How it works
|
|
37
|
+
|
|
38
|
+
The checker scans `git log` for all unique author identities and groups them using two rules:
|
|
39
|
+
|
|
40
|
+
**Rule 1 — Same email (case-insensitive)**
|
|
41
|
+
|
|
42
|
+
Identities that share the exact same email address are the same person.
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
Alice Johnson <alice@acme.com>
|
|
46
|
+
alice.j <alice@acme.com> ← same email, grouped together
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
**Rule 2 — Same email local-part (different domain)**
|
|
50
|
+
|
|
51
|
+
Identities whose email local-part (the part before `@`) matches are likely the same person who changed companies or used a different address.
|
|
52
|
+
|
|
53
|
+
```
|
|
54
|
+
Alice Johnson <alice.johnson@acme.com>
|
|
55
|
+
Alice Johnson <alice.johnson@oldcorp.com> ← same local-part, grouped
|
|
56
|
+
Alice J <alice.johnson@personal.net> ← same local-part, grouped
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Once groups are built, the checker looks for identities that are **not mapped** in `.mailmap`. If a group has more than one identity and any of them is missing from the file, the hook fails and reports the gap.
|
|
60
|
+
|
|
61
|
+
### Example
|
|
62
|
+
|
|
63
|
+
Given these three identities in git history and an empty `.mailmap`:
|
|
64
|
+
|
|
65
|
+
```
|
|
66
|
+
Alice Johnson <alice.johnson@acme.com>
|
|
67
|
+
Alice Johnson <alice.johnson@oldcorp.com>
|
|
68
|
+
Alice J <alice.johnson@personal.net>
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
`mailmap-checker check` detects the gap:
|
|
72
|
+
|
|
73
|
+
```
|
|
74
|
+
Found 2 unmapped identities in 1 group:
|
|
75
|
+
|
|
76
|
+
Canonical: Alice J <alice.johnson@personal.net>
|
|
77
|
+
- Alice Johnson <alice.johnson@acme.com>
|
|
78
|
+
- Alice Johnson <alice.johnson@oldcorp.com>
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
`mailmap-checker fix --dry-run` suggests entries to add:
|
|
82
|
+
|
|
83
|
+
```
|
|
84
|
+
Suggested .mailmap entries:
|
|
85
|
+
|
|
86
|
+
Alice J <alice.johnson@personal.net> Alice Johnson <alice.johnson@acme.com>
|
|
87
|
+
Alice J <alice.johnson@personal.net> Alice Johnson <alice.johnson@oldcorp.com>
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
> **Note:** When no `.mailmap` exists, the tool picks the alphabetically first identity as the canonical. In this case it chose `Alice J <alice.johnson@personal.net>`, but the actual preferred identity is likely `Alice Johnson <alice.johnson@acme.com>`. The `.mailmap` format places the canonical (left) and the alias (right) on each line. After running `fix`, open `.mailmap` and swap the canonical if needed:
|
|
91
|
+
>
|
|
92
|
+
> ```
|
|
93
|
+
> Alice Johnson <alice.johnson@acme.com> Alice Johnson <alice.johnson@oldcorp.com>
|
|
94
|
+
> Alice Johnson <alice.johnson@acme.com> Alice J <alice.johnson@personal.net>
|
|
95
|
+
> ```
|
|
96
|
+
|
|
97
|
+
## Installation
|
|
98
|
+
|
|
99
|
+
### Pre-commit hook (recommended)
|
|
100
|
+
|
|
101
|
+
```yaml
|
|
102
|
+
# .pre-commit-config.yaml
|
|
103
|
+
repos:
|
|
104
|
+
- repo: https://github.com/cansarigol/mailmap-checker
|
|
105
|
+
rev: "" # run: pre-commit autoupdate
|
|
106
|
+
hooks:
|
|
107
|
+
- id: mailmap-check
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Then run `pre-commit autoupdate` to pin the latest release.
|
|
111
|
+
|
|
112
|
+
### Standalone
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
pip install mailmap-checker
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## Usage
|
|
119
|
+
|
|
120
|
+
### `check`
|
|
121
|
+
|
|
122
|
+
Scan all Git authors and exit non-zero if any identity is missing from `.mailmap`.
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
mailmap-checker check
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### `init`
|
|
129
|
+
|
|
130
|
+
Create a `.mailmap` file (if it does not exist) and run a full check.
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
mailmap-checker init
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### `fix`
|
|
137
|
+
|
|
138
|
+
Preview or apply suggested `.mailmap` entries.
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
# Preview
|
|
142
|
+
mailmap-checker fix --dry-run
|
|
143
|
+
|
|
144
|
+
# Apply
|
|
145
|
+
mailmap-checker fix
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
All commands accept `--mailmap <path>` to use a custom file path.
|
|
149
|
+
|
|
150
|
+
## Contributing
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
git clone https://github.com/cansarigol/mailmap-checker.git
|
|
154
|
+
cd mailmap-checker
|
|
155
|
+
uv sync
|
|
156
|
+
uv run poe setup # installs pre-commit and commit-msg hooks
|
|
157
|
+
uv run poe check # lint + security + tests
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
Commits must follow [Conventional Commits](https://www.conventionalcommits.org/) with a required scope (e.g. `feat(cli): add --verbose flag`).
|
|
161
|
+
|
|
162
|
+
## License
|
|
163
|
+
|
|
164
|
+
[MIT](LICENSE)
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
# mailmap-checker
|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/mailmap-checker/)
|
|
4
|
+
[](https://pypi.org/project/mailmap-checker/)
|
|
5
|
+
[](https://github.com/cansarigol/mailmap-checker/actions/workflows/ci.yml)
|
|
6
|
+
[](LICENSE)
|
|
7
|
+
|
|
8
|
+
A pre-commit hook that detects unmapped Git identities by comparing your `.mailmap` against the full commit history. It groups authors by email address and email local-part so duplicates are caught even across domain changes.
|
|
9
|
+
|
|
10
|
+
## How it works
|
|
11
|
+
|
|
12
|
+
The checker scans `git log` for all unique author identities and groups them using two rules:
|
|
13
|
+
|
|
14
|
+
**Rule 1 — Same email (case-insensitive)**
|
|
15
|
+
|
|
16
|
+
Identities that share the exact same email address are the same person.
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
Alice Johnson <alice@acme.com>
|
|
20
|
+
alice.j <alice@acme.com> ← same email, grouped together
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
**Rule 2 — Same email local-part (different domain)**
|
|
24
|
+
|
|
25
|
+
Identities whose email local-part (the part before `@`) matches are likely the same person who changed companies or used a different address.
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
Alice Johnson <alice.johnson@acme.com>
|
|
29
|
+
Alice Johnson <alice.johnson@oldcorp.com> ← same local-part, grouped
|
|
30
|
+
Alice J <alice.johnson@personal.net> ← same local-part, grouped
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Once groups are built, the checker looks for identities that are **not mapped** in `.mailmap`. If a group has more than one identity and any of them is missing from the file, the hook fails and reports the gap.
|
|
34
|
+
|
|
35
|
+
### Example
|
|
36
|
+
|
|
37
|
+
Given these three identities in git history and an empty `.mailmap`:
|
|
38
|
+
|
|
39
|
+
```
|
|
40
|
+
Alice Johnson <alice.johnson@acme.com>
|
|
41
|
+
Alice Johnson <alice.johnson@oldcorp.com>
|
|
42
|
+
Alice J <alice.johnson@personal.net>
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
`mailmap-checker check` detects the gap:
|
|
46
|
+
|
|
47
|
+
```
|
|
48
|
+
Found 2 unmapped identities in 1 group:
|
|
49
|
+
|
|
50
|
+
Canonical: Alice J <alice.johnson@personal.net>
|
|
51
|
+
- Alice Johnson <alice.johnson@acme.com>
|
|
52
|
+
- Alice Johnson <alice.johnson@oldcorp.com>
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
`mailmap-checker fix --dry-run` suggests entries to add:
|
|
56
|
+
|
|
57
|
+
```
|
|
58
|
+
Suggested .mailmap entries:
|
|
59
|
+
|
|
60
|
+
Alice J <alice.johnson@personal.net> Alice Johnson <alice.johnson@acme.com>
|
|
61
|
+
Alice J <alice.johnson@personal.net> Alice Johnson <alice.johnson@oldcorp.com>
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
> **Note:** When no `.mailmap` exists, the tool picks the alphabetically first identity as the canonical. In this case it chose `Alice J <alice.johnson@personal.net>`, but the actual preferred identity is likely `Alice Johnson <alice.johnson@acme.com>`. The `.mailmap` format places the canonical (left) and the alias (right) on each line. After running `fix`, open `.mailmap` and swap the canonical if needed:
|
|
65
|
+
>
|
|
66
|
+
> ```
|
|
67
|
+
> Alice Johnson <alice.johnson@acme.com> Alice Johnson <alice.johnson@oldcorp.com>
|
|
68
|
+
> Alice Johnson <alice.johnson@acme.com> Alice J <alice.johnson@personal.net>
|
|
69
|
+
> ```
|
|
70
|
+
|
|
71
|
+
## Installation
|
|
72
|
+
|
|
73
|
+
### Pre-commit hook (recommended)
|
|
74
|
+
|
|
75
|
+
```yaml
|
|
76
|
+
# .pre-commit-config.yaml
|
|
77
|
+
repos:
|
|
78
|
+
- repo: https://github.com/cansarigol/mailmap-checker
|
|
79
|
+
rev: "" # run: pre-commit autoupdate
|
|
80
|
+
hooks:
|
|
81
|
+
- id: mailmap-check
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Then run `pre-commit autoupdate` to pin the latest release.
|
|
85
|
+
|
|
86
|
+
### Standalone
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
pip install mailmap-checker
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## Usage
|
|
93
|
+
|
|
94
|
+
### `check`
|
|
95
|
+
|
|
96
|
+
Scan all Git authors and exit non-zero if any identity is missing from `.mailmap`.
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
mailmap-checker check
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### `init`
|
|
103
|
+
|
|
104
|
+
Create a `.mailmap` file (if it does not exist) and run a full check.
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
mailmap-checker init
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### `fix`
|
|
111
|
+
|
|
112
|
+
Preview or apply suggested `.mailmap` entries.
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
# Preview
|
|
116
|
+
mailmap-checker fix --dry-run
|
|
117
|
+
|
|
118
|
+
# Apply
|
|
119
|
+
mailmap-checker fix
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
All commands accept `--mailmap <path>` to use a custom file path.
|
|
123
|
+
|
|
124
|
+
## Contributing
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
git clone https://github.com/cansarigol/mailmap-checker.git
|
|
128
|
+
cd mailmap-checker
|
|
129
|
+
uv sync
|
|
130
|
+
uv run poe setup # installs pre-commit and commit-msg hooks
|
|
131
|
+
uv run poe check # lint + security + tests
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
Commits must follow [Conventional Commits](https://www.conventionalcommits.org/) with a required scope (e.g. `feat(cli): add --verbose flag`).
|
|
135
|
+
|
|
136
|
+
## License
|
|
137
|
+
|
|
138
|
+
[MIT](LICENSE)
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "mailmap-checker"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "Pre-commit hook that checks and maintains .mailmap completeness"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
license = "MIT"
|
|
7
|
+
requires-python = ">=3.10"
|
|
8
|
+
authors = [{ name = "Can Sarigol", email = "ertugrulsarigol@gmail.com" }]
|
|
9
|
+
classifiers = [
|
|
10
|
+
"Development Status :: 4 - Beta",
|
|
11
|
+
"Environment :: Console",
|
|
12
|
+
"Intended Audience :: Developers",
|
|
13
|
+
"License :: OSI Approved :: MIT License",
|
|
14
|
+
"Operating System :: OS Independent",
|
|
15
|
+
"Programming Language :: Python :: 3",
|
|
16
|
+
"Programming Language :: Python :: 3.10",
|
|
17
|
+
"Programming Language :: Python :: 3.11",
|
|
18
|
+
"Programming Language :: Python :: 3.12",
|
|
19
|
+
"Programming Language :: Python :: 3.13",
|
|
20
|
+
"Topic :: Software Development :: Quality Assurance",
|
|
21
|
+
"Topic :: Software Development :: Version Control :: Git",
|
|
22
|
+
]
|
|
23
|
+
keywords = ["git", "mailmap", "pre-commit", "identity", "deduplication"]
|
|
24
|
+
|
|
25
|
+
[project.scripts]
|
|
26
|
+
mailmap-checker = "mailmap_checker.cli:main"
|
|
27
|
+
|
|
28
|
+
[project.urls]
|
|
29
|
+
Repository = "https://github.com/cansarigol/mailmap-checker"
|
|
30
|
+
Changelog = "https://github.com/cansarigol/mailmap-checker/blob/main/CHANGELOG.md"
|
|
31
|
+
Issues = "https://github.com/cansarigol/mailmap-checker/issues"
|
|
32
|
+
|
|
33
|
+
[build-system]
|
|
34
|
+
requires = ["hatchling"]
|
|
35
|
+
build-backend = "hatchling.build"
|
|
36
|
+
|
|
37
|
+
[tool.hatch.build.targets.wheel]
|
|
38
|
+
packages = ["src/mailmap_checker"]
|
|
39
|
+
|
|
40
|
+
[dependency-groups]
|
|
41
|
+
dev = [
|
|
42
|
+
"pytest>=8.0",
|
|
43
|
+
"pytest-cov>=6.0",
|
|
44
|
+
"ruff>=0.11",
|
|
45
|
+
"bandit>=1.8",
|
|
46
|
+
"poethepoet>=0.34",
|
|
47
|
+
"pre-commit>=4.0",
|
|
48
|
+
]
|
|
49
|
+
|
|
50
|
+
[tool.ruff]
|
|
51
|
+
line-length = 88
|
|
52
|
+
target-version = "py310"
|
|
53
|
+
src = ["src", "tests"]
|
|
54
|
+
|
|
55
|
+
[tool.ruff.lint]
|
|
56
|
+
select = [
|
|
57
|
+
"A",
|
|
58
|
+
"E",
|
|
59
|
+
"W",
|
|
60
|
+
"F",
|
|
61
|
+
"I",
|
|
62
|
+
"B",
|
|
63
|
+
"C4",
|
|
64
|
+
"PIE",
|
|
65
|
+
"FURB",
|
|
66
|
+
"PERF",
|
|
67
|
+
]
|
|
68
|
+
|
|
69
|
+
[tool.pytest.ini_options]
|
|
70
|
+
testpaths = ["tests"]
|
|
71
|
+
|
|
72
|
+
[tool.coverage.run]
|
|
73
|
+
source = ["mailmap_checker"]
|
|
74
|
+
|
|
75
|
+
[tool.coverage.report]
|
|
76
|
+
show_missing = true
|
|
77
|
+
fail_under = 100
|
|
78
|
+
|
|
79
|
+
[tool.bandit]
|
|
80
|
+
targets = ["src"]
|
|
81
|
+
|
|
82
|
+
[tool.poe]
|
|
83
|
+
env = { UV_PROJECT_ENVIRONMENT = "venv" }
|
|
84
|
+
|
|
85
|
+
[tool.poe.tasks.setup]
|
|
86
|
+
help = "Install git hooks (run once after cloning)"
|
|
87
|
+
sequence = [
|
|
88
|
+
{ cmd = "pre-commit install" },
|
|
89
|
+
{ cmd = "pre-commit install --hook-type commit-msg" },
|
|
90
|
+
]
|
|
91
|
+
|
|
92
|
+
[tool.poe.tasks.lint]
|
|
93
|
+
help = "Run ruff linter and format check"
|
|
94
|
+
sequence = [
|
|
95
|
+
{ cmd = "ruff check src tests" },
|
|
96
|
+
{ cmd = "ruff format --check src tests" },
|
|
97
|
+
]
|
|
98
|
+
|
|
99
|
+
[tool.poe.tasks.format]
|
|
100
|
+
help = "Format code with ruff"
|
|
101
|
+
cmd = "ruff format src tests"
|
|
102
|
+
|
|
103
|
+
[tool.poe.tasks.test]
|
|
104
|
+
help = "Run tests with coverage"
|
|
105
|
+
cmd = "pytest --cov --cov-report=term-missing"
|
|
106
|
+
|
|
107
|
+
[tool.poe.tasks.security]
|
|
108
|
+
help = "Run bandit security checks"
|
|
109
|
+
cmd = "bandit -r src"
|
|
110
|
+
|
|
111
|
+
[tool.poe.tasks.check]
|
|
112
|
+
help = "Run all checks (lint + security + test)"
|
|
113
|
+
sequence = [
|
|
114
|
+
{ ref = "lint" },
|
|
115
|
+
{ ref = "security" },
|
|
116
|
+
{ ref = "test" },
|
|
117
|
+
]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.1.0"
|