gitinspect 0.1.0__py3-none-any.whl

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.
@@ -0,0 +1,233 @@
1
+ Metadata-Version: 2.4
2
+ Name: gitinspect
3
+ Version: 0.1.0
4
+ Summary: Compare environment-level changes between two git branches or commits
5
+ Author-email: Naman Bhola <bhola.naman02@gmail.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/namanbhola1888/diffenv
8
+ Project-URL: Repository, https://github.com/namanbhola1888/diffenv
9
+ Project-URL: Bug Tracker, https://github.com/namanbhola1888/diffenv/issues
10
+ Keywords: git,diff,environment,dependencies,devops,cli
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Environment :: Console
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Topic :: Software Development :: Version Control :: Git
21
+ Classifier: Topic :: Utilities
22
+ Requires-Python: >=3.10
23
+ Description-Content-Type: text/markdown
24
+ Requires-Dist: typer>=0.12.0
25
+ Requires-Dist: rich>=13.0.0
26
+ Requires-Dist: tomli>=2.0.0; python_version < "3.11"
27
+ Provides-Extra: dev
28
+ Requires-Dist: pytest>=8.0.0; extra == "dev"
29
+ Requires-Dist: pytest-cov>=5.0.0; extra == "dev"
30
+ Requires-Dist: build>=1.0.0; extra == "dev"
31
+ Requires-Dist: twine>=5.0.0; extra == "dev"
32
+
33
+ # GitAudit
34
+
35
+ Compare environment-level changes between two git branches or commits — dependencies, environment variables, and Python runtime version — in one unified view. No more manually diffing `requirements.txt`, `.env.example`, and `.python-version` across branches by hand.
36
+
37
+ ```bash
38
+ gitaudit main feature/new-auth
39
+ ```
40
+
41
+ ```text
42
+ Dependencies
43
+ - flask-session
44
+ + requests==2.32.0 (was 2.28.0)
45
+
46
+ Environment Variables
47
+ + JWT_SECRET
48
+ + REDIS_URL
49
+
50
+ Python Runtime
51
+ 3.11 → 3.12
52
+ ```
53
+
54
+ ## Why
55
+
56
+ When reviewing a PR or preparing to merge a branch, "what changed in the environment" is usually scattered across several files and requires manual cross-referencing. `gitaudit` reads both refs directly from git (no checkout required) and reports only what's environment-relevant, in one pass.
57
+
58
+ ## Installation
59
+
60
+ ```bash
61
+ pip install gitaudit
62
+ ```
63
+
64
+ Requires Python 3.10+ and git installed and available on `PATH`.
65
+
66
+ ## CLI usage
67
+
68
+ ```bash
69
+ gitaudit <ref_old> <ref_new> [OPTIONS]
70
+ ```
71
+
72
+ | Option | Description | Default |
73
+ |---|---|---|
74
+ | `--format`, `-f` | Output format: `color`, `text`, or `json` | `color` |
75
+ | `--repo-path`, `-C` | Path to the git repository | `.` (current directory) |
76
+ | `--auto-fetch` | Fetch missing refs from `origin` automatically, no prompt | off |
77
+ | `--verbose`, `-v` | Print debug logs to stderr | off |
78
+
79
+ ### Examples
80
+
81
+ ```bash
82
+ # Compare two branches with colored terminal output
83
+ gitaudit main feature/new-auth
84
+
85
+ # Plain text — safe for piping/redirecting
86
+ gitaudit main feature/new-auth --format text > changes.txt
87
+
88
+ # JSON — for CI pipelines or scripting
89
+ gitaudit main feature/new-auth --format json | jq '.dependencies'
90
+
91
+ # Compare commits or tags directly
92
+ gitaudit v1.2.0 v1.3.0
93
+
94
+ # Run against a repo elsewhere on disk
95
+ gitaudit main develop --repo-path ~/projects/my-app
96
+
97
+ # Non-interactive: auto-fetch missing refs instead of prompting
98
+ gitaudit main origin-only-branch --auto-fetch
99
+ ```
100
+
101
+ ### Exit codes
102
+
103
+ `gitaudit` is CI-friendly: it exits `0` when no environment changes are found, and `1` when changes are detected — useful for gating a build on "did the environment change without sign-off."
104
+
105
+ | Code | Meaning |
106
+ |---|---|
107
+ | `0` | No environment-level changes found |
108
+ | `1` | Changes were found |
109
+ | `2` | Error (bad ref, not a git repo, bad arguments, parse failure) |
110
+
111
+ ### Missing branches
112
+
113
+ If a ref doesn't exist locally, `gitaudit` will:
114
+
115
+ 1. Check whether it exists on the `origin` remote.
116
+ 2. Prompt you to confirm fetching it (unless `--auto-fetch` is set).
117
+ 3. Fetch it and proceed, or fail with a clear message if it can't be found anywhere.
118
+
119
+ No raw git errors are ever shown — only clean, actionable messages.
120
+
121
+ ## Python SDK
122
+
123
+ ```python
124
+ from gitaudit import compare
125
+
126
+ # Get a structured result
127
+ result = compare("main", "feature/new-auth")
128
+ for change in result.dep_changes:
129
+ print(change.name, change.old_version, "->", change.new_version)
130
+
131
+ # Or get pre-rendered output directly
132
+ text = compare("main", "feature/new-auth", output_format="text")
133
+ json_str = compare("main", "feature/new-auth", output_format="json")
134
+ ```
135
+
136
+ By default, the SDK auto-fetches missing refs (`auto_fetch=True`) since scripted use can't respond to an interactive prompt. Pass `auto_fetch=False` to raise `RefNotFoundError` instead.
137
+
138
+ ```python
139
+ from gitaudit import compare
140
+ from gitaudit.exceptions import RefNotFoundError, NotAGitRepoError, ParseError
141
+
142
+ try:
143
+ result = compare("main", "feature/x", repo_path="/path/to/repo")
144
+ except RefNotFoundError as e:
145
+ print(f"Ref not found: {e.ref}")
146
+ except NotAGitRepoError:
147
+ print("Not a git repository")
148
+ except ParseError as e:
149
+ print(f"Could not parse {e.filename}")
150
+ ```
151
+
152
+ ## What it tracks
153
+
154
+ | File | What's compared |
155
+ |---|---|
156
+ | `requirements.txt` | Package additions, removals, and `==` version pins |
157
+ | `pyproject.toml` | `[project.dependencies]` (PEP 621), `requires-python` |
158
+ | `.env.example` | Declared environment variable keys (values are not compared) |
159
+ | `.python-version` | Exact pinned Python version |
160
+
161
+ Dependency names are matched case-insensitively (PyPI convention). Environment variable keys are matched case-sensitively (OS convention).
162
+
163
+ **Not yet supported** (natural extension points for a future parser):
164
+ - Poetry's `[tool.poetry.dependencies]`
165
+ - `Pipfile` / `Pipfile.lock`
166
+ - `package.json` (Node environments)
167
+ - Lockfile-level diffing (`poetry.lock`, `requirements-lock.txt`)
168
+
169
+ ## Architecture
170
+
171
+ ```
172
+ git ref ──▶ git_layer ──▶ parser_layer ──▶ diff_layer ──▶ formatter_layer ──▶ output
173
+ (fetch file (parse text (compare two (render as
174
+ content, into typed ParsedSnapshots text/json/color)
175
+ no checkout) models) → DiffResult)
176
+ ```
177
+
178
+ - **`git_layer`** — reads file content at any ref via `git show`, never touches your working tree or index. Handles missing-branch detection and remote fetching.
179
+ - **`parser_layer`** — one function per file type, registered independently. Adding a new file type means writing one parser function — no other layer changes.
180
+ - **`diff_layer`** — pure data comparison between two parsed snapshots, no I/O.
181
+ - **`formatter_layer`** — one class per output format (`text`, `json`, `color`), all swappable via dependency injection through `get_formatter(name)`.
182
+
183
+ Everything is fully offline — no network calls except an optional `git fetch` when a ref is missing locally, and no AI/external APIs are used anywhere.
184
+
185
+ ## Development
186
+
187
+ ```bash
188
+ git clone https://github.com/namanbhola1888/diffenv
189
+ cd diffenv
190
+ pip install -e ".[dev]"
191
+ ```
192
+
193
+ ### Running tests
194
+
195
+ ```bash
196
+ pytest
197
+ ```
198
+
199
+ Tests are split into fast unit tests (`test_models.py`, `test_parser_layer.py`, `test_diff_layer.py`, `test_formatter_layer.py`, `test_exceptions.py` — no I/O, no git) and integration tests (`test_git_layer.py`, `test_api.py`) that build real temporary git repositories via fixtures in `conftest.py` rather than mocking subprocess calls, since git_layer's correctness depends on actually invoking git.
200
+
201
+ ```bash
202
+ # Run with coverage
203
+ pytest --cov=gitaudit --cov-report=term-missing
204
+
205
+ # Run only fast unit tests, skipping integration tests that shell out to git
206
+ pytest tests/test_models.py tests/test_parser_layer.py tests/test_diff_layer.py tests/test_formatter_layer.py tests/test_exceptions.py
207
+ ```
208
+
209
+ ## Building and publishing to PyPI
210
+
211
+ ```bash
212
+ # 1. Install build tooling
213
+ pip install --upgrade build twine
214
+
215
+ # 2. Build the distribution
216
+ python -m build
217
+
218
+ # 3. Check the build for issues
219
+ twine check dist/*
220
+
221
+ # 4. Upload to TestPyPI first (recommended)
222
+ twine upload --repository testpypi dist/*
223
+ pip install --index-url https://test.pypi.org/simple/ gitaudit
224
+
225
+ # 5. Upload to the real PyPI
226
+ twine upload dist/*
227
+ ```
228
+
229
+ You'll need a PyPI account and an API token (set via `~/.pypirc` or the `TWINE_PASSWORD` environment variable with `__token__` as the username).
230
+
231
+ ## License
232
+
233
+ MIT
@@ -0,0 +1,15 @@
1
+ diffenv/__init__.py,sha256=lm1LCoReWTWsSHzIHwKrWofpXdlO3Ia76TdOwIJ1Io8,203
2
+ diffenv/api.py,sha256=3o9GIsTw5WZKElEt8zFYz8-U3Kr7mQ7yT4hukKBWla4,2912
3
+ diffenv/cli.py,sha256=fd1BmvCoJYut5-fTtVaJzgvM9Ni4XxLNRdM6RbZnyRk,5235
4
+ diffenv/diff_layer.py,sha256=uN6HTFQLhvV0NnabOE1mCOJUlYAUF7plxYs4W4xpqIg,3674
5
+ diffenv/exceptions.py,sha256=YPwFHrAa7QlCCO1om4MJG9DgJ8xCRb6iCeKUX02zIGo,835
6
+ diffenv/formatter_layer.py,sha256=UmPtYsKAMuBZ0XyEuc2S3vGYWBfn8N8wQgWP0QeTfJo,7149
7
+ diffenv/git_layer.py,sha256=iDTnOObYdwBz3l4EfSmuZR3woXz5GUllGsmeGpTSEqY,11263
8
+ diffenv/logging_config.py,sha256=-qC-6wu2j9DwMDEQetHQtKP2H2KOD-BeHrdjInKVW_E,754
9
+ diffenv/models.py,sha256=lGQPT1ivGcRCytD4DymhlIQ7V-wSTit1tWyK9Qzw3EQ,2944
10
+ diffenv/parser_layer.py,sha256=g_axBDUeyFse_2JPkMbv30ceyUgRI3tMPnOZhN8pTTg,9610
11
+ gitinspect-0.1.0.dist-info/METADATA,sha256=d6xS3YuMKp4-eKrgTtwAknEzECek9uJH5_W9EuG4ydY,8429
12
+ gitinspect-0.1.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
13
+ gitinspect-0.1.0.dist-info/entry_points.txt,sha256=fIphoV37-YiJ40Lv6E3AdyjtnruquRJq1emPNCRJsUU,47
14
+ gitinspect-0.1.0.dist-info/top_level.txt,sha256=VTTMWjMnZWfKPEvZetYl22y7ci_jo2WXwj3uu9I4ApA,8
15
+ gitinspect-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (82.0.1)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ gitinspect = diffenv.cli:app
@@ -0,0 +1 @@
1
+ diffenv