@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.
- package/README.md +14 -2
- package/dist/cjs/adapters/browser/index.cjs +1 -2
- package/dist/cjs/adapters/memory/index.cjs +1 -2
- package/dist/cjs/adapters/node/index.cjs +1 -2
- package/dist/cjs/chunks/adapter-detect-DW9fsw9d.cjs +1 -0
- package/dist/cjs/chunks/browser-http-transport-DGwW5YL7.cjs +1 -0
- package/dist/cjs/chunks/context-BcoAzPuU.cjs +0 -1
- package/dist/cjs/chunks/error-CfLWDui_.cjs +1 -0
- package/dist/cjs/chunks/index-Cy44GVR6.cjs +1 -0
- package/dist/cjs/chunks/inflate-CmCtM4-w.cjs +1 -0
- package/dist/cjs/chunks/lru-cache-1OU7JhD8.cjs +0 -1
- package/dist/cjs/chunks/memory-http-transport-CGriODcQ.cjs +1 -0
- package/dist/cjs/chunks/node-ssh-transport-PFu3ijfp.cjs +1 -0
- package/dist/cjs/chunks/{progress-CxU62NC1.cjs → progress-D8Dqbftk.cjs} +1 -2
- package/dist/cjs/chunks/readable-stream-MTA6D0Zh.cjs +0 -1
- package/dist/cjs/chunks/repository-Ci-BBxk0.cjs +1 -0
- package/dist/cjs/chunks/write-sparse-checkout-C1dsHCAD.cjs +1 -0
- package/dist/cjs/commands/index.cjs +1 -2
- package/dist/cjs/index.browser.cjs +1 -2
- package/dist/cjs/index.cjs +1 -2
- package/dist/cjs/index.default.cjs +1 -2
- package/dist/cjs/index.node.cjs +1 -2
- package/dist/cjs/operators/index.cjs +0 -1
- package/dist/cjs/primitives/index.cjs +1 -2
- package/dist/cjs/transport/index.cjs +0 -1
- package/dist/esm/adapters/browser/index.js +1 -2
- package/dist/esm/adapters/memory/index.js +1 -2
- package/dist/esm/adapters/node/index.js +1 -2
- package/dist/esm/chunks/adapter-detect-BkCMnjrI.js +1 -0
- package/dist/esm/chunks/browser-http-transport-CSxAte5h.js +1 -0
- package/dist/esm/chunks/context-CumKOV7K.js +0 -1
- package/dist/esm/chunks/error-BotOd-nD.js +1 -0
- package/dist/esm/chunks/index-DsvINN8n.js +1 -0
- package/dist/esm/chunks/inflate-BCIXqeeE.js +1 -0
- package/dist/esm/chunks/lru-cache-Cy7C7Lx2.js +0 -1
- package/dist/esm/chunks/memory-http-transport-caqmMGR1.js +1 -0
- package/dist/esm/chunks/node-ssh-transport-BgSv2IhT.js +1 -0
- package/dist/esm/chunks/{progress-BZobfl7p.js → progress-B_AJnOHx.js} +1 -2
- package/dist/esm/chunks/readable-stream-CGuf8k1J.js +0 -1
- package/dist/esm/chunks/repository-DyxknzvE.js +1 -0
- package/dist/esm/chunks/write-sparse-checkout-BwHbNKNS.js +1 -0
- package/dist/esm/commands/index.js +1 -2
- package/dist/esm/index.browser.js +1 -2
- package/dist/esm/index.default.js +1 -2
- package/dist/esm/index.js +1 -2
- package/dist/esm/index.node.js +1 -2
- package/dist/esm/operators/index.js +0 -1
- package/dist/esm/primitives/index.js +1 -2
- package/dist/esm/transport/index.js +0 -1
- package/dist/types/adapters/browser/index.d.cts +5 -3
- package/dist/types/adapters/browser/index.d.ts +5 -3
- package/dist/types/adapters/memory/index.d.cts +31 -4
- package/dist/types/adapters/memory/index.d.ts +31 -4
- package/dist/types/adapters/node/index.d.cts +146 -40
- package/dist/types/adapters/node/index.d.ts +146 -40
- package/dist/types/chunks/{context-YDw6qicq.d.cts → context-CF1YF2S8.d.cts} +165 -6
- package/dist/types/chunks/{context-CCL0_F8R.d.ts → context-sIhhtk2u.d.ts} +165 -6
- package/dist/types/chunks/{http-transport--_NdQOiw.d.cts → http-transport-DirKfK2S.d.cts} +1 -1
- package/dist/types/chunks/{http-transport--_NdQOiw.d.ts → http-transport-DirKfK2S.d.ts} +1 -1
- package/dist/types/chunks/index-B5Dps3fg.d.ts +2468 -0
- package/dist/types/chunks/index-B_A8VLaf.d.ts +1221 -0
- package/dist/types/chunks/index-Dfh8cvEs.d.cts +2468 -0
- package/dist/types/chunks/index-Dqxddhav.d.cts +1221 -0
- package/dist/types/chunks/progress-BjAKfkam.d.ts +1217 -0
- package/dist/types/chunks/progress-Ldnfb8st.d.cts +1217 -0
- package/dist/types/chunks/reflog-entry-Cqh3QrPH.d.ts +697 -0
- package/dist/types/chunks/reflog-entry-Dy-O27Dd.d.cts +697 -0
- package/dist/types/chunks/{repository-FoS_Laoy.d.ts → repository-D8QBTkEz.d.ts} +58 -20
- package/dist/types/chunks/{repository-BeifCqp0.d.cts → repository-D9YrVhcH.d.cts} +58 -20
- package/dist/types/commands/index.d.cts +4 -1259
- package/dist/types/commands/index.d.ts +4 -1259
- package/dist/types/index.browser.d.cts +7 -8
- package/dist/types/index.browser.d.ts +7 -8
- package/dist/types/index.d.cts +61 -124
- package/dist/types/index.d.ts +61 -124
- package/dist/types/index.default.d.cts +7 -8
- package/dist/types/index.default.d.ts +7 -8
- package/dist/types/index.node.d.cts +7 -8
- package/dist/types/index.node.d.ts +7 -8
- package/dist/types/primitives/index.d.cts +4 -692
- package/dist/types/primitives/index.d.ts +4 -692
- package/dist/types/transport/index.d.cts +1 -1
- package/dist/types/transport/index.d.ts +1 -1
- package/package.json +94 -28
- package/dist/cjs/adapters/browser/index.cjs.map +0 -1
- package/dist/cjs/adapters/memory/index.cjs.map +0 -1
- package/dist/cjs/adapters/node/index.cjs.map +0 -1
- package/dist/cjs/chunks/adapter-detect-CD_LcgaH.cjs +0 -2
- package/dist/cjs/chunks/adapter-detect-CD_LcgaH.cjs.map +0 -1
- package/dist/cjs/chunks/browser-http-transport-CiMRqtDS.cjs +0 -2
- package/dist/cjs/chunks/browser-http-transport-CiMRqtDS.cjs.map +0 -1
- package/dist/cjs/chunks/context-BcoAzPuU.cjs.map +0 -1
- package/dist/cjs/chunks/error-CfjFO3x_.cjs +0 -2
- package/dist/cjs/chunks/error-CfjFO3x_.cjs.map +0 -1
- package/dist/cjs/chunks/index-BWCq_5BJ.cjs +0 -2
- package/dist/cjs/chunks/index-BWCq_5BJ.cjs.map +0 -1
- package/dist/cjs/chunks/lru-cache-1OU7JhD8.cjs.map +0 -1
- package/dist/cjs/chunks/memory-http-transport-BVL6VgB-.cjs +0 -2
- package/dist/cjs/chunks/memory-http-transport-BVL6VgB-.cjs.map +0 -1
- package/dist/cjs/chunks/node-http-transport-BvfVcf02.cjs +0 -2
- package/dist/cjs/chunks/node-http-transport-BvfVcf02.cjs.map +0 -1
- package/dist/cjs/chunks/progress-CxU62NC1.cjs.map +0 -1
- package/dist/cjs/chunks/readable-stream-MTA6D0Zh.cjs.map +0 -1
- package/dist/cjs/chunks/repository-BEg2zNtx.cjs +0 -2
- package/dist/cjs/chunks/repository-BEg2zNtx.cjs.map +0 -1
- package/dist/cjs/chunks/walk-submodules-D2Sp7JEB.cjs +0 -2
- package/dist/cjs/chunks/walk-submodules-D2Sp7JEB.cjs.map +0 -1
- package/dist/cjs/commands/index.cjs.map +0 -1
- package/dist/cjs/index.browser.cjs.map +0 -1
- package/dist/cjs/index.cjs.map +0 -1
- package/dist/cjs/index.default.cjs.map +0 -1
- package/dist/cjs/index.node.cjs.map +0 -1
- package/dist/cjs/operators/index.cjs.map +0 -1
- package/dist/cjs/primitives/index.cjs.map +0 -1
- package/dist/cjs/transport/index.cjs.map +0 -1
- package/dist/esm/adapters/browser/index.js.map +0 -1
- package/dist/esm/adapters/memory/index.js.map +0 -1
- package/dist/esm/adapters/node/index.js.map +0 -1
- package/dist/esm/chunks/adapter-detect-DkZhhUhd.js +0 -2
- package/dist/esm/chunks/adapter-detect-DkZhhUhd.js.map +0 -1
- package/dist/esm/chunks/browser-http-transport-4rJkHcQu.js +0 -2
- package/dist/esm/chunks/browser-http-transport-4rJkHcQu.js.map +0 -1
- package/dist/esm/chunks/context-CumKOV7K.js.map +0 -1
- package/dist/esm/chunks/error-Dc-SRSJK.js +0 -2
- package/dist/esm/chunks/error-Dc-SRSJK.js.map +0 -1
- package/dist/esm/chunks/index-jH0UMhh-.js +0 -2
- package/dist/esm/chunks/index-jH0UMhh-.js.map +0 -1
- package/dist/esm/chunks/lru-cache-Cy7C7Lx2.js.map +0 -1
- package/dist/esm/chunks/memory-http-transport-CA1WxWBp.js +0 -2
- package/dist/esm/chunks/memory-http-transport-CA1WxWBp.js.map +0 -1
- package/dist/esm/chunks/node-http-transport-DPa2lK3T.js +0 -2
- package/dist/esm/chunks/node-http-transport-DPa2lK3T.js.map +0 -1
- package/dist/esm/chunks/progress-BZobfl7p.js.map +0 -1
- package/dist/esm/chunks/readable-stream-CGuf8k1J.js.map +0 -1
- package/dist/esm/chunks/repository-DF6ePd1x.js +0 -2
- package/dist/esm/chunks/repository-DF6ePd1x.js.map +0 -1
- package/dist/esm/chunks/walk-submodules-Dq9oGwP8.js +0 -2
- package/dist/esm/chunks/walk-submodules-Dq9oGwP8.js.map +0 -1
- package/dist/esm/commands/index.js.map +0 -1
- package/dist/esm/index.browser.js.map +0 -1
- package/dist/esm/index.default.js.map +0 -1
- package/dist/esm/index.js.map +0 -1
- package/dist/esm/index.node.js.map +0 -1
- package/dist/esm/operators/index.js.map +0 -1
- package/dist/esm/primitives/index.js.map +0 -1
- package/dist/esm/transport/index.js.map +0 -1
- package/dist/types/chunks/index-entry-DtEbVpOG.d.cts +0 -47
- package/dist/types/chunks/index-entry-UD4dvtKh.d.ts +0 -47
- package/dist/types/chunks/progress-7KKiXXfX.d.ts +0 -405
- package/dist/types/chunks/progress-By8yFaUE.d.cts +0 -405
- package/dist/types/chunks/reflog-entry-BbNnXCTC.d.cts +0 -368
- package/dist/types/chunks/reflog-entry-CSzjnZd4.d.ts +0 -368
- package/dist/types/chunks/write-tree-C3oNxOlX.d.cts +0 -196
- 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 };
|