db-git 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.
- db_git-0.1.0.dist-info/METADATA +363 -0
- db_git-0.1.0.dist-info/RECORD +30 -0
- db_git-0.1.0.dist-info/WHEEL +4 -0
- db_git-0.1.0.dist-info/entry_points.txt +2 -0
- db_git-0.1.0.dist-info/licenses/LICENSE +21 -0
- git_db/__init__.py +1 -0
- git_db/backends/__init__.py +173 -0
- git_db/backends/postgresql/__init__.py +0 -0
- git_db/backends/postgresql/backend.py +176 -0
- git_db/backends/postgresql/branch_db.py +203 -0
- git_db/backends/postgresql/connections.py +82 -0
- git_db/backends/postgresql/pgdump.py +212 -0
- git_db/backends/postgresql/template.py +160 -0
- git_db/cli/__init__.py +8 -0
- git_db/cli/_common.py +41 -0
- git_db/cli/_console.py +18 -0
- git_db/cli/_format.py +56 -0
- git_db/cli/_prompts.py +121 -0
- git_db/cli/branch.py +168 -0
- git_db/cli/hook.py +102 -0
- git_db/cli/init.py +267 -0
- git_db/cli/inspect.py +414 -0
- git_db/cli/snapshot.py +115 -0
- git_db/config.py +243 -0
- git_db/db.py +17 -0
- git_db/errors.py +46 -0
- git_db/git.py +349 -0
- git_db/hook_script.py +49 -0
- git_db/state.py +105 -0
- git_db/storage.py +203 -0
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: db-git
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Keep your database in sync with your git branches.
|
|
5
|
+
Project-URL: Homepage, https://github.com/earthcomfy/git-db
|
|
6
|
+
Project-URL: Repository, https://github.com/earthcomfy/git-db
|
|
7
|
+
Project-URL: Issues, https://github.com/earthcomfy/git-db/issues
|
|
8
|
+
Project-URL: Changelog, https://github.com/earthcomfy/git-db/blob/main/CHANGELOG.md
|
|
9
|
+
Author: Hana Belay
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: branching,cli,database,developer-tools,git,migrations,postgresql,snapshot
|
|
13
|
+
Classifier: Development Status :: 3 - Alpha
|
|
14
|
+
Classifier: Environment :: Console
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
17
|
+
Classifier: Operating System :: OS Independent
|
|
18
|
+
Classifier: Programming Language :: Python :: 3
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Topic :: Database
|
|
22
|
+
Classifier: Topic :: Software Development :: Version Control :: Git
|
|
23
|
+
Classifier: Topic :: Utilities
|
|
24
|
+
Classifier: Typing :: Typed
|
|
25
|
+
Requires-Python: >=3.12
|
|
26
|
+
Requires-Dist: psycopg[binary]>=3.3.0
|
|
27
|
+
Requires-Dist: rich>=14.0.0
|
|
28
|
+
Requires-Dist: tomlkit>=0.14.0
|
|
29
|
+
Requires-Dist: typer>=0.24.1
|
|
30
|
+
Description-Content-Type: text/markdown
|
|
31
|
+
|
|
32
|
+
# git-db
|
|
33
|
+
|
|
34
|
+
[](https://github.com/earthcomfy/git-db/actions/workflows/test.yml)
|
|
35
|
+
[](https://pypi.org/project/git-db/)
|
|
36
|
+
[](LICENSE)
|
|
37
|
+
|
|
38
|
+
Keep your database in sync with your git branches.
|
|
39
|
+
|
|
40
|
+
`git-db` is a developer tool for projects where database state follows code
|
|
41
|
+
changes: schema migrations, seed data, experimental feature work, and branch
|
|
42
|
+
switching during reviews. It installs a git `post-checkout` hook and keeps your
|
|
43
|
+
local database aligned with the branch you are working on.
|
|
44
|
+
|
|
45
|
+
> Status: PostgreSQL is supported today; support for additional database
|
|
46
|
+
> engines is planned.
|
|
47
|
+
|
|
48
|
+
## Features
|
|
49
|
+
|
|
50
|
+
- Automatic database handling on `git checkout`
|
|
51
|
+
- Two workflows:
|
|
52
|
+
- `shared`: one database, saved and restored per branch
|
|
53
|
+
- `per-branch`: one database per branch
|
|
54
|
+
- PostgreSQL support today, with plans for more database backends
|
|
55
|
+
- Two PostgreSQL snapshot strategies:
|
|
56
|
+
- `template`: fast database clones using `CREATE DATABASE ... TEMPLATE`
|
|
57
|
+
- `pgdump`: portable snapshots using `pg_dump` and `pg_restore`
|
|
58
|
+
- Manual `save`, `restore`, `create`, `reset`, `list`, `status`, and `prune`
|
|
59
|
+
commands
|
|
60
|
+
- Safe hook behavior: checkout is never blocked by git-db failures
|
|
61
|
+
- Rich terminal output and local state stored under `.git/git-db/`
|
|
62
|
+
|
|
63
|
+
## Quick Start
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
uv tool install git-db # or pip install git-db
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Run this from inside a git repository:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
git-db init --database-url postgresql://postgres:postgres@localhost:5432/myapp
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Interactive init will ask:
|
|
76
|
+
|
|
77
|
+
- Whether to use `shared` or `per-branch` mode
|
|
78
|
+
- Whether to use `template` or `pgdump` strategy
|
|
79
|
+
- What to do when active connections block database operations
|
|
80
|
+
- Whether to install the git `post-checkout` hook
|
|
81
|
+
|
|
82
|
+
After setup, switch branches normally:
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
git checkout feature/auth
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
In `shared` mode, git-db saves the previous branch database and restores the
|
|
89
|
+
new branch snapshot if one exists.
|
|
90
|
+
|
|
91
|
+
In `per-branch` mode, git-db creates or selects a database named from the
|
|
92
|
+
current branch, for example:
|
|
93
|
+
|
|
94
|
+
```text
|
|
95
|
+
myapp__feature__auth
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Because the database name changes per branch, your application server also
|
|
99
|
+
needs to connect to the branch database. For example, when working on
|
|
100
|
+
`feature/auth`, point your app's `DATABASE_URL` at `myapp__feature__auth`.
|
|
101
|
+
|
|
102
|
+
## Choosing a Mode
|
|
103
|
+
|
|
104
|
+
### Shared Mode
|
|
105
|
+
|
|
106
|
+
Shared mode keeps one database name from `DATABASE_URL`.
|
|
107
|
+
|
|
108
|
+
Use this when:
|
|
109
|
+
|
|
110
|
+
- You want one familiar local database name
|
|
111
|
+
- You want branch-specific snapshots
|
|
112
|
+
- You are comfortable with git-db dropping and restoring that local database
|
|
113
|
+
during branch switches
|
|
114
|
+
|
|
115
|
+
### Per-Branch Mode
|
|
116
|
+
|
|
117
|
+
Per-branch mode creates a separate database for each branch. The configured
|
|
118
|
+
default branch keeps the original database name and acts as the seed database.
|
|
119
|
+
|
|
120
|
+
Use this when:
|
|
121
|
+
|
|
122
|
+
- You want branch databases to persist independently
|
|
123
|
+
- You prefer creating new databases over repeatedly restoring one shared
|
|
124
|
+
database
|
|
125
|
+
|
|
126
|
+
## Choosing a Strategy
|
|
127
|
+
|
|
128
|
+
### template
|
|
129
|
+
|
|
130
|
+
The `template` strategy uses PostgreSQL database cloning:
|
|
131
|
+
|
|
132
|
+
```sql
|
|
133
|
+
CREATE DATABASE target TEMPLATE source;
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
It is usually fast, but requires sufficient PostgreSQL privileges and can be
|
|
137
|
+
blocked by active connections to the source or target database.
|
|
138
|
+
|
|
139
|
+
### pgdump
|
|
140
|
+
|
|
141
|
+
The `pgdump` strategy uses `pg_dump` and `pg_restore`.
|
|
142
|
+
|
|
143
|
+
It is slower than `template`, but can be a better fit when template cloning is
|
|
144
|
+
not available. It requires PostgreSQL client tools to be installed locally.
|
|
145
|
+
|
|
146
|
+
## Commands
|
|
147
|
+
|
|
148
|
+
### Initialize
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
git-db init --database-url postgresql://user:password@localhost:5432/myapp
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
Useful options:
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
git-db init \
|
|
158
|
+
--database-url postgresql://user:password@localhost:5432/myapp \
|
|
159
|
+
--mode per-branch \
|
|
160
|
+
--strategy template \
|
|
161
|
+
--on-active-connections terminate
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
Skip hook installation:
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
git-db init --database-url postgresql://localhost/myapp --no-hook
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### Inspect State
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
git-db status
|
|
174
|
+
git-db list
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### Shared Mode Commands
|
|
178
|
+
|
|
179
|
+
Save the current branch database:
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
git-db save
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
Restore the current branch database:
|
|
186
|
+
|
|
187
|
+
```bash
|
|
188
|
+
git-db restore
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
Save or restore a specific branch:
|
|
192
|
+
|
|
193
|
+
```bash
|
|
194
|
+
git-db save main
|
|
195
|
+
git-db restore feature/auth
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### Per-Branch Commands
|
|
199
|
+
|
|
200
|
+
Create a branch database before checking out the branch:
|
|
201
|
+
|
|
202
|
+
```bash
|
|
203
|
+
git-db create feature/auth
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
Drop and recreate a branch database from the seed database:
|
|
207
|
+
|
|
208
|
+
```bash
|
|
209
|
+
git-db reset feature/auth
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
The default branch database cannot be reset because it is the seed for other
|
|
213
|
+
branch databases.
|
|
214
|
+
|
|
215
|
+
### Prune Deleted Branches
|
|
216
|
+
|
|
217
|
+
Preview stale snapshots or branch databases:
|
|
218
|
+
|
|
219
|
+
```bash
|
|
220
|
+
git-db prune --dry-run
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
Remove stale snapshots or branch databases:
|
|
224
|
+
|
|
225
|
+
```bash
|
|
226
|
+
git-db prune --yes
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
### Hook Management
|
|
230
|
+
|
|
231
|
+
Install or reinstall the checkout hook:
|
|
232
|
+
|
|
233
|
+
```bash
|
|
234
|
+
git-db hook install
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
Remove the checkout hook:
|
|
238
|
+
|
|
239
|
+
```bash
|
|
240
|
+
git-db hook remove
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
Temporarily disable git-db without removing the hook:
|
|
244
|
+
|
|
245
|
+
```bash
|
|
246
|
+
git-db disable
|
|
247
|
+
git-db enable
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
You can also skip hook behavior for a single checkout:
|
|
251
|
+
|
|
252
|
+
```bash
|
|
253
|
+
GIT_DB_SKIP=1 git checkout other-branch
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
## Configuration
|
|
257
|
+
|
|
258
|
+
`git-db init` writes `.git-db.toml` at the repository root.
|
|
259
|
+
|
|
260
|
+
Example:
|
|
261
|
+
|
|
262
|
+
```toml
|
|
263
|
+
database_url = "postgresql://postgres:postgres@localhost:5432/myapp"
|
|
264
|
+
mode = "per-branch"
|
|
265
|
+
default_branch = "main"
|
|
266
|
+
strategy = "template"
|
|
267
|
+
on_active_connections = "terminate"
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
Supported configuration keys:
|
|
271
|
+
|
|
272
|
+
| Key | Description | Default |
|
|
273
|
+
| --- | --- | --- |
|
|
274
|
+
| `database_url` | Database connection URL | required |
|
|
275
|
+
| `mode` | `shared` or `per-branch` | `shared` |
|
|
276
|
+
| `default_branch` | Seed branch for per-branch mode | `main` |
|
|
277
|
+
| `strategy` | `template` or `pgdump` | required |
|
|
278
|
+
| `on_active_connections` | `terminate` or `fail` | `terminate` |
|
|
279
|
+
| `snapshot_dir` | Shared-mode snapshot metadata/dump directory | `.git/git-db/snapshots` |
|
|
280
|
+
| `max_snapshots` | Snapshot count kept by prune logic | `20` |
|
|
281
|
+
| `force_terminate_timeout_ms` | Active connection termination timeout | `5000` |
|
|
282
|
+
|
|
283
|
+
Configuration precedence:
|
|
284
|
+
|
|
285
|
+
1. Built-in defaults
|
|
286
|
+
2. `.git-db.toml`
|
|
287
|
+
3. Environment variables
|
|
288
|
+
4. CLI options
|
|
289
|
+
|
|
290
|
+
Environment variables:
|
|
291
|
+
|
|
292
|
+
```bash
|
|
293
|
+
DATABASE_URL
|
|
294
|
+
GIT_DB_DATABASE_URL
|
|
295
|
+
GIT_DB_MODE
|
|
296
|
+
GIT_DB_STRATEGY
|
|
297
|
+
GIT_DB_ON_ACTIVE_CONNECTIONS
|
|
298
|
+
GIT_DB_SNAPSHOT_DIR
|
|
299
|
+
GIT_DB_MAX_SNAPSHOTS
|
|
300
|
+
GIT_DB_FORCE_TERMINATE_TIMEOUT_MS
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
`GIT_DB_DATABASE_URL` takes precedence over `DATABASE_URL`.
|
|
304
|
+
|
|
305
|
+
### Active connections block an operation
|
|
306
|
+
|
|
307
|
+
Stop your development server, database console, migration watcher, or GUI
|
|
308
|
+
client, then retry.
|
|
309
|
+
|
|
310
|
+
Alternatively, configure:
|
|
311
|
+
|
|
312
|
+
```toml
|
|
313
|
+
on_active_connections = "terminate"
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
Your PostgreSQL user may need superuser privileges or membership in
|
|
317
|
+
`pg_signal_backend` to terminate sessions owned by other users.
|
|
318
|
+
|
|
319
|
+
### Temporarily skip git-db
|
|
320
|
+
|
|
321
|
+
```bash
|
|
322
|
+
git-db disable
|
|
323
|
+
git checkout some-branch
|
|
324
|
+
git-db enable
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
Or for one command:
|
|
328
|
+
|
|
329
|
+
```bash
|
|
330
|
+
GIT_DB_SKIP=1 git checkout some-branch
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
### Show full tracebacks
|
|
334
|
+
|
|
335
|
+
```bash
|
|
336
|
+
GIT_DB_DEBUG=1 git-db status
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
## Development
|
|
340
|
+
|
|
341
|
+
Install dependencies:
|
|
342
|
+
|
|
343
|
+
```bash
|
|
344
|
+
uv sync --group dev
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
Run checks:
|
|
348
|
+
|
|
349
|
+
```bash
|
|
350
|
+
uv run ruff check .
|
|
351
|
+
uv run mypy src tests
|
|
352
|
+
uv run pytest tests/unit
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
Run the full nox suite:
|
|
356
|
+
|
|
357
|
+
```bash
|
|
358
|
+
nox
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
## License
|
|
362
|
+
|
|
363
|
+
MIT
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
git_db/__init__.py,sha256=kUR5RAFc7HCeiqdlX36dZOHkUI5wI6V_43RpEcD8b-0,22
|
|
2
|
+
git_db/config.py,sha256=9mE8Pwc6iFnc6wfX_9HjzpJkwSGQNtYcp6c3mcDfPAI,7414
|
|
3
|
+
git_db/db.py,sha256=FA3VWaG7Avm6NyXP4eFwPJAP2TLF2bxa416eGalSrSs,533
|
|
4
|
+
git_db/errors.py,sha256=_KvV20_N3PP9ESETvsl0L4k55y8rl8F22AVpYb-w9q0,754
|
|
5
|
+
git_db/git.py,sha256=G-XW-xEt97Wh5TEsyVTH_0NX0UbvPhIa0NDzcXwPyvw,10057
|
|
6
|
+
git_db/hook_script.py,sha256=KEA1xt77J8IvS0SbpqMLgwgV4y2fgK7BA6wWBEHDqaA,1434
|
|
7
|
+
git_db/state.py,sha256=42_ikKGJG6f52sohk6fz-nAqhOLOnB5ZVLkiLvA4NYg,2568
|
|
8
|
+
git_db/storage.py,sha256=Fid6jepNM1-8lYTX-324WXEkk7Bma3HubSxXjKz7k6s,5592
|
|
9
|
+
git_db/backends/__init__.py,sha256=onyhOXPXR_eh38C4WJDAzLu-J0CJP8cuW4vchnS80CA,4020
|
|
10
|
+
git_db/backends/postgresql/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
11
|
+
git_db/backends/postgresql/backend.py,sha256=uaYRnb1JMeT0ER2xNrfEwRBd1dDsFA2Tug9X0r2lUYg,6026
|
|
12
|
+
git_db/backends/postgresql/branch_db.py,sha256=PEA1QTz7U3Vkkx1S8N9Gl2gqYPUecejNGBVPQ3dadTo,5726
|
|
13
|
+
git_db/backends/postgresql/connections.py,sha256=gR3IV4MTQlfBNo8lR78a8HJMvAqE1-kKdZ_NgqGnPM0,2453
|
|
14
|
+
git_db/backends/postgresql/pgdump.py,sha256=-epWSQvSypV6BGK2hyeO6gul_JIdEbsglA4hs7OH0BA,5629
|
|
15
|
+
git_db/backends/postgresql/template.py,sha256=fexuoTy0IKrs8V1zDIyJO1L8ZSpTDSAYeP5jw70pgug,4490
|
|
16
|
+
git_db/cli/__init__.py,sha256=ZLn5HbrLOokWC1rt7QY2hUPaj55w2SC7sGVCi4Pa1Rk,225
|
|
17
|
+
git_db/cli/_common.py,sha256=uyzlafCaB-tsUrRq25UmboujblA5v3g_9jLCBRU3zqQ,1042
|
|
18
|
+
git_db/cli/_console.py,sha256=nK7JES1yT7oi1iRMuPQY8P9oHttD4WMDd8l2ZoqEF6s,409
|
|
19
|
+
git_db/cli/_format.py,sha256=g1CEy-E8rz_sfRhRxwcYlCg0SsvUK6FZZgUQQNM54pg,1616
|
|
20
|
+
git_db/cli/_prompts.py,sha256=lfknOgNHNAPWkMi4RRIbrVbn6RZIgMqzRyb7ta5pLE4,3076
|
|
21
|
+
git_db/cli/branch.py,sha256=jtBA-i-TR7HE-dYj_Azxa1yJMwGXoGDaS7hao3S1h3Y,5377
|
|
22
|
+
git_db/cli/hook.py,sha256=-DW_0sOo7hHot5j0aqSISsmZAmFrns-XsyYJb5Xv85U,2640
|
|
23
|
+
git_db/cli/init.py,sha256=fsQhka7DdMj3i1vdWro9lVxBF1oB0eKQMh0J6Qc57qQ,9248
|
|
24
|
+
git_db/cli/inspect.py,sha256=ma_bF53Sy6DFN3orgF88wXyHKdZlrcbCIgGyLL5xb14,12457
|
|
25
|
+
git_db/cli/snapshot.py,sha256=5OjMdwr97Ga2HqK6xLf2sXNJbH6iAzyW5ZhEYUjpNSo,3713
|
|
26
|
+
db_git-0.1.0.dist-info/METADATA,sha256=VLNZ4dZ_nqdRfLoWpqAtuOb4xWJM3-iCGVBoWQGihp8,8451
|
|
27
|
+
db_git-0.1.0.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
|
|
28
|
+
db_git-0.1.0.dist-info/entry_points.txt,sha256=dU0NWsfYR8-COUVsowXR795CsqRqSFE-yBijHSX-wN8,42
|
|
29
|
+
db_git-0.1.0.dist-info/licenses/LICENSE,sha256=JTB2YQpxa0QXq1mU53Qj0hi-CwzxrV4GWa0g4FTZl8Q,1067
|
|
30
|
+
db_git-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Hana Belay
|
|
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.
|
git_db/__init__.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.1.0"
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import contextlib
|
|
4
|
+
import importlib
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import TYPE_CHECKING, Any, Protocol, runtime_checkable
|
|
7
|
+
from urllib.parse import urlparse
|
|
8
|
+
|
|
9
|
+
from git_db.errors import ConfigError
|
|
10
|
+
|
|
11
|
+
if TYPE_CHECKING:
|
|
12
|
+
from git_db.config import GitDbConfig
|
|
13
|
+
from git_db.state import BranchDbEntry
|
|
14
|
+
|
|
15
|
+
_BACKEND_REGISTRY: dict[str, type[DatabaseBackend]] = {}
|
|
16
|
+
_BUILTIN_BACKENDS: dict[str, str] = {
|
|
17
|
+
"postgresql": "git_db.backends.postgresql.backend",
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class DbCursor(Protocol):
|
|
22
|
+
"""
|
|
23
|
+
Minimal cursor protocol for database query results.
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
def fetchone(self) -> tuple[Any, ...] | None: ...
|
|
27
|
+
def fetchall(self) -> list[tuple[Any, ...]]: ...
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class DbConnection(Protocol):
|
|
31
|
+
"""
|
|
32
|
+
Minimal connection protocol returned by connect_maintenance.
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
def execute(self, query: Any, params: Any = None) -> DbCursor: ...
|
|
36
|
+
def close(self) -> None: ...
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
@runtime_checkable
|
|
40
|
+
class SnapshotStrategy(Protocol):
|
|
41
|
+
"""
|
|
42
|
+
Protocol for snapshot save/restore strategies.
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
name: str
|
|
46
|
+
|
|
47
|
+
def save(
|
|
48
|
+
self,
|
|
49
|
+
db_url: str,
|
|
50
|
+
branch: str,
|
|
51
|
+
snapshot_dir: Path,
|
|
52
|
+
config: GitDbConfig,
|
|
53
|
+
) -> None: ...
|
|
54
|
+
|
|
55
|
+
def restore(
|
|
56
|
+
self,
|
|
57
|
+
db_url: str,
|
|
58
|
+
branch: str,
|
|
59
|
+
snapshot_dir: Path,
|
|
60
|
+
config: GitDbConfig,
|
|
61
|
+
) -> None: ...
|
|
62
|
+
|
|
63
|
+
def cleanup(
|
|
64
|
+
self,
|
|
65
|
+
branch: str,
|
|
66
|
+
snapshot_dir: Path,
|
|
67
|
+
config: GitDbConfig,
|
|
68
|
+
) -> None: ...
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
class BranchDbManager(Protocol):
|
|
72
|
+
"""
|
|
73
|
+
Protocol for per-branch database operations.
|
|
74
|
+
"""
|
|
75
|
+
|
|
76
|
+
def exists(self, name: str) -> bool: ...
|
|
77
|
+
|
|
78
|
+
def create(
|
|
79
|
+
self,
|
|
80
|
+
target: str,
|
|
81
|
+
source: str,
|
|
82
|
+
branch: str,
|
|
83
|
+
created_from: str,
|
|
84
|
+
git_dir: Path,
|
|
85
|
+
) -> None: ...
|
|
86
|
+
|
|
87
|
+
def drop(
|
|
88
|
+
self,
|
|
89
|
+
name: str,
|
|
90
|
+
branch: str,
|
|
91
|
+
git_dir: Path,
|
|
92
|
+
) -> None: ...
|
|
93
|
+
|
|
94
|
+
def list(
|
|
95
|
+
self,
|
|
96
|
+
git_dir: Path,
|
|
97
|
+
) -> list[tuple[str, BranchDbEntry, bool]]: ...
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
@runtime_checkable
|
|
101
|
+
class DatabaseBackend(Protocol):
|
|
102
|
+
"""
|
|
103
|
+
Protocol for database engine backends.
|
|
104
|
+
"""
|
|
105
|
+
|
|
106
|
+
engine: str
|
|
107
|
+
max_identifier_length: int
|
|
108
|
+
|
|
109
|
+
def apply_url_defaults(
|
|
110
|
+
self, params: dict[str, str | int | None]
|
|
111
|
+
) -> dict[str, str | int]: ...
|
|
112
|
+
|
|
113
|
+
def get_engine_version(self, url: str) -> int: ...
|
|
114
|
+
|
|
115
|
+
def detect_strategy(self, config: GitDbConfig) -> SnapshotStrategy: ...
|
|
116
|
+
|
|
117
|
+
def branch_db_manager(self, config: GitDbConfig) -> BranchDbManager: ...
|
|
118
|
+
|
|
119
|
+
def connect_maintenance(self, params: dict[str, str | int]) -> DbConnection: ...
|
|
120
|
+
|
|
121
|
+
def build_subprocess_env(self, params: dict[str, str | int]) -> dict[str, str]: ...
|
|
122
|
+
|
|
123
|
+
def check_permissions(self, url: str) -> object: ...
|
|
124
|
+
|
|
125
|
+
def database_exists(self, url: str, name: str) -> bool: ...
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def register_backend(scheme: str, cls: type[DatabaseBackend]) -> None:
|
|
129
|
+
"""
|
|
130
|
+
Register a backend class for a URL scheme.
|
|
131
|
+
"""
|
|
132
|
+
_BACKEND_REGISTRY[scheme] = cls
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def get_backend(url: str) -> DatabaseBackend:
|
|
136
|
+
"""
|
|
137
|
+
Auto-detect and instantiate the correct backend from a database URL.
|
|
138
|
+
"""
|
|
139
|
+
parsed = urlparse(url)
|
|
140
|
+
scheme = parsed.scheme or "postgresql"
|
|
141
|
+
|
|
142
|
+
if scheme in ("postgres", "postgresql"):
|
|
143
|
+
scheme = "postgresql"
|
|
144
|
+
|
|
145
|
+
if scheme not in _BACKEND_REGISTRY:
|
|
146
|
+
_try_import_backend(scheme)
|
|
147
|
+
|
|
148
|
+
if scheme not in _BACKEND_REGISTRY:
|
|
149
|
+
supported = ", ".join(sorted(_BACKEND_REGISTRY.keys())) or "none"
|
|
150
|
+
raise ConfigError(
|
|
151
|
+
f"Unknown database scheme '{scheme}'. Supported: {supported}."
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
return _BACKEND_REGISTRY[scheme]()
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def _try_import_backend(scheme: str) -> None:
|
|
158
|
+
"""
|
|
159
|
+
Attempt to import a built-in backend module to trigger registration.
|
|
160
|
+
"""
|
|
161
|
+
module_name = _BUILTIN_BACKENDS.get(scheme)
|
|
162
|
+
if module_name:
|
|
163
|
+
with contextlib.suppress(ImportError):
|
|
164
|
+
importlib.import_module(module_name)
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
__all__ = [
|
|
168
|
+
"BranchDbManager",
|
|
169
|
+
"DatabaseBackend",
|
|
170
|
+
"SnapshotStrategy",
|
|
171
|
+
"get_backend",
|
|
172
|
+
"register_backend",
|
|
173
|
+
]
|
|
File without changes
|