gitgrip 1.5.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.
Files changed (80) hide show
  1. gitgrip-1.5.0.dist-info/METADATA +13 -0
  2. gitgrip-1.5.0.dist-info/RECORD +80 -0
  3. gitgrip-1.5.0.dist-info/WHEEL +5 -0
  4. gitgrip-1.5.0.dist-info/entry_points.txt +2 -0
  5. gitgrip-1.5.0.dist-info/top_level.txt +2 -0
  6. gr2/__init__.py +0 -0
  7. gr2/overlay/__init__.py +6 -0
  8. gr2/overlay/activate.py +196 -0
  9. gr2/overlay/agent_manifest.py +138 -0
  10. gr2/overlay/cli.py +181 -0
  11. gr2/overlay/cross_repo.py +124 -0
  12. gr2/overlay/drivers.py +113 -0
  13. gr2/overlay/introspection.py +155 -0
  14. gr2/overlay/language_drivers.py +115 -0
  15. gr2/overlay/objects.py +412 -0
  16. gr2/overlay/perf.py +251 -0
  17. gr2/overlay/refs.py +36 -0
  18. gr2/overlay/trust.py +150 -0
  19. gr2/overlay/types.py +69 -0
  20. gr2/overlay/units.py +313 -0
  21. gr2/overlay/workspace_spec.py +59 -0
  22. gr2/prototypes/__init__.py +0 -0
  23. gr2/prototypes/cache_materialization_probe.py +190 -0
  24. gr2/prototypes/concurrent_event_stress.py +199 -0
  25. gr2/prototypes/concurrent_lease_stress.py +240 -0
  26. gr2/prototypes/concurrent_workspace_cap_stress.py +231 -0
  27. gr2/prototypes/contribution_protocol.py +665 -0
  28. gr2/prototypes/cross_mode_lane_stress.py +986 -0
  29. gr2/prototypes/jsonl_store.py +158 -0
  30. gr2/prototypes/lane_workspace_prototype.py +2088 -0
  31. gr2/prototypes/layout_model_probe.py +139 -0
  32. gr2/prototypes/propagation_daemon.py +546 -0
  33. gr2/prototypes/propagation_state_machine.py +1478 -0
  34. gr2/prototypes/python_exec_playground.py +194 -0
  35. gr2/prototypes/python_hook_runtime_playground.py +240 -0
  36. gr2/prototypes/python_migration_playground.py +144 -0
  37. gr2/prototypes/python_review_checkout_playground.py +242 -0
  38. gr2/prototypes/python_spec_apply_playground.py +282 -0
  39. gr2/prototypes/real_git_lane_materialization.py +248 -0
  40. gr2/prototypes/real_git_playground.py +334 -0
  41. gr2/prototypes/recall_lane_history.py +274 -0
  42. gr2/prototypes/repo_maintenance_prototype.py +659 -0
  43. gr2/prototypes/repo_transport_probe.py +147 -0
  44. gr2/python_cli/__init__.py +2 -0
  45. gr2/python_cli/__main__.py +6 -0
  46. gr2/python_cli/add.py +51 -0
  47. gr2/python_cli/app.py +2516 -0
  48. gr2/python_cli/branch.py +67 -0
  49. gr2/python_cli/channel_bridge.py +131 -0
  50. gr2/python_cli/clone_exec.py +1019 -0
  51. gr2/python_cli/commit.py +199 -0
  52. gr2/python_cli/config.py +291 -0
  53. gr2/python_cli/env_exec.py +419 -0
  54. gr2/python_cli/events.py +529 -0
  55. gr2/python_cli/execops.py +372 -0
  56. gr2/python_cli/failures.py +98 -0
  57. gr2/python_cli/file_exec.py +256 -0
  58. gr2/python_cli/gitops.py +226 -0
  59. gr2/python_cli/grip.py +1337 -0
  60. gr2/python_cli/grip_cli.py +493 -0
  61. gr2/python_cli/hooks.py +450 -0
  62. gr2/python_cli/launch_exec.py +786 -0
  63. gr2/python_cli/merge_verification.py +274 -0
  64. gr2/python_cli/migration.py +985 -0
  65. gr2/python_cli/open_gr_review.py +699 -0
  66. gr2/python_cli/platform.py +441 -0
  67. gr2/python_cli/pr.py +487 -0
  68. gr2/python_cli/project_review.py +314 -0
  69. gr2/python_cli/prune.py +365 -0
  70. gr2/python_cli/push.py +172 -0
  71. gr2/python_cli/review.py +462 -0
  72. gr2/python_cli/review_ephemeral.py +143 -0
  73. gr2/python_cli/review_run.py +621 -0
  74. gr2/python_cli/spec_apply.py +1285 -0
  75. gr2/python_cli/staging_cleanup.py +205 -0
  76. gr2/python_cli/syncops.py +920 -0
  77. gr2/python_cli/target.py +100 -0
  78. gr2/python_cli/workspace_snapshot.py +105 -0
  79. gr2/schemas/gr2-materialization-plan-v1.schema.json +191 -0
  80. gr2_overlay/__init__.py +37 -0
