@scolladon/tsgit 2.0.1 → 3.1.0

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 (154) hide show
  1. package/README.md +14 -2
  2. package/dist/cjs/adapters/browser/index.cjs +1 -2
  3. package/dist/cjs/adapters/memory/index.cjs +1 -2
  4. package/dist/cjs/adapters/node/index.cjs +1 -2
  5. package/dist/cjs/chunks/adapter-detect-DW9fsw9d.cjs +1 -0
  6. package/dist/cjs/chunks/browser-http-transport-DGwW5YL7.cjs +1 -0
  7. package/dist/cjs/chunks/context-BcoAzPuU.cjs +0 -1
  8. package/dist/cjs/chunks/error-CfLWDui_.cjs +1 -0
  9. package/dist/cjs/chunks/index-Cy44GVR6.cjs +1 -0
  10. package/dist/cjs/chunks/inflate-CmCtM4-w.cjs +1 -0
  11. package/dist/cjs/chunks/lru-cache-1OU7JhD8.cjs +0 -1
  12. package/dist/cjs/chunks/memory-http-transport-CGriODcQ.cjs +1 -0
  13. package/dist/cjs/chunks/node-ssh-transport-PFu3ijfp.cjs +1 -0
  14. package/dist/cjs/chunks/{progress-CxU62NC1.cjs → progress-D8Dqbftk.cjs} +1 -2
  15. package/dist/cjs/chunks/readable-stream-MTA6D0Zh.cjs +0 -1
  16. package/dist/cjs/chunks/repository-Ci-BBxk0.cjs +1 -0
  17. package/dist/cjs/chunks/write-sparse-checkout-C1dsHCAD.cjs +1 -0
  18. package/dist/cjs/commands/index.cjs +1 -2
  19. package/dist/cjs/index.browser.cjs +1 -2
  20. package/dist/cjs/index.cjs +1 -2
  21. package/dist/cjs/index.default.cjs +1 -2
  22. package/dist/cjs/index.node.cjs +1 -2
  23. package/dist/cjs/operators/index.cjs +0 -1
  24. package/dist/cjs/primitives/index.cjs +1 -2
  25. package/dist/cjs/transport/index.cjs +0 -1
  26. package/dist/esm/adapters/browser/index.js +1 -2
  27. package/dist/esm/adapters/memory/index.js +1 -2
  28. package/dist/esm/adapters/node/index.js +1 -2
  29. package/dist/esm/chunks/adapter-detect-BkCMnjrI.js +1 -0
  30. package/dist/esm/chunks/browser-http-transport-CSxAte5h.js +1 -0
  31. package/dist/esm/chunks/context-CumKOV7K.js +0 -1
  32. package/dist/esm/chunks/error-BotOd-nD.js +1 -0
  33. package/dist/esm/chunks/index-DsvINN8n.js +1 -0
  34. package/dist/esm/chunks/inflate-BCIXqeeE.js +1 -0
  35. package/dist/esm/chunks/lru-cache-Cy7C7Lx2.js +0 -1
  36. package/dist/esm/chunks/memory-http-transport-caqmMGR1.js +1 -0
  37. package/dist/esm/chunks/node-ssh-transport-BgSv2IhT.js +1 -0
  38. package/dist/esm/chunks/{progress-BZobfl7p.js → progress-B_AJnOHx.js} +1 -2
  39. package/dist/esm/chunks/readable-stream-CGuf8k1J.js +0 -1
  40. package/dist/esm/chunks/repository-DyxknzvE.js +1 -0
  41. package/dist/esm/chunks/write-sparse-checkout-BwHbNKNS.js +1 -0
  42. package/dist/esm/commands/index.js +1 -2
  43. package/dist/esm/index.browser.js +1 -2
  44. package/dist/esm/index.default.js +1 -2
  45. package/dist/esm/index.js +1 -2
  46. package/dist/esm/index.node.js +1 -2
  47. package/dist/esm/operators/index.js +0 -1
  48. package/dist/esm/primitives/index.js +1 -2
  49. package/dist/esm/transport/index.js +0 -1
  50. package/dist/types/adapters/browser/index.d.cts +5 -3
  51. package/dist/types/adapters/browser/index.d.ts +5 -3
  52. package/dist/types/adapters/memory/index.d.cts +31 -4
  53. package/dist/types/adapters/memory/index.d.ts +31 -4
  54. package/dist/types/adapters/node/index.d.cts +146 -40
  55. package/dist/types/adapters/node/index.d.ts +146 -40
  56. package/dist/types/chunks/{context-YDw6qicq.d.cts → context-CF1YF2S8.d.cts} +165 -6
  57. package/dist/types/chunks/{context-CCL0_F8R.d.ts → context-sIhhtk2u.d.ts} +165 -6
  58. package/dist/types/chunks/{http-transport--_NdQOiw.d.cts → http-transport-DirKfK2S.d.cts} +1 -1
  59. package/dist/types/chunks/{http-transport--_NdQOiw.d.ts → http-transport-DirKfK2S.d.ts} +1 -1
  60. package/dist/types/chunks/index-B5Dps3fg.d.ts +2468 -0
  61. package/dist/types/chunks/index-B_A8VLaf.d.ts +1221 -0
  62. package/dist/types/chunks/index-Dfh8cvEs.d.cts +2468 -0
  63. package/dist/types/chunks/index-Dqxddhav.d.cts +1221 -0
  64. package/dist/types/chunks/progress-BjAKfkam.d.ts +1217 -0
  65. package/dist/types/chunks/progress-Ldnfb8st.d.cts +1217 -0
  66. package/dist/types/chunks/reflog-entry-Cqh3QrPH.d.ts +697 -0
  67. package/dist/types/chunks/reflog-entry-Dy-O27Dd.d.cts +697 -0
  68. package/dist/types/chunks/{repository-FoS_Laoy.d.ts → repository-D8QBTkEz.d.ts} +58 -20
  69. package/dist/types/chunks/{repository-BeifCqp0.d.cts → repository-D9YrVhcH.d.cts} +58 -20
  70. package/dist/types/commands/index.d.cts +4 -1259
  71. package/dist/types/commands/index.d.ts +4 -1259
  72. package/dist/types/index.browser.d.cts +7 -8
  73. package/dist/types/index.browser.d.ts +7 -8
  74. package/dist/types/index.d.cts +61 -124
  75. package/dist/types/index.d.ts +61 -124
  76. package/dist/types/index.default.d.cts +7 -8
  77. package/dist/types/index.default.d.ts +7 -8
  78. package/dist/types/index.node.d.cts +7 -8
  79. package/dist/types/index.node.d.ts +7 -8
  80. package/dist/types/primitives/index.d.cts +4 -692
  81. package/dist/types/primitives/index.d.ts +4 -692
  82. package/dist/types/transport/index.d.cts +1 -1
  83. package/dist/types/transport/index.d.ts +1 -1
  84. package/package.json +94 -28
  85. package/dist/cjs/adapters/browser/index.cjs.map +0 -1
  86. package/dist/cjs/adapters/memory/index.cjs.map +0 -1
  87. package/dist/cjs/adapters/node/index.cjs.map +0 -1
  88. package/dist/cjs/chunks/adapter-detect-CD_LcgaH.cjs +0 -2
  89. package/dist/cjs/chunks/adapter-detect-CD_LcgaH.cjs.map +0 -1
  90. package/dist/cjs/chunks/browser-http-transport-CiMRqtDS.cjs +0 -2
  91. package/dist/cjs/chunks/browser-http-transport-CiMRqtDS.cjs.map +0 -1
  92. package/dist/cjs/chunks/context-BcoAzPuU.cjs.map +0 -1
  93. package/dist/cjs/chunks/error-CfjFO3x_.cjs +0 -2
  94. package/dist/cjs/chunks/error-CfjFO3x_.cjs.map +0 -1
  95. package/dist/cjs/chunks/index-BWCq_5BJ.cjs +0 -2
  96. package/dist/cjs/chunks/index-BWCq_5BJ.cjs.map +0 -1
  97. package/dist/cjs/chunks/lru-cache-1OU7JhD8.cjs.map +0 -1
  98. package/dist/cjs/chunks/memory-http-transport-BVL6VgB-.cjs +0 -2
  99. package/dist/cjs/chunks/memory-http-transport-BVL6VgB-.cjs.map +0 -1
  100. package/dist/cjs/chunks/node-http-transport-BvfVcf02.cjs +0 -2
  101. package/dist/cjs/chunks/node-http-transport-BvfVcf02.cjs.map +0 -1
  102. package/dist/cjs/chunks/progress-CxU62NC1.cjs.map +0 -1
  103. package/dist/cjs/chunks/readable-stream-MTA6D0Zh.cjs.map +0 -1
  104. package/dist/cjs/chunks/repository-BEg2zNtx.cjs +0 -2
  105. package/dist/cjs/chunks/repository-BEg2zNtx.cjs.map +0 -1
  106. package/dist/cjs/chunks/walk-submodules-D2Sp7JEB.cjs +0 -2
  107. package/dist/cjs/chunks/walk-submodules-D2Sp7JEB.cjs.map +0 -1
  108. package/dist/cjs/commands/index.cjs.map +0 -1
  109. package/dist/cjs/index.browser.cjs.map +0 -1
  110. package/dist/cjs/index.cjs.map +0 -1
  111. package/dist/cjs/index.default.cjs.map +0 -1
  112. package/dist/cjs/index.node.cjs.map +0 -1
  113. package/dist/cjs/operators/index.cjs.map +0 -1
  114. package/dist/cjs/primitives/index.cjs.map +0 -1
  115. package/dist/cjs/transport/index.cjs.map +0 -1
  116. package/dist/esm/adapters/browser/index.js.map +0 -1
  117. package/dist/esm/adapters/memory/index.js.map +0 -1
  118. package/dist/esm/adapters/node/index.js.map +0 -1
  119. package/dist/esm/chunks/adapter-detect-DkZhhUhd.js +0 -2
  120. package/dist/esm/chunks/adapter-detect-DkZhhUhd.js.map +0 -1
  121. package/dist/esm/chunks/browser-http-transport-4rJkHcQu.js +0 -2
  122. package/dist/esm/chunks/browser-http-transport-4rJkHcQu.js.map +0 -1
  123. package/dist/esm/chunks/context-CumKOV7K.js.map +0 -1
  124. package/dist/esm/chunks/error-Dc-SRSJK.js +0 -2
  125. package/dist/esm/chunks/error-Dc-SRSJK.js.map +0 -1
  126. package/dist/esm/chunks/index-jH0UMhh-.js +0 -2
  127. package/dist/esm/chunks/index-jH0UMhh-.js.map +0 -1
  128. package/dist/esm/chunks/lru-cache-Cy7C7Lx2.js.map +0 -1
  129. package/dist/esm/chunks/memory-http-transport-CA1WxWBp.js +0 -2
  130. package/dist/esm/chunks/memory-http-transport-CA1WxWBp.js.map +0 -1
  131. package/dist/esm/chunks/node-http-transport-DPa2lK3T.js +0 -2
  132. package/dist/esm/chunks/node-http-transport-DPa2lK3T.js.map +0 -1
  133. package/dist/esm/chunks/progress-BZobfl7p.js.map +0 -1
  134. package/dist/esm/chunks/readable-stream-CGuf8k1J.js.map +0 -1
  135. package/dist/esm/chunks/repository-DF6ePd1x.js +0 -2
  136. package/dist/esm/chunks/repository-DF6ePd1x.js.map +0 -1
  137. package/dist/esm/chunks/walk-submodules-Dq9oGwP8.js +0 -2
  138. package/dist/esm/chunks/walk-submodules-Dq9oGwP8.js.map +0 -1
  139. package/dist/esm/commands/index.js.map +0 -1
  140. package/dist/esm/index.browser.js.map +0 -1
  141. package/dist/esm/index.default.js.map +0 -1
  142. package/dist/esm/index.js.map +0 -1
  143. package/dist/esm/index.node.js.map +0 -1
  144. package/dist/esm/operators/index.js.map +0 -1
  145. package/dist/esm/primitives/index.js.map +0 -1
  146. package/dist/esm/transport/index.js.map +0 -1
  147. package/dist/types/chunks/index-entry-DtEbVpOG.d.cts +0 -47
  148. package/dist/types/chunks/index-entry-UD4dvtKh.d.ts +0 -47
  149. package/dist/types/chunks/progress-7KKiXXfX.d.ts +0 -405
  150. package/dist/types/chunks/progress-By8yFaUE.d.cts +0 -405
  151. package/dist/types/chunks/reflog-entry-BbNnXCTC.d.cts +0 -368
  152. package/dist/types/chunks/reflog-entry-CSzjnZd4.d.ts +0 -368
  153. package/dist/types/chunks/write-tree-C3oNxOlX.d.cts +0 -196
  154. package/dist/types/chunks/write-tree-DRI-LzSr.d.ts +0 -196
