@mhalle/vost 0.8.1

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 (51) hide show
  1. package/LICENSE +191 -0
  2. package/README.md +24 -0
  3. package/dist/batch.d.ts +82 -0
  4. package/dist/batch.js +152 -0
  5. package/dist/batch.js.map +1 -0
  6. package/dist/copy.d.ts +242 -0
  7. package/dist/copy.js +1229 -0
  8. package/dist/copy.js.map +1 -0
  9. package/dist/exclude.d.ts +68 -0
  10. package/dist/exclude.js +157 -0
  11. package/dist/exclude.js.map +1 -0
  12. package/dist/fileobj.d.ts +82 -0
  13. package/dist/fileobj.js +127 -0
  14. package/dist/fileobj.js.map +1 -0
  15. package/dist/fs.d.ts +581 -0
  16. package/dist/fs.js +1318 -0
  17. package/dist/fs.js.map +1 -0
  18. package/dist/gitstore.d.ts +74 -0
  19. package/dist/gitstore.js +131 -0
  20. package/dist/gitstore.js.map +1 -0
  21. package/dist/glob.d.ts +14 -0
  22. package/dist/glob.js +68 -0
  23. package/dist/glob.js.map +1 -0
  24. package/dist/index.d.ts +37 -0
  25. package/dist/index.js +51 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/lock.d.ts +15 -0
  28. package/dist/lock.js +71 -0
  29. package/dist/lock.js.map +1 -0
  30. package/dist/mirror.d.ts +53 -0
  31. package/dist/mirror.js +270 -0
  32. package/dist/mirror.js.map +1 -0
  33. package/dist/notes.d.ts +148 -0
  34. package/dist/notes.js +508 -0
  35. package/dist/notes.js.map +1 -0
  36. package/dist/paths.d.ts +16 -0
  37. package/dist/paths.js +44 -0
  38. package/dist/paths.js.map +1 -0
  39. package/dist/refdict.d.ts +117 -0
  40. package/dist/refdict.js +267 -0
  41. package/dist/refdict.js.map +1 -0
  42. package/dist/reflog.d.ts +33 -0
  43. package/dist/reflog.js +83 -0
  44. package/dist/reflog.js.map +1 -0
  45. package/dist/tree.d.ts +79 -0
  46. package/dist/tree.js +283 -0
  47. package/dist/tree.js.map +1 -0
  48. package/dist/types.d.ts +354 -0
  49. package/dist/types.js +302 -0
  50. package/dist/types.js.map +1 -0
  51. package/package.json +58 -0