@@ -0,0 +1,274 @@
1
+ """Evidence-bound parent verification for gr2 pull-request merges.
2
+
3
+ The adapter returns an immutable commit OID from the merged PR record. This
4
+ module brings that exact object into the local DAG without writing FETCH_HEAD,
5
+ counts its parents, reports the result, and only then constructs a completed
6
+ merge record. No step re-resolves the base branch or reads process-global
7
+ mutable fetch state.
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ import subprocess
13
+ from collections.abc import Callable
14
+ from dataclasses import dataclass
15
+ from enum import StrEnum
16
+ from pathlib import Path
17
+ from typing import Any
18
+
19
+ from .platform import MergeMethod, MergeReceipt
20
+
21
+
22
+ @dataclass(frozen=True)
23
+ class MergeVerificationTarget:
24
+ """Explicit local evidence source for one host repository."""
25
+
26
+ repo_root: Path
27
+ remote: str
28
+
29
+
30
+ class ParentVerdictKind(StrEnum):
31
+ NOT_PERFORMED = "not_performed"
32
+ VERIFIED = "verified"
33
+ WRONG = "wrong"
34
+ UNVERIFIABLE = "unverifiable"
35
+ NOT_APPLICABLE = "not_applicable"
36
+
37
+
38
+ class ParentVerdict:
39
+ """Opaque parent-verification result.
40
+
41
+ The public constructor deliberately claims only NOT_PERFORMED. Verified,
42
+ wrong, unverifiable, and not-applicable results are minted by
43
+ `verify_parent_shape`, which has the evidence needed to earn them. Python
44
+ code in the same process can always forge an object with `object.__new__`.
45
+ The invariant covers supported construction routes, not hostile memory
46
+ mutation inside the verifier's process.
47
+ """
48
+
49
+ __slots__ = ("_commit_sha", "_detail", "_kind", "_parent_count")
50
+
51
+ def __init__(self) -> None:
52
+ object.__setattr__(self, "_kind", ParentVerdictKind.NOT_PERFORMED)
53
+ object.__setattr__(self, "_commit_sha", None)
54
+ object.__setattr__(self, "_parent_count", None)
55
+ object.__setattr__(self, "_detail", "parent verification was not performed")
56
+
57
+ def __setattr__(self, name: str, value: object) -> None:
58
+ raise AttributeError("ParentVerdict is immutable")
59
+
60
+ @classmethod
61
+ def _earned(
62
+ cls,
63
+ *,
64
+ kind: ParentVerdictKind,
65
+ commit_sha: str | None,
66
+ parent_count: int | None,
67
+ detail: str,
68
+ ) -> ParentVerdict:
69
+ value = object.__new__(cls)
70
+ object.__setattr__(value, "_kind", kind)
71
+ object.__setattr__(value, "_commit_sha", commit_sha)
72
+ object.__setattr__(value, "_parent_count", parent_count)
73
+ object.__setattr__(value, "_detail", detail)
74
+ return value
75
+
76
+ @property
77
+ def kind(self) -> ParentVerdictKind:
78
+ return self._kind
79
+
80
+ @property
81
+ def commit_sha(self) -> str | None:
82
+ return self._commit_sha
83
+
84
+ @property
85
+ def parent_count(self) -> int | None:
86
+ return self._parent_count
87
+
88
+ @property
89
+ def detail(self) -> str:
90
+ return self._detail
91
+
92
+ def as_dict(self) -> dict[str, object]:
93
+ return {
94
+ "kind": self.kind.value,
95
+ "commit_sha": self.commit_sha,
96
+ "parent_count": self.parent_count,
97
+ "detail": self.detail,
98
+ }
99
+
100
+
101
+ class _ReportedParentVerdict:
102
+ __slots__ = ("verdict",)
103
+
104
+ def __init__(self, verdict: ParentVerdict) -> None:
105
+ self.verdict = verdict
106
+
107
+
108
+ class CompletedMerge:
109
+ """A merge receipt whose parent verdict has been consumed.
110
+
111
+ Direct construction is unavailable. `consume_merge_receipt` verifies and
112
+ reports first, then mints this record from a private reported-verdict
113
+ carrier. A caller may retain the record, but cannot obtain one merely by
114
+ holding a raw receipt and choosing to skip the verdict.
115
+ """
116
+
117
+ __slots__ = ("_parent_verdict", "_receipt")
118
+
119
+ def __init__(self, *_args: object, **_kwargs: object) -> None:
120
+ raise TypeError("CompletedMerge is constructed by consume_merge_receipt")
121
+
122
+ def __setattr__(self, name: str, value: object) -> None:
123
+ raise AttributeError("CompletedMerge is immutable")
124
+
125
+ @classmethod
126
+ def _from_reported(
127
+ cls,
128
+ receipt: MergeReceipt,
129
+ reported: _ReportedParentVerdict,
130
+ ) -> CompletedMerge:
131
+ if not isinstance(reported, _ReportedParentVerdict):
132
+ raise TypeError("completion requires a reported parent verdict")
133
+ value = object.__new__(cls)
134
+ object.__setattr__(value, "_receipt", receipt)
135
+ object.__setattr__(value, "_parent_verdict", reported.verdict)
136
+ return value
137
+
138
+ @property
139
+ def receipt(self) -> MergeReceipt:
140
+ return self._receipt
141
+
142
+ @property
143
+ def parent_verdict(self) -> ParentVerdict:
144
+ return self._parent_verdict
145
+
146
+ def as_dict(self) -> dict[str, object]:
147
+ return {
148
+ "repo": self.receipt.observed.repo,
149
+ "pr_number": self.receipt.observed.number,
150
+ "url": self.receipt.observed.url,
151
+ "commit_sha": self.receipt.commit_sha,
152
+ "requested_method": self.receipt.requested_method.value,
153
+ "parent_verdict": self.parent_verdict.as_dict(),
154
+ }
155
+
156
+
157
+ def _run_git(repo_root: Path, *args: str) -> subprocess.CompletedProcess[str]:
158
+ return subprocess.run(
159
+ ["git", *args],
160
+ cwd=repo_root,
161
+ capture_output=True,
162
+ text=True,
163
+ check=False,
164
+ )
165
+
166
+
167
+ def verify_parent_shape(
168
+ *,
169
+ repo_root: Path,
170
+ receipt: MergeReceipt,
171
+ remote: str,
172
+ ) -> ParentVerdict:
173
+ """Verify the operation-returned commit in the local repository DAG."""
174
+
175
+ commit_sha = receipt.commit_sha
176
+ if commit_sha is None:
177
+ return ParentVerdict._earned(
178
+ kind=ParentVerdictKind.UNVERIFIABLE,
179
+ commit_sha=None,
180
+ parent_count=None,
181
+ detail="the host returned no immutable merge commit identity",
182
+ )
183
+
184
+ if receipt.requested_method in {MergeMethod.SQUASH, MergeMethod.REBASE}:
185
+ return ParentVerdict._earned(
186
+ kind=ParentVerdictKind.NOT_APPLICABLE,
187
+ commit_sha=commit_sha,
188
+ parent_count=None,
189
+ detail=f"{receipt.requested_method.value} merges are single-parent by design",
190
+ )
191
+
192
+ repo_root = Path(repo_root)
193
+ try:
194
+ fetch = _run_git(
195
+ repo_root,
196
+ "fetch",
197
+ "--no-write-fetch-head",
198
+ remote,
199
+ commit_sha,
200
+ )
201
+ except OSError as exc:
202
+ return _unverifiable(commit_sha, f"could not execute git fetch: {exc}")
203
+ if fetch.returncode != 0:
204
+ detail = fetch.stderr.strip() or fetch.stdout.strip() or "git fetch failed"
205
+ return _unverifiable(commit_sha, f"could not fetch receipt object: {detail}")
206
+
207
+ try:
208
+ opened = _run_git(repo_root, "rev-list", "--parents", "-n", "1", commit_sha)
209
+ except OSError as exc:
210
+ return _unverifiable(commit_sha, f"could not inspect receipt object: {exc}")
211
+ if opened.returncode != 0:
212
+ detail = opened.stderr.strip() or opened.stdout.strip() or "git rev-list failed"
213
+ return _unverifiable(commit_sha, f"could not inspect receipt object: {detail}")
214
+
215
+ rows = [line.split() for line in opened.stdout.splitlines() if line.strip()]
216
+ if len(rows) != 1 or not rows[0] or rows[0][0] != commit_sha:
217
+ return _unverifiable(
218
+ commit_sha,
219
+ "local DAG did not return the exact receipt commit",
220
+ )
221
+ parent_count = len(rows[0]) - 1
222
+ if parent_count == 2:
223
+ return ParentVerdict._earned(
224
+ kind=ParentVerdictKind.VERIFIED,
225
+ commit_sha=commit_sha,
226
+ parent_count=parent_count,
227
+ detail=f"merge commit {commit_sha} has two parents in the local DAG",
228
+ )
229
+ return ParentVerdict._earned(
230
+ kind=ParentVerdictKind.WRONG,
231
+ commit_sha=commit_sha,
232
+ parent_count=parent_count,
233
+ detail=(
234
+ f"merge commit {commit_sha} has {parent_count} parents in the local DAG; "
235
+ "expected 2"
236
+ ),
237
+ )
238
+
239
+
240
+ def _unverifiable(commit_sha: str, detail: str) -> ParentVerdict:
241
+ return ParentVerdict._earned(
242
+ kind=ParentVerdictKind.UNVERIFIABLE,
243
+ commit_sha=commit_sha,
244
+ parent_count=None,
245
+ detail=detail,
246
+ )
247
+
248
+
249
+ def report_parent_verdict(
250
+ verdict: ParentVerdict,
251
+ *,
252
+ report: Callable[[str], Any],
253
+ ) -> _ReportedParentVerdict:
254
+ if verdict.kind is ParentVerdictKind.NOT_PERFORMED:
255
+ raise TypeError("an unperformed parent verdict cannot complete a merge")
256
+ if verdict.kind in {ParentVerdictKind.WRONG, ParentVerdictKind.UNVERIFIABLE}:
257
+ report(f"merge parent verification {verdict.kind.value}: {verdict.detail}")
258
+ return _ReportedParentVerdict(verdict)
259
+
260
+
261
+ def consume_merge_receipt(
262
+ *,
263
+ repo_root: Path,
264
+ receipt: MergeReceipt,
265
+ remote: str,
266
+ report: Callable[[str], Any],
267
+ ) -> CompletedMerge:
268
+ verdict = verify_parent_shape(
269
+ repo_root=repo_root,
270
+ receipt=receipt,
271
+ remote=remote,
272
+ )
273
+ reported = report_parent_verdict(verdict, report=report)
274
+ return CompletedMerge._from_reported(receipt, reported)