@@ -0,0 +1,1221 @@
1
+ import { p as FileMode, aO as IndexEntry, G as GitIndex, B as BisectMidpoint, c as CatFileBatchOptions, C as CatFileBatchEntry, aN as ConfigScope, aP as ConfigKey, g as CreateCommitInput, h as CreateTagInput, n as DiffTreesInput, o as DiffTreesOptions, a3 as StatTreeDiff, a8 as TreeDiff, a7 as Tree, q as FlatTree, aR as TreeEntry, V as ReadObjectOptions, b as Blob, s as GitObject, a as AuthorIdentity, aQ as ReflogEntry, Y as ResolveRefOptions, aa as UpdateRefOptions, ac as WalkCommitsOptions, d as Commit, ab as WalkCommitsByDateOptions, ad as WalkSubmodulesOptions, a4 as SubmoduleEntry, af as WalkTreeOptions, ae as WalkTreeEntry, ah as WalkWorkingTreeOptions, ag as WalkWorkingTreeEntry } from './reflog-entry-Dy-O27Dd.cjs';
2
+ import { F as FilePath, c as Context, O as ObjectId, R as RefName, j as HookName } from './context-CF1YF2S8.cjs';
3
+
4
+ /**
5
+ * The four states a git attribute can resolve to (`gitattributes(5)`):
6
+ *
7
+ * - `true` — set (`name`)
8
+ * - `false` — unset (`-name`)
9
+ * - `'unspecified'` — explicitly unspecified (`!name`)
10
+ * - `{ set: value }`— set to a string value (`name=value`)
11
+ */
12
+ type AttributeValue = true | false | 'unspecified' | {
13
+ readonly set: string;
14
+ };
15
+
16
+ /** A compiled glob — `test` reports whether a path matches the pattern. */
17
+ interface GlobMatcher {
18
+ test(path: string): boolean;
19
+ }
20
+
21
+ /** A single `.gitattributes` pattern line and the attributes it assigns. */
22
+ interface AttributeRule {
23
+ /** Pattern as written (post-unquote, pre-anchor-strip) — the round-trip source form. */
24
+ readonly pattern: string;
25
+ /** True when the pattern is anchored to the file's directory (leading or interior `/`). */
26
+ readonly anchored: boolean;
27
+ /** True when the pattern ends with `/` (directory-only). */
28
+ readonly directoryOnly: boolean;
29
+ /** 1-based source line number (tracks comment / blank gaps). */
30
+ readonly lineNumber: number;
31
+ /** Compiled glob, matched against a path relative to the source's basedir. */
32
+ readonly compiled: GlobMatcher;
33
+ /** Attribute assignments, last-token-wins within the line. */
34
+ readonly attributes: ReadonlyMap<string, AttributeValue>;
35
+ }
36
+
37
+ /** A macro name → the attributes it expands to. */
38
+ type MacroRegistry = ReadonlyMap<string, ReadonlyMap<string, AttributeValue>>;
39
+
40
+ /**
41
+ * One attributes file's rules, tagged with the directory it lives in. Patterns
42
+ * are matched against a path made relative to `basedir` (`''` is the repo root).
43
+ */
44
+ interface AttributeSource {
45
+ readonly basedir: string;
46
+ readonly rules: ReadonlyArray<AttributeRule>;
47
+ }
48
+
49
+ /** Resolves the precedence-ordered attribute sources + macro registry for a path. */
50
+ interface AttributeProvider {
51
+ readonly sourcesForPath: (path: FilePath) => Promise<{
52
+ readonly sources: ReadonlyArray<AttributeSource>;
53
+ readonly macros: MacroRegistry;
54
+ }>;
55
+ }
56
+
57
+ /** `true` ⇒ the path is in the sparse set (materialise it). */
58
+ type SparseMatcher = (path: FilePath) => boolean;
59
+
60
+ type WorkingTreeComparison = 'absent' | 'unchanged' | 'modified' | 'type-changed' | 'mode-changed';
61
+ /**
62
+ * A working-tree comparison plus the working file's mode (`mW`). `worktreeMode`
63
+ * is what `git status --porcelain=v2` reports for the worktree side; it is
64
+ * present whenever a working file exists and omitted only when the file is
65
+ * `absent`. There is no working blob oid — the file need not be in the object
66
+ * store, so git itself prints no `hW`.
67
+ */
68
+ interface WorkingTreeDelta {
69
+ readonly status: WorkingTreeComparison;
70
+ readonly worktreeMode?: FileMode;
71
+ }
72
+ declare const compareWorkingTreeDelta: (ctx: Context, entry: IndexEntry, provider?: AttributeProvider) => Promise<WorkingTreeDelta>;
73
+ /**
74
+ * Enum projection over {@link compareWorkingTreeDelta} — the dirtiness verdict
75
+ * without the mode. Consumed by the local-modification valve (`rm`, `stash`,
76
+ * clean-work-tree, apply-merge) where only the status matters.
77
+ */
78
+ declare const compareWorkingTreeEntry: (ctx: Context, entry: IndexEntry, provider?: AttributeProvider) => Promise<WorkingTreeComparison>;
79
+
80
+ /**
81
+ * Pure helper that diffs a current GitIndex against a target tree's flat
82
+ * entry list and emits an ordered ChangesetEntry list. No FS, no ctx; the
83
+ * impure write side lives in `apply-changeset.ts`.
84
+ *
85
+ * Stage-0 entries only — unmerged stages are invisible to checkout (Phase
86
+ * 13.1 design step 5).
87
+ */
88
+
89
+ interface ChangesetEntry {
90
+ readonly kind: 'add' | 'update' | 'delete' | 'noop';
91
+ readonly path: FilePath;
92
+ readonly mode: FileMode;
93
+ readonly id: ObjectId | undefined;
94
+ readonly previousId: ObjectId | undefined;
95
+ readonly previousMode: FileMode | undefined;
96
+ }
97
+ interface ChangesetStats {
98
+ readonly add: number;
99
+ readonly update: number;
100
+ readonly delete: number;
101
+ readonly noop: number;
102
+ }
103
+ interface Changeset {
104
+ readonly entries: ReadonlyArray<ChangesetEntry>;
105
+ readonly stats: ChangesetStats;
106
+ }
107
+ interface TargetEntry {
108
+ readonly path: FilePath;
109
+ readonly id: ObjectId;
110
+ readonly mode: FileMode;
111
+ }
112
+ declare const computeChangeset: (currentIndex: GitIndex, targetTree: ReadonlyArray<TargetEntry>) => Changeset;
113
+
114
+ interface ApplyChangesetOpts {
115
+ readonly changeset: Changeset;
116
+ readonly force: boolean;
117
+ readonly workdir: string;
118
+ }
119
+ interface ApplyChangesetResult {
120
+ readonly writtenEntries: ReadonlyArray<IndexEntry>;
121
+ readonly written: number;
122
+ readonly deleted: number;
123
+ }
124
+ /**
125
+ * `true` when a working-tree file exists at `absPath` but its blob content
126
+ * hash differs from `expectedId`. An absent file is not dirty. Shared by
127
+ * `applySparseCheckout`'s narrowing pre-scan (design §9).
128
+ */
129
+ declare const isWorkingTreeDirty: (ctx: Context, absPath: string, expectedId: string) => Promise<boolean>;
130
+ declare const applyChangeset: (ctx: Context, opts: ApplyChangesetOpts) => Promise<ApplyChangesetResult>;
131
+
132
+ /**
133
+ * Compute the bisect midpoint: the commit that halves the candidate set
134
+ * (commits reachable from `bad` but not from any `good`).
135
+ *
136
+ * Returns `undefined` when the candidate set is empty (the bug does not
137
+ * exist within the `good`→`bad` range, or `bad` is already `good`-reachable).
138
+ *
139
+ * Mirrors `git rev-list --bisect-vars` semantics; see `BisectMidpoint`.
140
+ */
141
+ declare const bisectMidpoint: (ctx: Context, good: ReadonlyArray<ObjectId>, bad: ObjectId) => Promise<BisectMidpoint | undefined>;
142
+
143
+ /**
144
+ * Project a target tree onto a fresh stage-0 IndexEntry list, preserving
145
+ * stat-cache fields from the prior index where the path's `id` AND `mode`
146
+ * both match (the "stat-cache donor" strategy).
147
+ *
148
+ * Pure with respect to the working tree: this primitive never calls
149
+ * `fs.lstat`, `fs.read`, or any working-tree-side API. It only reads git
150
+ * objects via `walkTree` → `readObject` for nested trees.
151
+ *
152
+ * Used by `reset --mixed` to rebuild the index from a target
153
+ * commit's tree. Will be re-used by `reset --hard` composed
154
+ * with `materializeTree` to also write the working tree.
155
+ *
156
+ * ## Preconditions
157
+ *
158
+ * `currentIndex` MUST be read under the same `acquireIndexLock` that will
159
+ * later commit the result. Reading the index BEFORE the lock is acquired
160
+ * lets a concurrent writer mutate it between the donor-map build and the
161
+ * commit, producing a result that reflects neither the pre-reset nor the
162
+ * post-reset state. See `reset.ts:rebuildIndexFromCommit` for the
163
+ * canonical pattern: acquire → read → build → commit → release-in-finally.
164
+ */
165
+
166
+ interface BuildIndexFromTreeOpts {
167
+ readonly targetTree: ObjectId;
168
+ readonly currentIndex: GitIndex;
169
+ /**
170
+ * Sparse-checkout filter. When supplied, an excluded path is rebuilt as a
171
+ * zero-stat skip-worktree entry and an in-pattern path has any stale
172
+ * skip-worktree bit cleared. `undefined` ⇒ sparse inactive — the rebuilt
173
+ * index is byte-identical to the non-sparse behaviour.
174
+ */
175
+ readonly sparse?: SparseMatcher;
176
+ }
177
+ declare const buildIndexFromTree: (ctx: Context, opts: BuildIndexFromTreeOpts) => Promise<ReadonlyArray<IndexEntry>>;
178
+
179
+ interface BuildPackInput {
180
+ readonly oids: ReadonlyArray<ObjectId>;
181
+ }
182
+ interface BuildPackResult {
183
+ readonly bytes: Uint8Array;
184
+ /** Hex SHA of the pack body, also the trailer (last 20 bytes). */
185
+ readonly sha: string;
186
+ readonly objectCount: number;
187
+ }
188
+ declare const buildPack: (ctx: Context, input: BuildPackInput) => Promise<BuildPackResult>;
189
+
190
+ declare function catFileBatch(ctx: Context, ids: AsyncIterable<ObjectId> | Iterable<ObjectId>, options?: CatFileBatchOptions): AsyncIterable<CatFileBatchEntry>;
191
+
192
+ /** `push.default` mode; `tracking` is a deprecated alias canonicalized to `upstream` at parse time. */
193
+ type PushDefaultMode = 'nothing' | 'current' | 'upstream' | 'simple' | 'matching';
194
+ /**
195
+ * Subset of `.git/config` that v1 commands consume. Only fields actually used by
196
+ * commands are typed — the parser ignores everything else (lenient, like git itself).
197
+ */
198
+ interface ParsedConfig {
199
+ readonly core?: {
200
+ readonly bare?: boolean;
201
+ readonly excludesFile?: string;
202
+ readonly attributesFile?: string;
203
+ readonly logAllRefUpdates?: boolean | 'always';
204
+ readonly hooksPath?: string;
205
+ /** `core.notesRef` — default notes ref when neither explicit arg nor `GIT_NOTES_REF` is set. */
206
+ readonly notesRef?: string;
207
+ readonly sparseCheckout?: boolean;
208
+ readonly sparseCheckoutCone?: boolean;
209
+ readonly looseCompression?: number;
210
+ /** `core.sshCommand` — shell string resolved by `resolveSshCommand` ahead of `GIT_SSH`. */
211
+ readonly sshCommand?: string;
212
+ };
213
+ readonly user?: {
214
+ readonly name?: string;
215
+ readonly email?: string;
216
+ readonly signingKey?: string;
217
+ };
218
+ readonly remote?: ReadonlyMap<string, {
219
+ readonly url?: string;
220
+ /** `remote.<name>.pushurl` — push-only URL; `push` reads `pushUrl ?? url`. */
221
+ readonly pushUrl?: string;
222
+ readonly fetch?: ReadonlyArray<string>;
223
+ /** `remote.<name>.promisor` — true when this is a partial-clone promisor remote. */
224
+ readonly promisor?: boolean;
225
+ /** `remote.<name>.partialclonefilter` — the canonical filter spec applied at clone. */
226
+ readonly partialCloneFilter?: string;
227
+ }>;
228
+ /** `remote.pushDefault` — subsectionless `[remote]` only; per-remote `[remote "x"] pushDefault` is not read. */
229
+ readonly remotePushDefault?: string;
230
+ readonly branch?: ReadonlyMap<string, {
231
+ readonly remote?: string;
232
+ readonly merge?: string;
233
+ /** `branch.<name>.pushRemote` — overrides the push-remote for this branch. */
234
+ readonly pushRemote?: string;
235
+ }>;
236
+ /** `[submodule "<name>"]` — the registered (initialised) submodules. */
237
+ readonly submodule?: ReadonlyMap<string, {
238
+ readonly url?: string;
239
+ readonly active?: boolean;
240
+ readonly update?: string;
241
+ }>;
242
+ /** `[merge "<driver>"]` — configured custom merge drivers. */
243
+ readonly merge?: ReadonlyMap<string, {
244
+ readonly name?: string;
245
+ readonly driver?: string;
246
+ readonly recursive?: string;
247
+ }>;
248
+ /** `[diff "<name>"]` configured diff/textconv drivers. */
249
+ readonly diff?: ReadonlyMap<string, {
250
+ readonly textconv?: string;
251
+ readonly cachetextconv?: boolean;
252
+ }>;
253
+ /** `[filter "<name>"]` configured clean/smudge filter drivers. */
254
+ readonly filter?: ReadonlyMap<string, {
255
+ readonly clean?: string;
256
+ readonly smudge?: string;
257
+ readonly process?: string;
258
+ readonly required?: boolean;
259
+ }>;
260
+ /** `[extensions]` — `partialClone` names the promisor remote of a partial clone. */
261
+ readonly extensions?: {
262
+ readonly partialClone?: string;
263
+ };
264
+ /** `commit.gpgSign` — sign commits by default when true. */
265
+ readonly commit?: {
266
+ readonly gpgSign?: boolean;
267
+ };
268
+ /** `tag.gpgSign` — sign annotated tags by default when true. */
269
+ readonly tag?: {
270
+ readonly gpgSign?: boolean;
271
+ };
272
+ readonly push?: {
273
+ /** `push.gpgSign` — sign push certificates: `true`/`false`, or `if-asked` (server-requested). */
274
+ readonly gpgSign?: 'true' | 'false' | 'if-asked';
275
+ /** `push.default` — canonicalized push remote-selection mode (`tracking` maps to `upstream`). */
276
+ readonly default?: PushDefaultMode;
277
+ };
278
+ /** `[gpg]` — signing backend selection and the external program(s) invoked to sign/verify. */
279
+ readonly gpg?: {
280
+ readonly format?: 'openpgp' | 'ssh' | 'x509';
281
+ readonly program?: string;
282
+ /** `gpg.ssh.program` — the `ssh-keygen`-compatible binary used for `gpg.format = ssh`. */
283
+ readonly ssh?: {
284
+ readonly program?: string;
285
+ };
286
+ };
287
+ }
288
+ /**
289
+ * Read and cache `${gitDir}/config`. Missing → empty config (not an error).
290
+ *
291
+ * The cache is keyed on `Context` identity; a new context (e.g., after a write
292
+ * that re-creates the repo) gets a fresh read. Concurrent calls share the same
293
+ * in-flight promise (per-context single-flight).
294
+ */
295
+ declare const readConfig: (ctx: Context) => Promise<ParsedConfig>;
296
+ /**
297
+ * Drop the cached `readConfig` entry for a single `Context`. The production
298
+ * invalidator: a config write (`updateCoreConfig`) calls this so a subsequent
299
+ * `readConfig` on the same context re-reads the file instead of serving the
300
+ * stale parse.
301
+ */
302
+ declare const invalidateConfigCache: (ctx: Context) => void;
303
+ interface ValuelessEntry {
304
+ readonly key: string;
305
+ readonly source: string;
306
+ readonly line: number;
307
+ }
308
+ /**
309
+ * Valueless-entry detection: scan the repo-local config and return the FIRST
310
+ * valueless (`value === null`) entry, by config-file line, whose key
311
+ * (case-insensitive) is one of `keys` and which sits under `[<section> "<subsection>"]`
312
+ * (subsection `undefined` ⇒ the section with no subsection). Returns the fully-qualified
313
+ * key, the absolute config path, and the 1-based line, or `undefined` when no such
314
+ * entry exists. Walks the cached token stream, so an eager caller (the `[user]`
315
+ * identity pre-flight) pays only an in-memory scan, not a second read.
316
+ */
317
+ declare const findFirstValuelessEntry: (ctx: Context, section: string, subsection: string | undefined, keys: ReadonlyArray<string>) => Promise<ValuelessEntry | undefined>;
318
+ /**
319
+ * One `[section "subsection"]` block of a git-config-format INI file: the
320
+ * section name, an optional quoted subsection, and its key/value entries.
321
+ * Exported so `.gitmodules` parsing — byte-identical grammar — reuses one
322
+ * tokenizer (ADR-086).
323
+ *
324
+ * Entry `value`:
325
+ * - `string` — key present with `=` (possibly `''` for `key =`)
326
+ * - `null` — key present with no `=` (git's internal NULL; boolean-true)
327
+ * - `undefined` is never used here; the absent-key state lives one layer up
328
+ */
329
+ interface IniSection {
330
+ readonly section: string;
331
+ readonly subsection: string | undefined;
332
+ readonly entries: ReadonlyArray<{
333
+ readonly key: string;
334
+ readonly value: string | null;
335
+ }>;
336
+ }
337
+ /**
338
+ * Tokenize git-config-format INI text into its sections. Lenient on structure,
339
+ * like git is with unknown keys: orphan key/values and malformed headers are
340
+ * skipped. Values follow git's full quoted-value grammar — quotes stripped,
341
+ * `\n`/`\t`/`\b`/`\"`/`\\` decoded, backslash-newline continuations, unquoted
342
+ * `#`/`;` starting comments — and a malformed value (unknown escape, unclosed
343
+ * quote) throws `CONFIG_PARSE_ERROR` with its 1-based physical line and the
344
+ * optional `source` label, mirroring git's `bad config line N in file F`
345
+ * refusal. A malformed quoted-subsection header (e.g. `[s"a"]`, `[s "a" x]`,
346
+ * unclosed quote) also throws `CONFIG_PARSE_ERROR` with `partialSectionName`.
347
+ *
348
+ * Keys before the first header are recorded under an implicit orphan section
349
+ * (`section: ''`, `subsection: undefined`), so they surface on the token stream
350
+ * and porcelain `--list`, mirroring git, which dumps them with no section prefix
351
+ * but refuses to address them. The orphan section is emitted only when it
352
+ * gathered an entry — a header-only file yields no leading empty section.
353
+ *
354
+ * A line with no `=` records a valueless key (`value: null`); the key grammar
355
+ * (alpha-first, `[a-zA-Z0-9-]`, then space/TAB and `=`-or-EOL) refuses anything
356
+ * else — `bad!key`, `9key`, a mid-key `#`/`;` — with `CONFIG_PARSE_ERROR`.
357
+ */
358
+ declare const parseIniSections: (text: string, source?: string) => ReadonlyArray<IniSection>;
359
+
360
+ /**
361
+ * Drop the per-scope sections cache for a single `Context`. Called by
362
+ * `invalidateConfigCache` in `config-read.ts` so writers can invalidate both
363
+ * caches atomically.
364
+ */
365
+ declare const invalidateScopedConfigCache: (ctx: Context) => void;
366
+ /**
367
+ * Read the raw IniSection array for a single config scope, or a scope-tagged
368
+ * flat array merged in precedence order (`system → global → local → worktree`)
369
+ * when `scope` is omitted.
370
+ *
371
+ * Per-Context, per-scope cached: a second call with the same `(ctx, scope)`
372
+ * shares the in-flight promise of the first. `invalidateConfigCache(ctx)` (from
373
+ * `config-read.ts`) drops the cached entries here too.
374
+ *
375
+ * In the merged-read path (`scope` omitted), scopes that are unavailable on
376
+ * the current adapter (`CONFIG_SCOPE_NOT_AVAILABLE`, `CONFIG_SYSTEM_PATH_UNRESOLVED`)
377
+ * are silently skipped — the caller gets whatever scopes the adapter can
378
+ * actually surface. Single-scope calls raise instead, so the caller can react
379
+ * to a missing scope explicitly.
380
+ */
381
+ declare const readConfigSections: ({ ctx, scope, }: {
382
+ readonly ctx: Context;
383
+ readonly scope?: ConfigScope;
384
+ }) => Promise<ReadonlyArray<{
385
+ readonly scope: ConfigScope;
386
+ readonly section: IniSection;
387
+ }>>;
388
+ /**
389
+ * Look up a single value for a fully-qualified key (`section.name` or
390
+ * `section.subsection.name`). Behaviour:
391
+ *
392
+ * - When `scope` is provided, reads only that scope. If the key has more than
393
+ * one match in that scope, throws `CONFIG_MULTIPLE_VALUES` (carries `scope`).
394
+ * - When `scope` is omitted, merges across the four scopes. Same multi-value
395
+ * throw if more than one entry matches anywhere across the merged view
396
+ * (without the `scope` discriminator).
397
+ * - Absent key: returns `{ key, value: undefined }`; never throws.
398
+ * - Valueless key (no `=` in the file): returns `{ key, value: null, scope }`.
399
+ * `null` (present, no `=`) is distinct from `undefined` (absent) and from
400
+ * `''` (empty string after `key =`).
401
+ *
402
+ * Branding: the returned `key` is the caller's input cast to `ConfigKey`;
403
+ * `parseConfigKey` validates the string before this cast, so the brand is
404
+ * load-bearing only at the type level.
405
+ */
406
+ declare const getConfigValue: ({ ctx, key, scope, }: {
407
+ readonly ctx: Context;
408
+ readonly key: string;
409
+ readonly scope?: ConfigScope;
410
+ }) => Promise<{
411
+ readonly key: ConfigKey;
412
+ readonly value: string | null;
413
+ readonly scope: ConfigScope;
414
+ } | {
415
+ readonly key: ConfigKey;
416
+ readonly value: undefined;
417
+ }>;
418
+ /**
419
+ * Look up every value for a key. Returns matches in scope-precedence order
420
+ * (and physical-file order within each scope). Empty array when the key is
421
+ * absent. Never throws on multi-value.
422
+ *
423
+ * Each `value` carries `string | null`: `null` means the entry was present
424
+ * with no `=` (git's internal NULL); `undefined` is never in the array.
425
+ */
426
+ declare const getAllConfigValues: ({ ctx, key, scope, }: {
427
+ readonly ctx: Context;
428
+ readonly key: string;
429
+ readonly scope?: ConfigScope;
430
+ }) => Promise<{
431
+ readonly key: ConfigKey;
432
+ readonly values: ReadonlyArray<{
433
+ readonly value: string | null;
434
+ readonly scope: ConfigScope;
435
+ }>;
436
+ }>;
437
+
438
+ declare function createCommit(ctx: Context, input: CreateCommitInput): Promise<ObjectId>;
439
+
440
+ /**
441
+ * Build and write an annotated tag object (`object`/`type`/`tag`/`tagger` +
442
+ * message). Tag-name validity (non-empty, no `\n`/`\0`) is enforced by
443
+ * `serializeTagContent` during `writeObject`; the tagger identity is
444
+ * roundtripped through `serializeIdentity` here first (rejects control
445
+ * characters per Step 0(a)), matching `createCommit`'s author/committer
446
+ * validation.
447
+ */
448
+ declare function createTag(ctx: Context, input: CreateTagInput): Promise<ObjectId>;
449
+
450
+ declare function diffTrees(ctx: Context, a: DiffTreesInput, b: DiffTreesInput, options: DiffTreesOptions & {
451
+ withStat: true;
452
+ }): Promise<StatTreeDiff>;
453
+ declare function diffTrees(ctx: Context, a: DiffTreesInput, b: DiffTreesInput, options?: DiffTreesOptions): Promise<TreeDiff>;
454
+
455
+ interface EnumerateObjectsOptions {
456
+ /** Include objects from pack files (default: true). */
457
+ readonly includePacks?: boolean;
458
+ }
459
+ declare function enumerateObjects(ctx: Context, opts?: EnumerateObjectsOptions): Promise<ReadonlyArray<ObjectId>>;
460
+
461
+ /**
462
+ * push closure walker.
463
+ *
464
+ * Enumerates every object the remote does NOT have so the caller can
465
+ * stream them into `buildPack`. Walks commits from `wants` with `haves`
466
+ * as the boundary (canonical `until` semantics — the haves themselves
467
+ * are never yielded), then walks each commit's tree for the trees and
468
+ * blobs they reference. Duplicates are removed across the whole stream
469
+ * via a single `Set<ObjectId>`.
470
+ *
471
+ * Annotated tags pushed via a refspec must appear in the stream too —
472
+ * `readObject` is called on each want; if the result is a Tag, the tag
473
+ * oid is yielded and the chain is followed (tag → tag →... → commit)
474
+ * before handing the resolved commit oid to `walkCommits`.
475
+ *
476
+ * Gitlink entries in a tree (submodules) are NOT included: the oid
477
+ * names a commit that lives in another repository, which we cannot
478
+ * resolve locally and have no business including in this push's pack.
479
+ */
480
+
481
+ interface EnumeratePushObjectsInput {
482
+ /**
483
+ * Object ids the caller wants on the remote. Each MUST resolve to a
484
+ * commit or an annotated tag (tags are unwrapped to commits before the
485
+ * commit walk).
486
+ */
487
+ readonly wants: ReadonlyArray<ObjectId>;
488
+ /** Object ids the remote already has (server's advertised ref tips). */
489
+ readonly haves: ReadonlyArray<ObjectId>;
490
+ /** Hard cap on objects emitted. Defaults to MAX_PUSH_OBJECTS. */
491
+ readonly maxObjects?: number;
492
+ }
493
+ declare function enumeratePushObjects(ctx: Context, input: EnumeratePushObjectsInput): AsyncIterable<ObjectId>;
494
+
495
+ /**
496
+ * Enumerate every current ref: `HEAD`, loose refs under `.git/refs/**`, and
497
+ * packed-refs entries — deduplicated. Used by `reflog expire` to seed the
498
+ * reachable-commit walk; not on any hot path.
499
+ */
500
+
501
+ declare function enumerateRefs(ctx: Context): Promise<ReadonlyArray<RefName>>;
502
+
503
+ interface FetchPackInput {
504
+ /** Advertised refs the caller wants. MUST be non-empty (server-side requirement). */
505
+ readonly wants: ReadonlyArray<ObjectId>;
506
+ /** Objects the caller already has (negotiation). Empty for clone, populated for fetch. */
507
+ readonly haves: ReadonlyArray<ObjectId>;
508
+ /** Negotiated capabilities (intersection of advertised + supported). */
509
+ readonly capabilities: ReadonlyArray<string>;
510
+ /** Progress op label — clone uses 'clone:write-objects', fetch uses 'fetch:write-objects'. */
511
+ readonly progressOp: string;
512
+ /**
513
+ * Shallow clone depth. When set, sends `deepen N` and consumes the
514
+ * accompanying `shallow <oid>` / `unshallow <oid>` response block.
515
+ *
516
+ */
517
+ readonly depth?: number;
518
+ /**
519
+ * Partial-clone object filter — a canonical filter spec. When set, a
520
+ * `filter` line is emitted; the caller must have negotiated the `filter`
521
+ * capability.
522
+ */
523
+ readonly filter?: string;
524
+ /**
525
+ * When true, write an empty `pack-<sha>.promisor` sentinel beside the pack
526
+ * so the objects it references but omits are treated as promised.
527
+ */
528
+ readonly promisor?: boolean;
529
+ }
530
+ interface FetchPackResult {
531
+ readonly packPath: string;
532
+ readonly idxPath: string;
533
+ readonly objectCount: number;
534
+ /** Hex-encoded SHA of the pack trailer; also the on-disk filename stem. */
535
+ readonly packSha: string;
536
+ /** Commits the server advertised as new shallow boundaries (empty when depth is unset). */
537
+ readonly shallow: ReadonlyArray<ObjectId>;
538
+ /** Commits the server advertised as no-longer-shallow (empty when depth is unset). */
539
+ readonly unshallow: ReadonlyArray<ObjectId>;
540
+ }
541
+ interface PackDownload {
542
+ readonly packBytes: Uint8Array;
543
+ readonly shallow: ReadonlyArray<ObjectId>;
544
+ readonly unshallow: ReadonlyArray<ObjectId>;
545
+ }
546
+ /**
547
+ * Negotiates and drains the pack body for one `fetchPack` call. Callers bind
548
+ * the wire version and the transport session into this closure — `fetchPack`
549
+ * itself stays version-agnostic, matching every other caller of the shared
550
+ * `PackDownload` shape.
551
+ */
552
+ type NegotiatePackBytes = (ctx: Context, input: FetchPackInput) => Promise<PackDownload>;
553
+ declare const fetchPack: (ctx: Context, negotiatePackBytes: NegotiatePackBytes, input: FetchPackInput) => Promise<FetchPackResult>;
554
+
555
+ /**
556
+ * Flatten a nested `Tree` into the `FlatTree` shape that the `mergeTrees`
557
+ * domain primitive (and the recursive tree-diff) consume.
558
+ *
559
+ * Bridges `walkTree`'s iterator into the `FlatTree` Map of
560
+ * `path → { id, mode }`. Accepts either an oid or an already-resolved `Tree`
561
+ * object (the recursive diff passes the latter to avoid a redundant root read);
562
+ * `walkTree` resolves both. Consumed by `merge.ts`'s clean-merge tree walk,
563
+ * `rm`'s HEAD-vs-index staged-change check, and the `diffTrees` recursive path,
564
+ * so it is exported from the primitives barrel.
565
+ *
566
+ * Pure with respect to the working tree — only reads git objects via
567
+ * `walkTree`.
568
+ */
569
+
570
+ declare const flattenTree: (ctx: Context, treeIdOrObject: ObjectId | Tree) => Promise<FlatTree>;
571
+
572
+ /**
573
+ * Local-only object-presence probe. A CQS query: unlike `readObject`, it never
574
+ * inflates, never verifies, and never consults `ctx.promisor` — a promised
575
+ * (not-yet-fetched) object in a partial repo answers `false` here, exactly as
576
+ * it would on disk. Callers that need the object's bytes still go through
577
+ * `readObject`.
578
+ */
579
+
580
+ declare const hasObject: (ctx: Context, id: ObjectId) => Promise<boolean>;
581
+
582
+ interface HashBlobOptions {
583
+ /** Persist the loose object under `.git/objects/<2>/<38>`. Default `false`. */
584
+ readonly write?: boolean;
585
+ }
586
+ declare const hashBlob: (ctx: Context, content: Uint8Array, opts?: HashBlobOptions) => Promise<ObjectId>;
587
+
588
+ interface IsIgnoredQuery {
589
+ readonly path: FilePath;
590
+ /** Match directory rules (`build/`). Defaults to `false`. */
591
+ readonly isDirectory?: boolean;
592
+ }
593
+ interface IsIgnoredMatchSource {
594
+ readonly kind: 'global' | 'info' | 'gitignore';
595
+ /** POSIX-relative directory whose file carried the rule. `''` for global / info / repo-root gitignore. */
596
+ readonly basedir: FilePath | '';
597
+ /** 1-based line number of the matching rule inside its file. */
598
+ readonly line: number;
599
+ /** Raw pattern text (e.g. `*.log`, `!keep.log`, `build/`). */
600
+ readonly pattern: string;
601
+ }
602
+ interface IsIgnoredMatch {
603
+ readonly path: FilePath;
604
+ readonly ignored: boolean;
605
+ /** Set only when `ignored === true`. */
606
+ readonly source?: IsIgnoredMatchSource;
607
+ }
608
+ declare const isIgnored: (ctx: Context, queries: ReadonlyArray<IsIgnoredQuery>) => Promise<ReadonlyArray<IsIgnoredMatch>>;
609
+
610
+ /**
611
+ * Lazily reads an on-disk fanout subtree's entries on demand. Injected by the
612
+ * caller so the trie stays pure: the I/O lives outside the domain.
613
+ */
614
+ type SubtreeReader = (oid: ObjectId) => Promise<ReadonlyArray<TreeEntry>>;
615
+ interface EmptySlot {
616
+ readonly kind: 'empty';
617
+ }
618
+ interface NoteSlot {
619
+ readonly kind: 'note';
620
+ readonly key: ObjectId;
621
+ readonly val: ObjectId;
622
+ }
623
+ interface SubtreeSlot {
624
+ readonly kind: 'subtree';
625
+ readonly prefix: string;
626
+ readonly oid: ObjectId;
627
+ }
628
+ interface InternalSlot {
629
+ readonly kind: 'internal';
630
+ readonly node: NotesTrie;
631
+ }
632
+ type Slot = EmptySlot | NoteSlot | SubtreeSlot | InternalSlot;
633
+ /** A 16-way nibble-trie node: one slot per hex value of the oid at this depth. */
634
+ interface NotesTrie {
635
+ readonly slots: ReadonlyArray<Slot>;
636
+ readonly preserved: ReadonlyArray<TreeEntry>;
637
+ }
638
+
639
+ interface LoadedNotesTree {
640
+ /** The trie built from the on-disk notes tree. Empty when the ref is absent. */
641
+ readonly trie: NotesTrie;
642
+ /** Reads a subtree's entries on demand (lazy subtree unpacking). */
643
+ readonly read: SubtreeReader;
644
+ /** The commit oid the notes ref resolved to, or `undefined` if the ref did not exist. */
645
+ readonly notesCommitOid: ObjectId | undefined;
646
+ /** The notes commit's root tree oid, or `undefined` if the ref did not exist. */
647
+ readonly notesTreeOid: ObjectId | undefined;
648
+ }
649
+ /**
650
+ * Resolves a notes ref to its commit, reads the commit's tree, and builds a
651
+ * `NotesTrie` via the domain's `loadTrieRoot`. Returns an empty trie when the
652
+ * ref does not exist yet.
653
+ *
654
+ * The returned `read` function acts as the lazy subtree reader: passing it to
655
+ * the domain's write-plan walker lets it unpack fanout subtrees on demand.
656
+ */
657
+ declare function loadNotesTree(ctx: Context, ref: RefName): Promise<LoadedNotesTree>;
658
+
659
+ /**
660
+ * Compose `walkTree → computeChangeset → applyChangeset` to update the
661
+ * working tree to a target tree's contents.
662
+ *
663
+ * - Branch switch mode: `paths === undefined` — diff the entire current
664
+ * index against the entire target tree.
665
+ * - Path-restore mode: `paths !== undefined` — restrict both sides of
666
+ * the diff to those paths.
667
+ *
668
+ * Returns the new IndexEntry list for the caller to commit, plus
669
+ * written/deleted counts. The primitive does NOT commit the index — the
670
+ * caller decides.
671
+ *
672
+ * ## Stat-source contract for `newIndexEntries` (load-bearing for)
673
+ *
674
+ * - **Paths that were written/added** (`add` or `update` changeset entries):
675
+ * the IndexEntry carries **post-write `lstat`-derived stat fields**
676
+ * (ctime/mtime/dev/ino/uid/gid/fileSize). These reflect the file we just
677
+ * wrote, so the next `status` runs the fast `isStatClean` path.
678
+ * - **Paths whose changeset classification was `noop`** (skipped — index
679
+ * already matched target by `id + mode`): the IndexEntry is the caller's
680
+ * `currentIndex` entry verbatim. Donor stats survive across the call.
681
+ * - `reset --hard` therefore MUST set `forceRewriteAll: true` so every noop
682
+ * upgrades to update and the post-write stats land in the output. Without
683
+ * that, a locally-modified working-tree file that the index still records
684
+ * as clean would survive the reset, AND the donor stats would be stale
685
+ * relative to the actual disk state.
686
+ */
687
+
688
+ interface MaterializeTreeOpts {
689
+ readonly targetTree: ObjectId;
690
+ readonly currentIndex: GitIndex;
691
+ readonly force?: boolean;
692
+ readonly paths?: ReadonlySet<FilePath>;
693
+ /**
694
+ * When true, every target-tree path is written to the working tree
695
+ * unconditionally — even paths the index→target diff classified as `noop`
696
+ * (same `id` AND `mode`). Required by `reset --hard`, where the working
697
+ * tree may diverge from the index (uncommitted local modifications); the
698
+ * standard index→target diff cannot see that drift, so noops would skip
699
+ * paths the caller wants overwritten. Default `false` keeps the Phase
700
+ * 13.1 checkout behaviour: clean files are never spuriously rewritten.
701
+ */
702
+ readonly forceRewriteAll?: boolean;
703
+ /**
704
+ * Branch-switch sparse-checkout filter. Honoured ONLY when `paths` is
705
+ * undefined. A target-tree path the matcher rejects is NOT written to the
706
+ * working tree; its `newIndexEntries` record carries `skipWorktree: true`
707
+ * (the index keeps every path — git-faithful). A path the matcher accepts
708
+ * that the *current* index records as skip-worktree (absent on disk) is
709
+ * materialised even when its `id` matches, because the current index is
710
+ * filtered to drop skip-worktree entries before the diff — such a path
711
+ * classifies as `add`, never `noop`.
712
+ */
713
+ readonly sparse?: SparseMatcher;
714
+ }
715
+ interface MaterializeTreeResult {
716
+ readonly newIndexEntries: ReadonlyArray<IndexEntry>;
717
+ readonly written: number;
718
+ readonly deleted: number;
719
+ }
720
+ declare const materializeTree: (ctx: Context, opts: MaterializeTreeOpts) => Promise<MaterializeTreeResult>;
721
+
722
+ declare const materializeWorktreeFromHead: (ctx: Context) => Promise<MaterializeTreeResult>;
723
+
724
+ interface MergeBaseOptions {
725
+ readonly all?: boolean;
726
+ readonly octopus?: boolean;
727
+ }
728
+ /**
729
+ * Compute merge bases — the best common ancestors of the given commits.
730
+ *
731
+ * `commits[0]` is `one`, the rest are the others. Returns the lexicographically
732
+ * smallest single base by default; the full reduced set with `{ all: true }`;
733
+ * the octopus fold with `{ octopus: true }`. Unrelated histories yield `[]`.
734
+ */
735
+ declare const mergeBase: (ctx: Context, commits: readonly ObjectId[], options?: MergeBaseOptions) => Promise<readonly ObjectId[]>;
736
+
737
+ /**
738
+ * Pure path helpers composing `ctx.layout.gitDir` with known sub-paths.
739
+ * No I/O. No port access. Primitive step 3.
740
+ */
741
+
742
+ /**
743
+ * Repository working-tree root. Returns the workDir from the current context;
744
+ * facade-tier code is responsible for discovery / realpath pinning
745
+ * at construction time. Primitives consume the already-resolved path.
746
+ */
747
+ declare const getRepoRoot: (ctx: Context) => FilePath;
748
+ declare const sparseCheckoutPath: (gitDir: string) => string;
749
+
750
+ declare function readBlob(ctx: Context, id: ObjectId, options?: ReadObjectOptions): Promise<Blob>;
751
+
752
+ /**
753
+ * Resolve HEAD's commit tree as a `FlatTree` (`path → { id, mode }`), or
754
+ * `undefined` for an unborn HEAD (no commits yet). This is git's HEAD-tree side
755
+ * of `diff-index` — the staged column compares it against the index.
756
+ *
757
+ * Tolerates an unborn HEAD by catching `REF_NOT_FOUND` (the symbolic ref points
758
+ * at a branch with no commit). A HEAD that resolves to a non-commit object is a
759
+ * corrupt repository and throws `unexpectedObjectType`.
760
+ *
761
+ * Pure with respect to the working tree — only reads git objects (via
762
+ * `resolveRef` / `readObject` / `flattenTree`).
763
+ */
764
+
765
+ declare const readHeadTree: (ctx: Context) => Promise<FlatTree | undefined>;
766
+
767
+ declare function readIndex(ctx: Context): Promise<GitIndex>;
768
+
769
+ declare function readObject(ctx: Context, id: ObjectId, options?: ReadObjectOptions): Promise<GitObject>;
770
+
771
+ /**
772
+ * Hard cap on the `.git/info/sparse-checkout` file — 1 MiB, mirroring
773
+ * `MAX_GITIGNORE_BYTES`. A plain literal (not `1024 * 1024`) so a boundary test
774
+ * keyed on the constant cannot drift with an arithmetic mutation of it.
775
+ */
776
+ declare const MAX_SPARSE_PATTERN_FILE_BYTES = 1048576;
777
+ /**
778
+ * Read `.git/info/sparse-checkout` as UTF-8 text. An absent file yields
779
+ * `undefined`; a file whose byte length exceeds
780
+ * `MAX_SPARSE_PATTERN_FILE_BYTES` throws `SPARSE_PATTERN_FILE_TOO_LARGE`
781
+ * (checked before decode so an over-cap file never reaches the decoder).
782
+ */
783
+ declare const readSparsePatternText: (ctx: Context) => Promise<string | undefined>;
784
+ /**
785
+ * Build the sparse matcher for the current repository. Returns `undefined`
786
+ * when `core.sparseCheckout` is falsy/absent — sparse is inactive and callers
787
+ * behave exactly as a non-sparse repo. When active, the matcher is parsed in
788
+ * the mode `core.sparseCheckoutCone` dictates; a cone file that degrades to
789
+ * non-cone matching logs one warning.
790
+ */
791
+ declare const loadSparseMatcher: (ctx: Context) => Promise<SparseMatcher | undefined>;
792
+
793
+ declare function readTree(ctx: Context, ref: RefName | ObjectId): Promise<Tree>;
794
+
795
+ /**
796
+ * Committer identity for reflog entries: config `user.*` plus a fresh
797
+ * timestamp, or a portable fallback when `user.*` is unset. Never throws —
798
+ * reflog logging must not abort a ref update.
799
+ */
800
+ declare function resolveReflogIdentity(ctx: Context): Promise<AuthorIdentity>;
801
+
802
+ /**
803
+ * Thin I/O layer over `.git/logs/<ref>` reflog files. Append is the hot path;
804
+ * whole-file rewrite and delete back the `reflog` command's expire / delete.
805
+ */
806
+
807
+ /** Append one entry to `ref`'s reflog, creating the file and parents as needed. */
808
+ declare function appendReflog(ctx: Context, ref: RefName, entry: ReflogEntry): Promise<void>;
809
+ /** Read `ref`'s reflog, oldest-first. Returns `[]` when the file is absent. */
810
+ declare function readReflog(ctx: Context, ref: RefName): Promise<ReadonlyArray<ReflogEntry>>;
811
+ /** Whether `ref` has a reflog file at all. */
812
+ declare function reflogExists(ctx: Context, ref: RefName): Promise<boolean>;
813
+ /** Replace `ref`'s reflog with exactly `entries`. Used by expire / delete. */
814
+ declare function writeReflog(ctx: Context, ref: RefName, entries: ReadonlyArray<ReflogEntry>): Promise<void>;
815
+ /** Remove `ref`'s reflog file. A no-op when the file is already absent. */
816
+ declare function deleteReflog(ctx: Context, ref: RefName): Promise<void>;
817
+ /** Every reflog under `.git/logs/`, each as the `RefName` it logs. */
818
+ declare function listReflogs(ctx: Context): Promise<ReadonlyArray<RefName>>;
819
+
820
+ /** The default notes namespace git uses when no override is in effect. */
821
+ declare const DEFAULT_NOTES_REF: RefName;
822
+ /**
823
+ * Resolves the notes ref to use for a notes operation.
824
+ *
825
+ * Precedence (highest first):
826
+ * 1. Explicit `ref` argument (git `--ref`) — expanded under `refs/notes/`
827
+ * 2. `GIT_NOTES_REF` environment variable — verbatim, refused if outside
828
+ * 3. `core.notesRef` git config value — verbatim, refused if outside
829
+ * 4. `refs/notes/commits` (hard-coded default)
830
+ *
831
+ * The resolved name is validated as a legal ref name before being returned.
832
+ */
833
+ declare function resolveNotesRef(ctx: Context, ref?: string): Promise<RefName>;
834
+
835
+ declare function resolveRef(ctx: Context, name: RefName | 'HEAD', options?: ResolveRefOptions): Promise<ObjectId>;
836
+
837
+ /** Optional arguments and stdin a caller threads into a hook invocation. */
838
+ interface HookInput {
839
+ readonly args?: ReadonlyArray<string>;
840
+ readonly stdin?: string;
841
+ }
842
+ /**
843
+ * Run a blocking git hook through `ctx.hooks`. A no-op when no `HookRunner` is
844
+ * wired (browser, or opted out), when the hook file is absent / not executable
845
+ * (`skipped`), or when the hook exits 0. Throws `HOOK_FAILED` on a non-zero
846
+ * exit — the caller's signal to abort the operation.
847
+ */
848
+ declare const runHook: (ctx: Context, name: HookName, input?: HookInput) => Promise<void>;
849
+ /**
850
+ * Run an informational (`post-*`) git hook — fire-and-forget. The operation has
851
+ * already completed, so git ignores a post-hook's exit code (it cannot abort);
852
+ * tsgit does the same: absent runner, `skipped`, or any exit code → no throw,
853
+ * no return value. The runner never rejects, so this only ever resolves.
854
+ */
855
+ declare const runInformationalHook: (ctx: Context, name: HookName, input?: HookInput) => Promise<void>;
856
+
857
+ /**
858
+ * Read `.git/shallow`. Returns an empty set when the file does not exist or
859
+ * contains no oids. Malformed lines are tolerated (skipped) — canonical
860
+ * git behaves the same; a corrupted shallow file should not block a fetch.
861
+ */
862
+ declare const readShallow: (ctx: Context) => Promise<ReadonlySet<ObjectId>>;
863
+ interface ShallowUpdate {
864
+ readonly shallow: ReadonlyArray<ObjectId>;
865
+ readonly unshallow: ReadonlyArray<ObjectId>;
866
+ }
867
+ /**
868
+ * Apply a set of shallow / unshallow updates to `.git/shallow`. Writes
869
+ * atomically via lock-rename; deletes the file when the resulting set is
870
+ * empty.
871
+ */
872
+ declare const updateShallow: (ctx: Context, updates: ShallowUpdate) => Promise<void>;
873
+
874
+ type SignPayloadResult = {
875
+ readonly ok: true;
876
+ readonly armor: string;
877
+ } | {
878
+ readonly ok: false;
879
+ readonly reason: 'off-node' | 'unsupported-format' | 'signer-failed';
880
+ };
881
+ interface SignRequest {
882
+ readonly format: 'openpgp' | 'ssh' | 'x509';
883
+ /** `gpg.program` / `gpg.ssh.program`; a family-specific default applies when absent. */
884
+ readonly program?: string;
885
+ /** Resolved `-u` value (openpgp) / `-f` key-file path (ssh). */
886
+ readonly selector: string;
887
+ }
888
+ interface ResolveSigningSelectorInput {
889
+ readonly signingKey?: string;
890
+ readonly keyOverride?: string;
891
+ readonly fallbackIdent: string;
892
+ }
893
+ /**
894
+ * Resolves the openpgp `-u` selector / the push-cert `pusher` selector —
895
+ * the identical `user.signingKey`-else-ident rule shared by commit, tag, and
896
+ * push-cert signing. The ssh `-f` key-file selector has NO ident fallback and
897
+ * is resolved by the caller directly (`keyOverride ?? signingKey`), not here.
898
+ */
899
+ declare const resolveSigningSelector: (input: ResolveSigningSelectorInput) => string;
900
+ /**
901
+ * Pure(ish) signing primitive delegating to the system signer through
902
+ * `ctx.command` — no new port. `gpg` runs stdin→stdout; `ssh-keygen` writes
903
+ * the payload to a temp file and reads the armor back from `<file>.sig`.
904
+ * Requesting `x509` and running with no `ctx.command` both refuse with a
905
+ * typed reason before any spawn or temp-file write. Success requires exit 0
906
+ * AND a well-formed armor block on the signer's output; anything else is a
907
+ * typed `signer-failed` refusal — never a partial or silent result.
908
+ */
909
+ declare const signPayload: (ctx: Context, payload: Uint8Array, req: SignRequest) => Promise<SignPayloadResult>;
910
+
911
+ interface StreamBlobOptions {
912
+ readonly verifyHash?: boolean;
913
+ }
914
+ interface BlobStream extends AsyncIterable<Uint8Array> {
915
+ readonly materialised: boolean;
916
+ }
917
+ declare function streamBlob(ctx: Context, id: ObjectId, options?: StreamBlobOptions): Promise<BlobStream>;
918
+
919
+ /**
920
+ * Synthesise a nested `Tree` object from a flat `GitIndex` and return the
921
+ * root tree's `ObjectId`. Sub-trees are written to the object store as a
922
+ * side-effect of the recursive descent — only stage-0 entries contribute.
923
+ *
924
+ * Used by `checkout({ paths, source: 'index' })` to restore
925
+ * the working tree from staged content even when the index has diverged
926
+ * from HEAD via `add` / `rm`. The previous placeholder fell back to
927
+ * HEAD's tree, which silently lost the divergence.
928
+ *
929
+ * The synthesis is the inverse of `buildIndexFromTree`:
930
+ * "tree → index" and "index → tree" form a round-trip identity for any
931
+ * stage-0-only index.
932
+ *
933
+ * Pure with respect to the working tree — never calls `fs.lstat`,
934
+ * `fs.read`, or any working-tree-side API. Only writes git objects via
935
+ * the existing `writeTree` primitive.
936
+ *
937
+ * ## Safety
938
+ *
939
+ * - **Path validation**:.7 hoisted segment-level validation into
940
+ * `parseIndex` (`src/domain/git-index/path-validator.ts`). Every
941
+ * `IndexEntry` reaching this primitive THROUGH THE CANONICAL PARSER
942
+ * carries a `FilePath` value already free of `..`, `.`, empty segments,
943
+ * and leading-slash absolute paths. However, the primitive is also
944
+ * reachable from callers that construct `IndexEntry` records outside
945
+ * the parser (test fixtures, in-memory adapters, future synthesisers).
946
+ * Defence-in-depth: every entry is re-validated here so the primitive
947
+ * stays safe even when the parser-trusted path is bypassed.
948
+ * - **Depth cap**: synthesis bounds recursion at `MAX_TREE_DEPTH` (4096,
949
+ * matching git's canonical limit). The cap is enforced at the input
950
+ * boundary by counting slashes — by the time recursion would catch a
951
+ * pathological depth, the JS engine has already exhausted its call
952
+ * stack. Path validation does NOT subsume this check: a path can be
953
+ * safe segment-by-segment (no `..`/`.`/empty) and still be 10 000
954
+ * levels deep.
955
+ */
956
+
957
+ /**
958
+ * Public entry: pass the `entries` array directly (typically
959
+ * `index.entries`, but callers holding a filtered list may supply it
960
+ * without wrapping in a fake `GitIndex`).
961
+ */
962
+ declare const synthesizeTreeFromIndex: (ctx: Context, entries: ReadonlyArray<IndexEntry>) => Promise<ObjectId>;
963
+
964
+ /**
965
+ * Section-level surgery for `.git/config`: rename-section and remove-section.
966
+ * These operations match headers by their raw dotted name (byte-exact,
967
+ * case-sensitive) and rewrite or drop them without touching any other byte.
968
+ *
969
+ * @writes
970
+ * surface: config
971
+ * kind: readback-only
972
+ * format: git-config-text
973
+ */
974
+
975
+ /**
976
+ * Rename headers matching `oldName` (raw byte-exact dotted name) to the new
977
+ * section shape derived from `newName` (parsed via `parseNewSectionName`).
978
+ * The old name is never validated — any string is a legal lookup key; a miss
979
+ * throws `CONFIG_SECTION_NOT_FOUND` carrying the raw input verbatim. Throws
980
+ * `INVALID_OPTION` when the new subsection contains a LF or NUL.
981
+ */
982
+ declare const renameConfigSection: ({ ctx, oldName, newName, scope, }: {
983
+ readonly ctx: Context;
984
+ readonly oldName: string;
985
+ readonly newName: string;
986
+ readonly scope?: ConfigScope;
987
+ }) => Promise<void>;
988
+ /**
989
+ * Delete headers matching `sectionName` (raw byte-exact dotted name) and their
990
+ * bodies. The name is never validated — any string is a legal lookup key (e.g.
991
+ * `'remote'`, `'s.'`, `''`); a miss throws `CONFIG_SECTION_NOT_FOUND` carrying
992
+ * the raw input verbatim. For the trailing-dot and empty-name forms see
993
+ * `rawSectionName` and `removeConfigSectionInText` documentation.
994
+ */
995
+ declare const removeConfigSection: ({ ctx, sectionName, scope, }: {
996
+ readonly ctx: Context;
997
+ readonly sectionName: string;
998
+ readonly scope?: ConfigScope;
999
+ }) => Promise<void>;
1000
+
1001
+ /**
1002
+ * Targeted `.git/config` writer: entry-level surgery that preserves comments,
1003
+ * blank lines, key order, casing of unrelated keys, and every other section
1004
+ * byte-for-byte. Writes one `key = value` per call under any
1005
+ * `[section]` / `[section "subsection"]`.
1006
+ *
1007
+ * @writes
1008
+ * surface: config
1009
+ * kind: readback-only
1010
+ * format: git-config-text
1011
+ */
1012
+
1013
+ /**
1014
+ * Set `key` under `[section]` / `[section "subsection"]`, preserving every
1015
+ * other byte verbatim.
1016
+ *
1017
+ * - existing section with that key ⇒ full span of the first match is replaced
1018
+ * by a single canonical `\t<key> = <value>` line;
1019
+ * - existing section without that key ⇒ a `\t<key> = <value>` line is
1020
+ * inserted at the end of the last matching block;
1021
+ * - no such section ⇒ `[section]\n\t<key> = <value>\n` is appended.
1022
+ */
1023
+ declare const setConfigEntryInText: (text: string, section: string, subsection: string | undefined, key: string, value: string) => string;
1024
+ /** `setConfigEntryInText` bound to the `[core]` section — kept for legacy callers. */
1025
+ declare const setCoreConfigEntryInText: (text: string, key: string, value: string) => string;
1026
+ /** One `key = value` write under `[section]` / `[section "subsection"]`. */
1027
+ interface ConfigEntry {
1028
+ readonly section: string;
1029
+ readonly subsection?: string;
1030
+ readonly key: string;
1031
+ readonly value: string;
1032
+ }
1033
+ /**
1034
+ * Read `${gitDir}/config` (a missing file is treated as `''`), fold
1035
+ * `setConfigEntryInText` over `entries`, write the result, and invalidate the
1036
+ * per-`Context` `readConfig` cache so a later read sees the new values.
1037
+ */
1038
+ declare const updateConfigEntries: (ctx: Context, entries: ReadonlyArray<ConfigEntry>) => Promise<void>;
1039
+ /** Fold a batch of `[core]` `key = value` writes via `updateConfigEntries`. */
1040
+ declare const updateCoreConfig: (ctx: Context, entries: Record<string, string>) => Promise<void>;
1041
+ /**
1042
+ * Mixed-operation batch entry. Folded over the on-disk text in order in
1043
+ * a single `writeUtf8`. Use this when `remote` CRUD needs a section-
1044
+ * remove paired with branch-referrer key removals in one atomic write.
1045
+ */
1046
+ type ConfigOperation = {
1047
+ readonly kind: 'set';
1048
+ readonly section: string;
1049
+ readonly subsection?: string;
1050
+ readonly key: string;
1051
+ readonly value: string;
1052
+ } | {
1053
+ /**
1054
+ * Insert a fresh `key = value` line at the end of the last matching
1055
+ * section block WITHOUT replacing any existing entry with the same key.
1056
+ * Use for multi-value keys (`fetch`) where every call must yield an
1057
+ * additional line.
1058
+ */
1059
+ readonly kind: 'appendEntry';
1060
+ readonly section: string;
1061
+ readonly subsection?: string;
1062
+ readonly key: string;
1063
+ readonly value: string;
1064
+ } | {
1065
+ /**
1066
+ * Remove every entry span for `key` from the section, pruning the block
1067
+ * header if no entries or comments remain. Delegates to `removeConfigEntry`.
1068
+ */
1069
+ readonly kind: 'removeEntry';
1070
+ readonly section: string;
1071
+ readonly subsection?: string;
1072
+ readonly key: string;
1073
+ } | {
1074
+ readonly kind: 'removeSection';
1075
+ readonly section: string;
1076
+ readonly subsection?: string;
1077
+ } | {
1078
+ readonly kind: 'renameSection';
1079
+ readonly section: string;
1080
+ readonly from: string;
1081
+ readonly to: string;
1082
+ };
1083
+ declare const applyConfigOpInText: (text: string, op: ConfigOperation) => string;
1084
+ /**
1085
+ * Write a single `key = value` entry into the config file for the given scope
1086
+ * (default `'local'`). Re-runs of the same call with a different value
1087
+ * overwrite the existing entry in place (preserving comments and surrounding
1088
+ * content). The key is validated via `parseConfigKey` (throws
1089
+ * `CONFIG_KEY_INVALID` on a malformed input) and the value is validated by
1090
+ * `assertValueSafe` (throws `CONFIG_VALUE_INVALID` on a banned control char)
1091
+ * BEFORE any I/O — a rejected input never touches the file system.
1092
+ *
1093
+ * The branding on `ConfigKey` is enforced at the type level; this primitive
1094
+ * accepts a raw string and parses it internally so it can be used directly
1095
+ * from porcelain wrappers that hold un-branded callers' input.
1096
+ */
1097
+ declare const setConfigEntry: ({ ctx, key, value, scope, }: {
1098
+ readonly ctx: Context;
1099
+ readonly key: string;
1100
+ readonly value: string;
1101
+ readonly scope?: ConfigScope;
1102
+ }) => Promise<void>;
1103
+ /**
1104
+ * Remove a single `key = value` entry from the given scope. Idempotent — if
1105
+ * the key is absent the call is a no-op (no I/O). If the key appears more
1106
+ * than once in the targeted scope, throws `CONFIG_MULTIPLE_VALUES` with
1107
+ * `requested: 'remove'` (the caller should use `unsetAllConfigEntries` to
1108
+ * clear every occurrence). An emptied section block is pruned entirely
1109
+ * (header + blank lines removed) unless the block contains a comment.
1110
+ */
1111
+ declare const unsetConfigEntry: ({ ctx, key, scope, }: {
1112
+ readonly ctx: Context;
1113
+ readonly key: string;
1114
+ readonly scope?: ConfigScope;
1115
+ }) => Promise<void>;
1116
+ /**
1117
+ * Remove every occurrence of `key` from the targeted scope. Idempotent — a
1118
+ * missing key produces no I/O. Unlike `unsetConfigEntry`, multi-valued keys
1119
+ * are explicitly supported: all matching spans are removed in a single
1120
+ * read-modify-write pass. An emptied section block is pruned entirely
1121
+ * (header + blank lines removed) unless the block contains a comment.
1122
+ */
1123
+ declare const unsetAllConfigEntries: ({ ctx, key, scope, }: {
1124
+ readonly ctx: Context;
1125
+ readonly key: string;
1126
+ readonly scope?: ConfigScope;
1127
+ }) => Promise<void>;
1128
+
1129
+ declare function updateRef(ctx: Context, name: RefName, newId: ObjectId, options: UpdateRefOptions): Promise<void>;
1130
+
1131
+ declare function walkCommits(ctx: Context, options: WalkCommitsOptions): AsyncIterable<Commit>;
1132
+
1133
+ /**
1134
+ * Walk every commit reachable from `from` across **all** parents, yielding them
1135
+ * in commit-date priority order — newest committer date first, oid-ascending on
1136
+ * ties. A thin wrapper over the shared {@link commitDateWalk} core: it owns the
1137
+ * public `INVALID_WALK_INPUT` seed contract (empty / too-many seeds) and
1138
+ * delegates the all-parents traversal. The core's first-parent variant is
1139
+ * internal — no public consumer needs date + first-parent yet (`log` routes
1140
+ * `--first-parent` through `walkCommits`'s lazy FIFO).
1141
+ */
1142
+ declare function walkCommitsByDate(ctx: Context, options: WalkCommitsByDateOptions): AsyncIterable<Commit>;
1143
+
1144
+ /**
1145
+ * Yield every gitlink reachable in `ref`'s tree, joined with its `.gitmodules`
1146
+ * metadata. With `recursive: true`, descend into each nested submodule whose
1147
+ * absorbed gitdir (`${gitDir}/modules/<name>`) is locally available; nested
1148
+ * yields carry `depth >= 1` and a `parent` path. Uninitialised / missing /
1149
+ * cyclic nested submodules contribute their own entry but no children — the
1150
+ * absence of further yields is the signal, matching `git submodule status
1151
+ * --recursive`.
1152
+ */
1153
+ declare function walkSubmodules(ctx: Context, options?: WalkSubmodulesOptions): AsyncIterable<SubmoduleEntry>;
1154
+
1155
+ declare function walkTree(ctx: Context, treeIdOrObject: ObjectId | Tree, options?: WalkTreeOptions): AsyncIterable<WalkTreeEntry>;
1156
+
1157
+ /**
1158
+ * Depth-first walk of the working tree starting at `ctx.layout.workDir`.
1159
+ *
1160
+ * Yields leaf entries (files and symlinks) as `{ path, stat }`. Directories
1161
+ * are descended into, not yielded. `.git` at any level is skipped
1162
+ * (case-insensitive, NTFS-trimmed). Embedded repositories (directories
1163
+ * containing a `.git` child) are skipped entirely — yields nothing under
1164
+ * them. Symlinks are surfaced via `lstat` (no follow); a symlink to a
1165
+ * directory is yielded as a leaf, not descended into.
1166
+ *
1167
+ * The host repository's own `.git` is NOT treated as an embedded-repo
1168
+ * marker — at the workDir root we only skip the `.git` entry itself, not
1169
+ * the workDir.
1170
+ */
1171
+ declare function walkWorkingTree(ctx: Context, options?: WalkWorkingTreeOptions): AsyncIterable<WalkWorkingTreeEntry>;
1172
+
1173
+ interface WriteNotesTreeInput {
1174
+ /** The in-memory trie to serialize. */
1175
+ readonly trie: NotesTrie;
1176
+ /** Subtree reader for lazy unpacking during write-plan generation. */
1177
+ readonly read: SubtreeReader;
1178
+ /** The notes commit the new commit should descend from, or `undefined` for a root commit. */
1179
+ readonly prevCommitOid: ObjectId | undefined;
1180
+ /** The notes commit message (caller owns the verb, e.g. "Notes added by 'git notes add'"). */
1181
+ readonly message: string;
1182
+ /** The identity used as both author and committer of the notes commit. */
1183
+ readonly author: AuthorIdentity;
1184
+ }
1185
+ /**
1186
+ * Converts a notes trie into a git commit:
1187
+ * 1. Walks the trie to produce a flat write-plan.
1188
+ * 2. Converts the flat plan into a real git tree hierarchy (bottom-up).
1189
+ * 3. Creates a notes commit (author == committer == the caller-resolved identity).
1190
+ *
1191
+ * Identity resolution lives in the calling command (`resolveCurrentIdentity`);
1192
+ * this primitive stays config-free. The caller is responsible for updating the
1193
+ * notes ref and reflog after this returns.
1194
+ */
1195
+ declare function writeNotesTree(ctx: Context, input: WriteNotesTreeInput): Promise<ObjectId>;
1196
+
1197
+ declare function writeObject(ctx: Context, object: GitObject): Promise<ObjectId>;
1198
+
1199
+ /**
1200
+ * Write the `.git/info/sparse-checkout` pattern file. The command tier
1201
+ * computes the text (via `serializeCone` or raw non-cone lines); this
1202
+ * primitive only persists it (design §7.3).
1203
+ *
1204
+ * @writes
1205
+ * surface: sparseCheckoutFile
1206
+ * kind: byte-identical
1207
+ * format: git-sparse-checkout
1208
+ */
1209
+
1210
+ /**
1211
+ * Persist `text` to `.git/info/sparse-checkout`. The `.git/info` directory is
1212
+ * created defensively first — `writeUtf8` creates parents on every adapter,
1213
+ * but an explicit `mkdir` keeps the contract clear and survives adapters that
1214
+ * tighten that guarantee.
1215
+ */
1216
+ declare const writeSparsePatternText: (ctx: Context, text: string) => Promise<void>;
1217
+
1218
+ declare function writeTree(ctx: Context, entries: ReadonlyArray<TreeEntry>): Promise<ObjectId>;
1219
+
1220
+ export { findFirstValuelessEntry as $, DEFAULT_NOTES_REF as D, buildPack as G, catFileBatch as J, compareWorkingTreeDelta as K, MAX_SPARSE_PATTERN_FILE_BYTES as M, compareWorkingTreeEntry as N, computeChangeset as O, createCommit as Q, createTag as R, deleteReflog as T, diffTrees as U, enumerateObjects as X, enumeratePushObjects as Y, enumerateRefs as Z, fetchPack as _, flattenTree as a0, getAllConfigValues as a1, getConfigValue as a2, getRepoRoot as a3, hasObject as a4, hashBlob as a5, invalidateConfigCache as a6, invalidateScopedConfigCache as a7, isIgnored as a8, isWorkingTreeDirty as a9, setConfigEntry as aA, setConfigEntryInText as aB, setCoreConfigEntryInText as aC, signPayload as aD, sparseCheckoutPath as aE, streamBlob as aF, synthesizeTreeFromIndex as aG, unsetAllConfigEntries as aH, unsetConfigEntry as aI, updateConfigEntries as aJ, updateCoreConfig as aK, updateRef as aL, updateShallow as aM, walkCommits as aN, walkCommitsByDate as aO, walkSubmodules as aP, walkTree as aQ, walkWorkingTree as aR, writeNotesTree as aS, writeObject as aT, writeReflog as aU, writeSparsePatternText as aV, writeTree as aW, listReflogs as aa, loadNotesTree as ab, loadSparseMatcher as ac, materializeTree as ad, materializeWorktreeFromHead as ae, mergeBase as af, parseIniSections as ag, readBlob as ah, readConfig as ai, readConfigSections as aj, readHeadTree as ak, readIndex as al, readObject as am, readReflog as an, readShallow as ao, readSparsePatternText as ap, readTree as aq, reflogExists as ar, removeConfigSection as as, renameConfigSection as at, resolveNotesRef as au, resolveRef as av, resolveReflogIdentity as aw, resolveSigningSelector as ax, runHook as ay, runInformationalHook as az, appendReflog as v, applyChangeset as w, applyConfigOpInText as x, bisectMidpoint as y, buildIndexFromTree as z };
1221
+ export type { ApplyChangesetOpts as A, BlobStream as B, Changeset as C, EnumerateObjectsOptions as E, FetchPackInput as F, HashBlobOptions as H, IniSection as I, LoadedNotesTree as L, ParsedConfig as P, SignPayloadResult as S, ValuelessEntry as V, WorkingTreeComparison as W, ApplyChangesetResult as a, GlobMatcher as aX, BuildIndexFromTreeOpts as b, BuildPackInput as c, BuildPackResult as d, ChangesetEntry as e, ChangesetStats as f, ConfigEntry as g, EnumeratePushObjectsInput as h, FetchPackResult as i, HookInput as j, IsIgnoredMatch as k, IsIgnoredMatchSource as l, IsIgnoredQuery as m, MaterializeTreeOpts as n, MaterializeTreeResult as o, MergeBaseOptions as p, PushDefaultMode as q, SignRequest as r, StreamBlobOptions as s, WorkingTreeDelta as t, WriteNotesTreeInput as u };