@@ -0,0 +1,117 @@
1
+ /**
2
+ * RefDict: Map-like access to git branches or tags.
3
+ */
4
+ import { type ReflogEntry } from './types.js';
5
+ import { FS } from './fs.js';
6
+ import type { GitStore } from './gitstore.js';
7
+ /**
8
+ * Map-like access to branches or tags.
9
+ *
10
+ * `store.branches` and `store.tags` are both `RefDict` instances.
11
+ * Supports `get`, `set`, `delete`, `has`, `list`, and async iteration.
12
+ */
13
+ export declare class RefDict {
14
+ private _store;
15
+ private _prefix;
16
+ constructor(store: GitStore, prefix: string);
17
+ private get _isTags();
18
+ private get _fsModule();
19
+ private get _gitdir();
20
+ private _refName;
21
+ toString(): string;
22
+ /**
23
+ * Get a branch or tag as an FS snapshot.
24
+ *
25
+ * Branches return a writable FS; tags return a read-only FS.
26
+ *
27
+ * @param name - Branch or tag name.
28
+ * @returns FS snapshot for the ref.
29
+ * @throws {Error} If the branch or tag does not exist.
30
+ */
31
+ get(name: string): Promise<FS>;
32
+ /**
33
+ * Set or create a branch pointing to an FS snapshot's commit.
34
+ *
35
+ * The FS must belong to the same repository. Tags cannot be overwritten;
36
+ * an error is thrown if the tag already exists.
37
+ *
38
+ * @param name - Branch or tag name.
39
+ * @param fs - FS snapshot whose commit to point the ref at.
40
+ * @throws {TypeError} If fs is not an FS instance.
41
+ * @throws {Error} If the FS belongs to a different repository.
42
+ * @throws {Error} If the tag already exists (tags only).
43
+ */
44
+ set(name: string, fs: FS): Promise<void>;
45
+ /**
46
+ * Set branch to an FS snapshot and return a writable FS bound to it.
47
+ *
48
+ * Convenience method that combines `set()` and `get()`.
49
+ *
50
+ * @param name - Branch name.
51
+ * @param fs - FS snapshot to set (can be read-only).
52
+ * @returns New writable FS bound to the branch.
53
+ */
54
+ setAndGet(name: string, fs: FS): Promise<FS>;
55
+ /**
56
+ * Delete a branch or tag.
57
+ *
58
+ * @param name - Branch or tag name.
59
+ * @throws {Error} If the branch or tag does not exist.
60
+ */
61
+ delete(name: string): Promise<void>;
62
+ /**
63
+ * Check if a branch or tag exists.
64
+ *
65
+ * @param name - Branch or tag name.
66
+ * @returns True if the ref exists.
67
+ */
68
+ has(name: string): Promise<boolean>;
69
+ /**
70
+ * List all branch or tag names.
71
+ *
72
+ * @returns Array of ref names (without the refs/heads/ or refs/tags/ prefix).
73
+ */
74
+ list(): Promise<string[]>;
75
+ /**
76
+ * Async iteration over branch/tag names.
77
+ */
78
+ [Symbol.asyncIterator](): AsyncGenerator<string>;
79
+ /**
80
+ * Get the current (HEAD) branch name, or null if HEAD is dangling.
81
+ *
82
+ * Only valid for branches; throws for tags. Cheap -- does not
83
+ * construct an FS object.
84
+ *
85
+ * @returns Branch name string, or null.
86
+ * @throws {Error} If called on tags.
87
+ */
88
+ getCurrentName(): Promise<string | null>;
89
+ /**
90
+ * Get the FS for the current (HEAD) branch, or null if HEAD is dangling.
91
+ *
92
+ * Only valid for branches; throws for tags.
93
+ *
94
+ * @returns Writable FS snapshot, or null.
95
+ * @throws {Error} If called on tags.
96
+ */
97
+ getCurrent(): Promise<FS | null>;
98
+ /**
99
+ * Set the current branch (HEAD symbolic ref target).
100
+ *
101
+ * Only valid for branches; throws for tags.
102
+ *
103
+ * @param name - Branch name to set as current.
104
+ * @throws {Error} If called on tags.
105
+ * @throws {Error} If the branch does not exist.
106
+ */
107
+ setCurrent(name: string): Promise<void>;
108
+ /**
109
+ * Read reflog entries for a branch.
110
+ *
111
+ * @param name - Branch name (e.g. 'main').
112
+ * @returns List of ReflogEntry objects, newest first.
113
+ * @throws {Error} If called on tags.
114
+ * @throws {Error} If the branch does not exist.
115
+ */
116
+ reflog(name: string): Promise<ReflogEntry[]>;
117
+ }
@@ -0,0 +1,267 @@
1
+ /**
2
+ * RefDict: Map-like access to git branches or tags.
3
+ */
4
+ import git from 'isomorphic-git';
5
+ import { KeyNotFoundError, KeyExistsError } from './types.js';
6
+ import { validateRefName } from './paths.js';
7
+ import { withRepoLock } from './lock.js';
8
+ import { readReflog, writeReflogEntry, ZERO_SHA } from './reflog.js';
9
+ import { FS } from './fs.js';
10
+ /**
11
+ * Map-like access to branches or tags.
12
+ *
13
+ * `store.branches` and `store.tags` are both `RefDict` instances.
14
+ * Supports `get`, `set`, `delete`, `has`, `list`, and async iteration.
15
+ */
16
+ export class RefDict {
17
+ _store;
18
+ _prefix; // "refs/heads/" or "refs/tags/"
19
+ constructor(store, prefix) {
20
+ this._store = store;
21
+ this._prefix = prefix;
22
+ }
23
+ get _isTags() {
24
+ return this._prefix === 'refs/tags/';
25
+ }
26
+ get _fsModule() {
27
+ return this._store._fsModule;
28
+ }
29
+ get _gitdir() {
30
+ return this._store._gitdir;
31
+ }
32
+ _refName(name) {
33
+ return `${this._prefix}${name}`;
34
+ }
35
+ toString() {
36
+ const kind = this._isTags ? 'tags' : 'branches';
37
+ return `RefDict('${kind}')`;
38
+ }
39
+ /**
40
+ * Get a branch or tag as an FS snapshot.
41
+ *
42
+ * Branches return a writable FS; tags return a read-only FS.
43
+ *
44
+ * @param name - Branch or tag name.
45
+ * @returns FS snapshot for the ref.
46
+ * @throws {Error} If the branch or tag does not exist.
47
+ */
48
+ async get(name) {
49
+ const refName = this._refName(name);
50
+ let oid;
51
+ try {
52
+ oid = await git.resolveRef({ fs: this._fsModule, gitdir: this._gitdir, ref: refName });
53
+ }
54
+ catch {
55
+ throw new KeyNotFoundError(`Key not found: ${name}`);
56
+ }
57
+ if (this._isTags) {
58
+ // Tags may point to annotated tag objects — peel to commit
59
+ const { commit } = await git.readCommit({
60
+ fs: this._fsModule,
61
+ gitdir: this._gitdir,
62
+ oid,
63
+ });
64
+ // oid is already the commit oid after resolveRef for lightweight tags.
65
+ // For annotated tags, readCommit may fail — try reading as tag first.
66
+ return FS._fromCommit(this._store, oid, name, false);
67
+ }
68
+ return FS._fromCommit(this._store, oid, name, true);
69
+ }
70
+ /**
71
+ * Set or create a branch pointing to an FS snapshot's commit.
72
+ *
73
+ * The FS must belong to the same repository. Tags cannot be overwritten;
74
+ * an error is thrown if the tag already exists.
75
+ *
76
+ * @param name - Branch or tag name.
77
+ * @param fs - FS snapshot whose commit to point the ref at.
78
+ * @throws {TypeError} If fs is not an FS instance.
79
+ * @throws {Error} If the FS belongs to a different repository.
80
+ * @throws {Error} If the tag already exists (tags only).
81
+ */
82
+ async set(name, fs) {
83
+ validateRefName(name);
84
+ if (!(fs instanceof FS))
85
+ throw new TypeError(`Expected FS, got ${typeof fs}`);
86
+ const selfPath = this._fsModule.realpathSync(this._gitdir);
87
+ const fsPath = this._fsModule.realpathSync(fs._gitdir);
88
+ if (selfPath !== fsPath) {
89
+ throw new Error('FS belongs to a different repository');
90
+ }
91
+ const refName = this._refName(name);
92
+ const sig = this._store._signature;
93
+ const committerStr = `${sig.name} <${sig.email}>`;
94
+ await withRepoLock(this._fsModule, this._gitdir, async () => {
95
+ let exists = false;
96
+ try {
97
+ await git.resolveRef({ fs: this._fsModule, gitdir: this._gitdir, ref: refName });
98
+ exists = true;
99
+ }
100
+ catch { /* not found */ }
101
+ if (exists && this._isTags) {
102
+ throw new KeyExistsError(`Tag '${name}' already exists`);
103
+ }
104
+ const oldSha = exists
105
+ ? await git.resolveRef({ fs: this._fsModule, gitdir: this._gitdir, ref: refName }).catch(() => ZERO_SHA)
106
+ : ZERO_SHA;
107
+ await git.writeRef({
108
+ fs: this._fsModule,
109
+ gitdir: this._gitdir,
110
+ ref: refName,
111
+ value: fs._commitOid,
112
+ force: true,
113
+ });
114
+ // Write reflog
115
+ const msg = exists
116
+ ? `branch: set to ${(await fs.getMessage()).split('\n')[0]}`
117
+ : `branch: Created from ${(await fs.getMessage()).split('\n')[0]}`;
118
+ await writeReflogEntry(this._fsModule, this._gitdir, refName, typeof oldSha === 'string' ? oldSha : ZERO_SHA, fs._commitOid, committerStr, msg);
119
+ });
120
+ }
121
+ /**
122
+ * Set branch to an FS snapshot and return a writable FS bound to it.
123
+ *
124
+ * Convenience method that combines `set()` and `get()`.
125
+ *
126
+ * @param name - Branch name.
127
+ * @param fs - FS snapshot to set (can be read-only).
128
+ * @returns New writable FS bound to the branch.
129
+ */
130
+ async setAndGet(name, fs) {
131
+ await this.set(name, fs);
132
+ return this.get(name);
133
+ }
134
+ /**
135
+ * Delete a branch or tag.
136
+ *
137
+ * @param name - Branch or tag name.
138
+ * @throws {Error} If the branch or tag does not exist.
139
+ */
140
+ async delete(name) {
141
+ const refName = this._refName(name);
142
+ await withRepoLock(this._fsModule, this._gitdir, async () => {
143
+ try {
144
+ await git.resolveRef({ fs: this._fsModule, gitdir: this._gitdir, ref: refName });
145
+ }
146
+ catch {
147
+ throw new KeyNotFoundError(`Key not found: ${name}`);
148
+ }
149
+ await git.deleteRef({ fs: this._fsModule, gitdir: this._gitdir, ref: refName });
150
+ });
151
+ }
152
+ /**
153
+ * Check if a branch or tag exists.
154
+ *
155
+ * @param name - Branch or tag name.
156
+ * @returns True if the ref exists.
157
+ */
158
+ async has(name) {
159
+ const refName = this._refName(name);
160
+ try {
161
+ await git.resolveRef({ fs: this._fsModule, gitdir: this._gitdir, ref: refName });
162
+ return true;
163
+ }
164
+ catch {
165
+ return false;
166
+ }
167
+ }
168
+ /**
169
+ * List all branch or tag names.
170
+ *
171
+ * @returns Array of ref names (without the refs/heads/ or refs/tags/ prefix).
172
+ */
173
+ async list() {
174
+ if (this._isTags) {
175
+ return git.listTags({ fs: this._fsModule, gitdir: this._gitdir });
176
+ }
177
+ return git.listBranches({ fs: this._fsModule, gitdir: this._gitdir });
178
+ }
179
+ /**
180
+ * Async iteration over branch/tag names.
181
+ */
182
+ async *[Symbol.asyncIterator]() {
183
+ const names = await this.list();
184
+ for (const name of names) {
185
+ yield name;
186
+ }
187
+ }
188
+ /**
189
+ * Get the current (HEAD) branch name, or null if HEAD is dangling.
190
+ *
191
+ * Only valid for branches; throws for tags. Cheap -- does not
192
+ * construct an FS object.
193
+ *
194
+ * @returns Branch name string, or null.
195
+ * @throws {Error} If called on tags.
196
+ */
197
+ async getCurrentName() {
198
+ if (this._isTags)
199
+ throw new Error('Tags do not have a current branch');
200
+ const branch = await git.currentBranch({
201
+ fs: this._fsModule,
202
+ gitdir: this._gitdir,
203
+ fullname: false,
204
+ });
205
+ return branch ?? null;
206
+ }
207
+ /**
208
+ * Get the FS for the current (HEAD) branch, or null if HEAD is dangling.
209
+ *
210
+ * Only valid for branches; throws for tags.
211
+ *
212
+ * @returns Writable FS snapshot, or null.
213
+ * @throws {Error} If called on tags.
214
+ */
215
+ async getCurrent() {
216
+ if (this._isTags)
217
+ throw new Error('Tags do not have a current branch');
218
+ const name = await this.getCurrentName();
219
+ if (!name)
220
+ return null;
221
+ try {
222
+ return await this.get(name);
223
+ }
224
+ catch {
225
+ return null;
226
+ }
227
+ }
228
+ /**
229
+ * Set the current branch (HEAD symbolic ref target).
230
+ *
231
+ * Only valid for branches; throws for tags.
232
+ *
233
+ * @param name - Branch name to set as current.
234
+ * @throws {Error} If called on tags.
235
+ * @throws {Error} If the branch does not exist.
236
+ */
237
+ async setCurrent(name) {
238
+ if (this._isTags)
239
+ throw new Error('Tags do not have a current branch');
240
+ if (!(await this.has(name)))
241
+ throw new Error(`Branch not found: '${name}'`);
242
+ await git.writeRef({
243
+ fs: this._fsModule,
244
+ gitdir: this._gitdir,
245
+ ref: 'HEAD',
246
+ value: `refs/heads/${name}`,
247
+ symbolic: true,
248
+ force: true,
249
+ });
250
+ }
251
+ /**
252
+ * Read reflog entries for a branch.
253
+ *
254
+ * @param name - Branch name (e.g. 'main').
255
+ * @returns List of ReflogEntry objects, newest first.
256
+ * @throws {Error} If called on tags.
257
+ * @throws {Error} If the branch does not exist.
258
+ */
259
+ async reflog(name) {
260
+ if (this._isTags)
261
+ throw new Error('Tags do not have reflog');
262
+ if (!(await this.has(name)))
263
+ throw new KeyNotFoundError(`Key not found: ${name}`);
264
+ return readReflog(this._fsModule, this._gitdir, name);
265
+ }
266
+ }
267
+ //# sourceMappingURL=refdict.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"refdict.js","sourceRoot":"","sources":["../src/refdict.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Reflog read/write using direct filesystem access.
3
+ *
4
+ * Git reflog format (one line per entry):
5
+ * <old-sha> <new-sha> <committer> <timestamp> <tz>\t<message>\n
6
+ */
7
+ import type { FsModule, ReflogEntry } from './types.js';
8
+ /** The all-zeros SHA used for newly-created refs in reflog entries. */
9
+ declare const ZERO_SHA = "0000000000000000000000000000000000000000";
10
+ /**
11
+ * Read reflog entries for a branch.
12
+ * Returns entries in chronological order (oldest first).
13
+ *
14
+ * @param fsModule - Node.js-compatible fs module.
15
+ * @param gitdir - Path to the bare git repository.
16
+ * @param branchName - Branch name (e.g. "main").
17
+ * @returns Array of {@link ReflogEntry} objects.
18
+ * @throws Error if no reflog file exists for the branch.
19
+ */
20
+ export declare function readReflog(fsModule: FsModule, gitdir: string, branchName: string): Promise<ReflogEntry[]>;
21
+ /**
22
+ * Append a reflog entry for a ref update.
23
+ *
24
+ * @param fsModule - Node.js-compatible fs module.
25
+ * @param gitdir - Path to the bare git repository.
26
+ * @param refName - Full ref name (e.g. "refs/heads/main").
27
+ * @param oldSha - Previous 40-char hex commit SHA (ZERO_SHA for new refs).
28
+ * @param newSha - New 40-char hex commit SHA.
29
+ * @param committer - Identity string (e.g. "vost \<vost@localhost\>").
30
+ * @param message - Reflog message (e.g. "commit: + file.txt").
31
+ */
32
+ export declare function writeReflogEntry(fsModule: FsModule, gitdir: string, refName: string, oldSha: string, newSha: string, committer: string, message: string): Promise<void>;
33
+ export { ZERO_SHA };
package/dist/reflog.js ADDED
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Reflog read/write using direct filesystem access.
3
+ *
4
+ * Git reflog format (one line per entry):
5
+ * <old-sha> <new-sha> <committer> <timestamp> <tz>\t<message>\n
6
+ */
7
+ /** The all-zeros SHA used for newly-created refs in reflog entries. */
8
+ const ZERO_SHA = '0000000000000000000000000000000000000000';
9
+ /**
10
+ * Read reflog entries for a branch.
11
+ * Returns entries in chronological order (oldest first).
12
+ *
13
+ * @param fsModule - Node.js-compatible fs module.
14
+ * @param gitdir - Path to the bare git repository.
15
+ * @param branchName - Branch name (e.g. "main").
16
+ * @returns Array of {@link ReflogEntry} objects.
17
+ * @throws Error if no reflog file exists for the branch.
18
+ */
19
+ export async function readReflog(fsModule, gitdir, branchName) {
20
+ const reflogPath = `${gitdir}/logs/refs/heads/${branchName}`;
21
+ let data;
22
+ try {
23
+ const raw = await fsModule.promises.readFile(reflogPath, { encoding: 'utf8' });
24
+ data = typeof raw === 'string' ? raw : new TextDecoder().decode(raw);
25
+ }
26
+ catch (err) {
27
+ if (err?.code === 'ENOENT') {
28
+ throw new Error(`No reflog found for branch '${branchName}'`);
29
+ }
30
+ throw err;
31
+ }
32
+ const entries = [];
33
+ for (const line of data.split('\n')) {
34
+ if (!line.trim())
35
+ continue;
36
+ // Format: <old> <new> <committer> <timestamp> <tz>\t<message>
37
+ const tabIdx = line.indexOf('\t');
38
+ const message = tabIdx >= 0 ? line.slice(tabIdx + 1) : '';
39
+ const header = tabIdx >= 0 ? line.slice(0, tabIdx) : line;
40
+ // Parse header: old_sha new_sha committer_name <email> timestamp tz
41
+ const oldSha = header.slice(0, 40);
42
+ const newSha = header.slice(41, 81);
43
+ const rest = header.slice(82); // "Name <email> timestamp tz"
44
+ // Extract timestamp: find the last two space-separated tokens
45
+ const parts = rest.split(' ');
46
+ const tz = parts.pop() ?? '+0000';
47
+ const timestampStr = parts.pop() ?? '0';
48
+ const committer = parts.join(' ');
49
+ entries.push({
50
+ oldSha,
51
+ newSha,
52
+ committer,
53
+ timestamp: parseInt(timestampStr, 10),
54
+ message,
55
+ });
56
+ }
57
+ return entries;
58
+ }
59
+ /**
60
+ * Append a reflog entry for a ref update.
61
+ *
62
+ * @param fsModule - Node.js-compatible fs module.
63
+ * @param gitdir - Path to the bare git repository.
64
+ * @param refName - Full ref name (e.g. "refs/heads/main").
65
+ * @param oldSha - Previous 40-char hex commit SHA (ZERO_SHA for new refs).
66
+ * @param newSha - New 40-char hex commit SHA.
67
+ * @param committer - Identity string (e.g. "vost \<vost@localhost\>").
68
+ * @param message - Reflog message (e.g. "commit: + file.txt").
69
+ */
70
+ export async function writeReflogEntry(fsModule, gitdir, refName, oldSha, newSha, committer, message) {
71
+ // Construct reflog path: refs/heads/main → logs/refs/heads/main
72
+ const reflogPath = `${gitdir}/logs/${refName}`;
73
+ // Create parent directories
74
+ const parentDir = reflogPath.slice(0, reflogPath.lastIndexOf('/'));
75
+ await fsModule.promises.mkdir(parentDir, { recursive: true });
76
+ // Format entry
77
+ const timestamp = Math.floor(Date.now() / 1000);
78
+ const line = `${oldSha} ${newSha} ${committer} ${timestamp} +0000\t${message}\n`;
79
+ // Append
80
+ await fsModule.promises.appendFile(reflogPath, line);
81
+ }
82
+ export { ZERO_SHA };
83
+ //# sourceMappingURL=reflog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reflog.js","sourceRoot":"","sources":["../src/reflog.ts"],"names":[],"mappings":"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"}
package/dist/tree.d.ts ADDED
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Low-level tree manipulation for vost.
3
+ *
4
+ * Provides recursive tree rebuild and path-based read helpers
5
+ * on top of isomorphic-git's readTree/writeTree/writeBlob.
6
+ */
7
+ import { type FsModule, type WalkEntry } from './types.js';
8
+ export interface TreeWrite {
9
+ /** Raw blob data (will create blob). Mutually exclusive with oid. */
10
+ data?: Uint8Array;
11
+ /** Existing blob OID (skip blob creation). Mutually exclusive with data. */
12
+ oid?: string;
13
+ /** Git mode string (default: '100644'). */
14
+ mode: string;
15
+ }
16
+ /**
17
+ * Detect the git filemode for a local file by checking its executable bit.
18
+ *
19
+ * @param fsModule - Node.js-compatible fs module.
20
+ * @param localPath - Path to the local file.
21
+ * @returns MODE_BLOB_EXEC if executable, MODE_BLOB otherwise.
22
+ * @throws IsADirectoryError if the path is a directory.
23
+ */
24
+ export declare function modeFromDisk(fsModule: FsModule, localPath: string): Promise<string>;
25
+ interface TreeEntryResult {
26
+ oid: string;
27
+ mode: string;
28
+ type: string;
29
+ path: string;
30
+ }
31
+ /**
32
+ * Walk through tree to the object at the given path.
33
+ * Returns the final tree entry.
34
+ */
35
+ export declare function walkTo(fsModule: FsModule, gitdir: string, treeOid: string, path: string): Promise<TreeEntryResult>;
36
+ /**
37
+ * Return { oid, mode } of the entry at path, or null if missing.
38
+ */
39
+ export declare function entryAtPath(fsModule: FsModule, gitdir: string, treeOid: string, path: string): Promise<{
40
+ oid: string;
41
+ mode: string;
42
+ } | null>;
43
+ /**
44
+ * Read a blob at the given path in the tree.
45
+ */
46
+ export declare function readBlobAtPath(fsModule: FsModule, gitdir: string, treeOid: string, path: string): Promise<Uint8Array>;
47
+ /**
48
+ * List entry names at the given path (or root if path is null/empty).
49
+ */
50
+ export declare function listTreeAtPath(fsModule: FsModule, gitdir: string, treeOid: string, path?: string | null): Promise<string[]>;
51
+ /**
52
+ * List full entries at the given path (or root if path is null/empty).
53
+ */
54
+ export declare function listEntriesAtPath(fsModule: FsModule, gitdir: string, treeOid: string, path?: string | null): Promise<WalkEntry[]>;
55
+ /**
56
+ * Walk the tree recursively, yielding (dirpath, dirnames, fileEntries).
57
+ */
58
+ export declare function walkTree(fsModule: FsModule, gitdir: string, treeOid: string, prefix?: string): AsyncGenerator<[string, string[], WalkEntry[]]>;
59
+ /**
60
+ * Check if a path exists in the tree.
61
+ */
62
+ export declare function existsAtPath(fsModule: FsModule, gitdir: string, treeOid: string, path: string): Promise<boolean>;
63
+ /**
64
+ * Count the number of immediate subdirectories in a tree (for stat nlink).
65
+ *
66
+ * @param fsModule - Node.js-compatible fs module.
67
+ * @param gitdir - Path to the bare git repository.
68
+ * @param treeOid - 40-char hex SHA of the tree object.
69
+ * @returns Number of subdirectory entries in the tree.
70
+ */
71
+ export declare function countSubdirs(fsModule: FsModule, gitdir: string, treeOid: string): Promise<number>;
72
+ /**
73
+ * Rebuild a tree with writes and removes applied.
74
+ *
75
+ * Only the ancestor chain from changed leaves to root is rebuilt.
76
+ * Sibling subtrees are shared by hash reference.
77
+ */
78
+ export declare function rebuildTree(fsModule: FsModule, gitdir: string, baseTreeOid: string | null, writes: Map<string, TreeWrite>, removes: Set<string>): Promise<string>;
79
+ export {};