@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.
- package/LICENSE +191 -0
- package/README.md +24 -0
- package/dist/batch.d.ts +82 -0
- package/dist/batch.js +152 -0
- package/dist/batch.js.map +1 -0
- package/dist/copy.d.ts +242 -0
- package/dist/copy.js +1229 -0
- package/dist/copy.js.map +1 -0
- package/dist/exclude.d.ts +68 -0
- package/dist/exclude.js +157 -0
- package/dist/exclude.js.map +1 -0
- package/dist/fileobj.d.ts +82 -0
- package/dist/fileobj.js +127 -0
- package/dist/fileobj.js.map +1 -0
- package/dist/fs.d.ts +581 -0
- package/dist/fs.js +1318 -0
- package/dist/fs.js.map +1 -0
- package/dist/gitstore.d.ts +74 -0
- package/dist/gitstore.js +131 -0
- package/dist/gitstore.js.map +1 -0
- package/dist/glob.d.ts +14 -0
- package/dist/glob.js +68 -0
- package/dist/glob.js.map +1 -0
- package/dist/index.d.ts +37 -0
- package/dist/index.js +51 -0
- package/dist/index.js.map +1 -0
- package/dist/lock.d.ts +15 -0
- package/dist/lock.js +71 -0
- package/dist/lock.js.map +1 -0
- package/dist/mirror.d.ts +53 -0
- package/dist/mirror.js +270 -0
- package/dist/mirror.js.map +1 -0
- package/dist/notes.d.ts +148 -0
- package/dist/notes.js +508 -0
- package/dist/notes.js.map +1 -0
- package/dist/paths.d.ts +16 -0
- package/dist/paths.js +44 -0
- package/dist/paths.js.map +1 -0
- package/dist/refdict.d.ts +117 -0
- package/dist/refdict.js +267 -0
- package/dist/refdict.js.map +1 -0
- package/dist/reflog.d.ts +33 -0
- package/dist/reflog.js +83 -0
- package/dist/reflog.js.map +1 -0
- package/dist/tree.d.ts +79 -0
- package/dist/tree.js +283 -0
- package/dist/tree.js.map +1 -0
- package/dist/types.d.ts +354 -0
- package/dist/types.js +302 -0
- package/dist/types.js.map +1 -0
- package/package.json +58 -0
package/dist/notes.js
ADDED
|
@@ -0,0 +1,508 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Git notes support: per-namespace mapping of commit hashes to note text.
|
|
3
|
+
*
|
|
4
|
+
* Notes live at `refs/notes/<namespace>`, mapping commit hashes to UTF-8
|
|
5
|
+
* text blobs. Reads handle both flat (40-char filename) and 2/38 fanout
|
|
6
|
+
* layouts. Writes always use flat. Each mutation creates a commit on the
|
|
7
|
+
* namespace's notes ref chain, or batch() defers to a single commit.
|
|
8
|
+
*/
|
|
9
|
+
import git from 'isomorphic-git';
|
|
10
|
+
import { MODE_BLOB, MODE_TREE, GitStoreError, KeyNotFoundError, BatchClosedError } from './types.js';
|
|
11
|
+
import { withRepoLock } from './lock.js';
|
|
12
|
+
const HEX40_RE = /^[0-9a-f]{40}$/;
|
|
13
|
+
function validateHash(h) {
|
|
14
|
+
if (typeof h !== 'string' || !HEX40_RE.test(h)) {
|
|
15
|
+
throw new GitStoreError(`Invalid commit hash: '${h}' (must be 40-char lowercase hex)`);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
// -----------------------------------------------------------------------
|
|
19
|
+
// NoteNamespace
|
|
20
|
+
// -----------------------------------------------------------------------
|
|
21
|
+
/**
|
|
22
|
+
* One git notes namespace, backed by `refs/notes/<name>`.
|
|
23
|
+
*
|
|
24
|
+
* Maps 40-char hex commit hashes to UTF-8 note text.
|
|
25
|
+
* Supports `get`, `set`, `delete`, `has`, `list`, and `batch()`.
|
|
26
|
+
*/
|
|
27
|
+
export class NoteNamespace {
|
|
28
|
+
/** @internal */ _store;
|
|
29
|
+
/** @internal */ _namespace;
|
|
30
|
+
/** @internal */ _ref;
|
|
31
|
+
constructor(store, namespace) {
|
|
32
|
+
this._store = store;
|
|
33
|
+
this._namespace = namespace;
|
|
34
|
+
this._ref = `refs/notes/${namespace}`;
|
|
35
|
+
}
|
|
36
|
+
toString() {
|
|
37
|
+
return `NoteNamespace('${this._namespace}')`;
|
|
38
|
+
}
|
|
39
|
+
// -- internal helpers --------------------------------------------------
|
|
40
|
+
get _fs() {
|
|
41
|
+
return this._store._fsModule;
|
|
42
|
+
}
|
|
43
|
+
get _gitdir() {
|
|
44
|
+
return this._store._gitdir;
|
|
45
|
+
}
|
|
46
|
+
/** Resolve the notes ref to a commit OID, or null. */
|
|
47
|
+
async _tipOid() {
|
|
48
|
+
try {
|
|
49
|
+
return await git.resolveRef({
|
|
50
|
+
fs: this._fs,
|
|
51
|
+
gitdir: this._gitdir,
|
|
52
|
+
ref: this._ref,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/** @internal Read the tree OID from the tip commit, or null. */
|
|
60
|
+
async _treeOid() {
|
|
61
|
+
const tip = await this._tipOid();
|
|
62
|
+
if (tip === null)
|
|
63
|
+
return null;
|
|
64
|
+
const { commit } = await git.readCommit({
|
|
65
|
+
fs: this._fs,
|
|
66
|
+
gitdir: this._gitdir,
|
|
67
|
+
oid: tip,
|
|
68
|
+
});
|
|
69
|
+
return commit.tree;
|
|
70
|
+
}
|
|
71
|
+
/** Find the blob OID for `hash` in a tree, handling flat and fanout. */
|
|
72
|
+
async _findNoteInTree(treeOid, hash) {
|
|
73
|
+
const entries = await git.readTree({
|
|
74
|
+
fs: this._fs,
|
|
75
|
+
gitdir: this._gitdir,
|
|
76
|
+
oid: treeOid,
|
|
77
|
+
});
|
|
78
|
+
// Try flat: entry named by full 40-char hash
|
|
79
|
+
for (const e of entries.tree) {
|
|
80
|
+
if (e.path === hash && e.mode !== MODE_TREE) {
|
|
81
|
+
return e.oid;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
// Try 2/38 fanout
|
|
85
|
+
const prefix = hash.slice(0, 2);
|
|
86
|
+
const suffix = hash.slice(2);
|
|
87
|
+
for (const e of entries.tree) {
|
|
88
|
+
if (e.path === prefix && e.mode === MODE_TREE) {
|
|
89
|
+
const sub = await git.readTree({
|
|
90
|
+
fs: this._fs,
|
|
91
|
+
gitdir: this._gitdir,
|
|
92
|
+
oid: e.oid,
|
|
93
|
+
});
|
|
94
|
+
for (const se of sub.tree) {
|
|
95
|
+
if (se.path === suffix) {
|
|
96
|
+
return se.oid;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
/** Yield all [hash, blobOid] pairs from the tree. */
|
|
104
|
+
async _iterNotes(treeOid) {
|
|
105
|
+
const result = [];
|
|
106
|
+
const entries = await git.readTree({
|
|
107
|
+
fs: this._fs,
|
|
108
|
+
gitdir: this._gitdir,
|
|
109
|
+
oid: treeOid,
|
|
110
|
+
});
|
|
111
|
+
for (const e of entries.tree) {
|
|
112
|
+
if (e.mode === MODE_TREE && e.path.length === 2) {
|
|
113
|
+
// Fanout subtree
|
|
114
|
+
const sub = await git.readTree({
|
|
115
|
+
fs: this._fs,
|
|
116
|
+
gitdir: this._gitdir,
|
|
117
|
+
oid: e.oid,
|
|
118
|
+
});
|
|
119
|
+
for (const se of sub.tree) {
|
|
120
|
+
const full = e.path + se.path;
|
|
121
|
+
if (HEX40_RE.test(full)) {
|
|
122
|
+
result.push([full, se.oid]);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
else if (HEX40_RE.test(e.path)) {
|
|
127
|
+
result.push([e.path, e.oid]);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
return result;
|
|
131
|
+
}
|
|
132
|
+
/** @internal Build a new note tree from a base tree + writes + deletes. */
|
|
133
|
+
async _buildNoteTree(baseTreeOid, writes, // hash → text
|
|
134
|
+
deletes) {
|
|
135
|
+
// Load existing tree entries
|
|
136
|
+
const treeEntries = new Map();
|
|
137
|
+
if (baseTreeOid !== null) {
|
|
138
|
+
const { tree } = await git.readTree({
|
|
139
|
+
fs: this._fs,
|
|
140
|
+
gitdir: this._gitdir,
|
|
141
|
+
oid: baseTreeOid,
|
|
142
|
+
});
|
|
143
|
+
for (const e of tree) {
|
|
144
|
+
treeEntries.set(e.path, { mode: e.mode, oid: e.oid });
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
// Process deletes
|
|
148
|
+
for (const h of deletes) {
|
|
149
|
+
let removed = false;
|
|
150
|
+
// Try flat removal
|
|
151
|
+
if (treeEntries.has(h)) {
|
|
152
|
+
const entry = treeEntries.get(h);
|
|
153
|
+
if (entry.mode !== MODE_TREE) {
|
|
154
|
+
treeEntries.delete(h);
|
|
155
|
+
removed = true;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
// Try fanout removal
|
|
159
|
+
if (!removed) {
|
|
160
|
+
const prefix = h.slice(0, 2);
|
|
161
|
+
const suffix = h.slice(2);
|
|
162
|
+
const prefixEntry = treeEntries.get(prefix);
|
|
163
|
+
if (prefixEntry && prefixEntry.mode === MODE_TREE) {
|
|
164
|
+
const sub = await git.readTree({
|
|
165
|
+
fs: this._fs,
|
|
166
|
+
gitdir: this._gitdir,
|
|
167
|
+
oid: prefixEntry.oid,
|
|
168
|
+
});
|
|
169
|
+
const subEntry = sub.tree.find((e) => e.path === suffix);
|
|
170
|
+
if (subEntry) {
|
|
171
|
+
const newSubEntries = sub.tree.filter((e) => e.path !== suffix);
|
|
172
|
+
if (newSubEntries.length === 0) {
|
|
173
|
+
treeEntries.delete(prefix);
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
const newSubOid = await git.writeTree({
|
|
177
|
+
fs: this._fs,
|
|
178
|
+
gitdir: this._gitdir,
|
|
179
|
+
tree: newSubEntries.map((e) => ({
|
|
180
|
+
mode: e.mode,
|
|
181
|
+
path: e.path,
|
|
182
|
+
oid: e.oid,
|
|
183
|
+
type: 'blob',
|
|
184
|
+
})),
|
|
185
|
+
});
|
|
186
|
+
treeEntries.set(prefix, { mode: MODE_TREE, oid: newSubOid });
|
|
187
|
+
}
|
|
188
|
+
removed = true;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
if (!removed) {
|
|
193
|
+
throw new KeyNotFoundError(`key not found: ${h}`);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
// Process writes (flat, clearing fanout if present)
|
|
197
|
+
for (const [h, text] of writes) {
|
|
198
|
+
const blobOid = await git.writeBlob({
|
|
199
|
+
fs: this._fs,
|
|
200
|
+
gitdir: this._gitdir,
|
|
201
|
+
blob: new TextEncoder().encode(text),
|
|
202
|
+
});
|
|
203
|
+
// Remove fanout entry if present
|
|
204
|
+
if (baseTreeOid !== null) {
|
|
205
|
+
const prefix = h.slice(0, 2);
|
|
206
|
+
const suffix = h.slice(2);
|
|
207
|
+
const prefixEntry = treeEntries.get(prefix);
|
|
208
|
+
if (prefixEntry && prefixEntry.mode === MODE_TREE) {
|
|
209
|
+
const sub = await git.readTree({
|
|
210
|
+
fs: this._fs,
|
|
211
|
+
gitdir: this._gitdir,
|
|
212
|
+
oid: prefixEntry.oid,
|
|
213
|
+
});
|
|
214
|
+
if (sub.tree.some((e) => e.path === suffix)) {
|
|
215
|
+
const newSubEntries = sub.tree.filter((e) => e.path !== suffix);
|
|
216
|
+
if (newSubEntries.length === 0) {
|
|
217
|
+
treeEntries.delete(prefix);
|
|
218
|
+
}
|
|
219
|
+
else {
|
|
220
|
+
const newSubOid = await git.writeTree({
|
|
221
|
+
fs: this._fs,
|
|
222
|
+
gitdir: this._gitdir,
|
|
223
|
+
tree: newSubEntries.map((e) => ({
|
|
224
|
+
mode: e.mode,
|
|
225
|
+
path: e.path,
|
|
226
|
+
oid: e.oid,
|
|
227
|
+
type: 'blob',
|
|
228
|
+
})),
|
|
229
|
+
});
|
|
230
|
+
treeEntries.set(prefix, { mode: MODE_TREE, oid: newSubOid });
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
// Write flat entry
|
|
236
|
+
treeEntries.set(h, { mode: MODE_BLOB, oid: blobOid });
|
|
237
|
+
}
|
|
238
|
+
// Write final tree
|
|
239
|
+
const entries = Array.from(treeEntries.entries())
|
|
240
|
+
.sort(([a], [b]) => a.localeCompare(b))
|
|
241
|
+
.map(([path, { mode, oid }]) => ({
|
|
242
|
+
mode,
|
|
243
|
+
path,
|
|
244
|
+
oid,
|
|
245
|
+
type: mode === MODE_TREE ? 'tree' : 'blob',
|
|
246
|
+
}));
|
|
247
|
+
return await git.writeTree({
|
|
248
|
+
fs: this._fs,
|
|
249
|
+
gitdir: this._gitdir,
|
|
250
|
+
tree: entries,
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
/** @internal Commit a new tree to the notes ref under repo lock. */
|
|
254
|
+
async _commitNoteTree(newTreeOid, message) {
|
|
255
|
+
await withRepoLock(this._fs, this._gitdir, async () => {
|
|
256
|
+
// Re-read tip inside lock
|
|
257
|
+
let parents;
|
|
258
|
+
try {
|
|
259
|
+
const tip = await git.resolveRef({
|
|
260
|
+
fs: this._fs,
|
|
261
|
+
gitdir: this._gitdir,
|
|
262
|
+
ref: this._ref,
|
|
263
|
+
});
|
|
264
|
+
parents = [tip];
|
|
265
|
+
}
|
|
266
|
+
catch {
|
|
267
|
+
parents = [];
|
|
268
|
+
}
|
|
269
|
+
const now = Math.floor(Date.now() / 1000);
|
|
270
|
+
const sig = this._store._signature;
|
|
271
|
+
const commitOid = await git.writeCommit({
|
|
272
|
+
fs: this._fs,
|
|
273
|
+
gitdir: this._gitdir,
|
|
274
|
+
commit: {
|
|
275
|
+
message: `${message}\n`,
|
|
276
|
+
tree: newTreeOid,
|
|
277
|
+
parent: parents,
|
|
278
|
+
author: { name: sig.name, email: sig.email, timestamp: now, timezoneOffset: 0 },
|
|
279
|
+
committer: { name: sig.name, email: sig.email, timestamp: now, timezoneOffset: 0 },
|
|
280
|
+
},
|
|
281
|
+
});
|
|
282
|
+
await git.writeRef({
|
|
283
|
+
fs: this._fs,
|
|
284
|
+
gitdir: this._gitdir,
|
|
285
|
+
ref: this._ref,
|
|
286
|
+
value: commitOid,
|
|
287
|
+
force: true,
|
|
288
|
+
});
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
// -- public API --------------------------------------------------------
|
|
292
|
+
/**
|
|
293
|
+
* Get the note text for a commit hash.
|
|
294
|
+
*
|
|
295
|
+
* @param hash - 40-char lowercase hex commit hash.
|
|
296
|
+
* @returns The note text (UTF-8).
|
|
297
|
+
* @throws {GitStoreError} If no note exists for the hash.
|
|
298
|
+
*/
|
|
299
|
+
async get(hash) {
|
|
300
|
+
validateHash(hash);
|
|
301
|
+
const treeOid = await this._treeOid();
|
|
302
|
+
if (treeOid === null) {
|
|
303
|
+
throw new KeyNotFoundError(`key not found: ${hash}`);
|
|
304
|
+
}
|
|
305
|
+
const blobOid = await this._findNoteInTree(treeOid, hash);
|
|
306
|
+
if (blobOid === null) {
|
|
307
|
+
throw new KeyNotFoundError(`key not found: ${hash}`);
|
|
308
|
+
}
|
|
309
|
+
const { blob } = await git.readBlob({
|
|
310
|
+
fs: this._fs,
|
|
311
|
+
gitdir: this._gitdir,
|
|
312
|
+
oid: blobOid,
|
|
313
|
+
});
|
|
314
|
+
return new TextDecoder().decode(blob);
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* Set or overwrite the note text for a commit hash.
|
|
318
|
+
*
|
|
319
|
+
* Creates a commit on the namespace's notes ref.
|
|
320
|
+
*
|
|
321
|
+
* @param hash - 40-char lowercase hex commit hash.
|
|
322
|
+
* @param text - Note text (UTF-8 string).
|
|
323
|
+
*/
|
|
324
|
+
async set(hash, text) {
|
|
325
|
+
validateHash(hash);
|
|
326
|
+
const writes = new Map();
|
|
327
|
+
writes.set(hash, text);
|
|
328
|
+
const treeOid = await this._treeOid();
|
|
329
|
+
const newTreeOid = await this._buildNoteTree(treeOid, writes, new Set());
|
|
330
|
+
await this._commitNoteTree(newTreeOid, `Notes added by 'git notes' on ${hash.slice(0, 7)}`);
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* Delete the note for a commit hash.
|
|
334
|
+
*
|
|
335
|
+
* @param hash - 40-char lowercase hex commit hash.
|
|
336
|
+
* @throws {GitStoreError} If no note exists for the hash.
|
|
337
|
+
*/
|
|
338
|
+
async delete(hash) {
|
|
339
|
+
validateHash(hash);
|
|
340
|
+
const treeOid = await this._treeOid();
|
|
341
|
+
if (treeOid === null) {
|
|
342
|
+
throw new KeyNotFoundError(`key not found: ${hash}`);
|
|
343
|
+
}
|
|
344
|
+
const deletes = new Set();
|
|
345
|
+
deletes.add(hash);
|
|
346
|
+
const newTreeOid = await this._buildNoteTree(treeOid, new Map(), deletes);
|
|
347
|
+
await this._commitNoteTree(newTreeOid, `Notes removed by 'git notes' on ${hash.slice(0, 7)}`);
|
|
348
|
+
}
|
|
349
|
+
/**
|
|
350
|
+
* Check if a note exists for a commit hash.
|
|
351
|
+
*
|
|
352
|
+
* @param hash - 40-char lowercase hex commit hash.
|
|
353
|
+
* @returns True if a note exists.
|
|
354
|
+
*/
|
|
355
|
+
async has(hash) {
|
|
356
|
+
validateHash(hash);
|
|
357
|
+
const treeOid = await this._treeOid();
|
|
358
|
+
if (treeOid === null)
|
|
359
|
+
return false;
|
|
360
|
+
return (await this._findNoteInTree(treeOid, hash)) !== null;
|
|
361
|
+
}
|
|
362
|
+
/**
|
|
363
|
+
* List all commit hashes that have notes in this namespace.
|
|
364
|
+
*
|
|
365
|
+
* @returns Array of 40-char hex commit hashes.
|
|
366
|
+
*/
|
|
367
|
+
async list() {
|
|
368
|
+
const treeOid = await this._treeOid();
|
|
369
|
+
if (treeOid === null)
|
|
370
|
+
return [];
|
|
371
|
+
const notes = await this._iterNotes(treeOid);
|
|
372
|
+
return notes.map(([h]) => h);
|
|
373
|
+
}
|
|
374
|
+
/** Return the number of notes in this namespace. */
|
|
375
|
+
async size() {
|
|
376
|
+
const treeOid = await this._treeOid();
|
|
377
|
+
if (treeOid === null)
|
|
378
|
+
return 0;
|
|
379
|
+
const notes = await this._iterNotes(treeOid);
|
|
380
|
+
return notes.length;
|
|
381
|
+
}
|
|
382
|
+
/**
|
|
383
|
+
* Get the note for the current HEAD commit.
|
|
384
|
+
*
|
|
385
|
+
* @returns The note text.
|
|
386
|
+
* @throws {GitStoreError} If HEAD is dangling or no note exists.
|
|
387
|
+
*/
|
|
388
|
+
async getForCurrentBranch() {
|
|
389
|
+
const current = await this._store.branches.getCurrent();
|
|
390
|
+
if (current === null) {
|
|
391
|
+
throw new GitStoreError('HEAD is dangling — no current branch');
|
|
392
|
+
}
|
|
393
|
+
return this.get(current.commitHash);
|
|
394
|
+
}
|
|
395
|
+
/**
|
|
396
|
+
* Set the note for the current HEAD commit.
|
|
397
|
+
*
|
|
398
|
+
* @param text - Note text (UTF-8 string).
|
|
399
|
+
* @throws {GitStoreError} If HEAD is dangling.
|
|
400
|
+
*/
|
|
401
|
+
async setForCurrentBranch(text) {
|
|
402
|
+
const current = await this._store.branches.getCurrent();
|
|
403
|
+
if (current === null) {
|
|
404
|
+
throw new GitStoreError('HEAD is dangling — no current branch');
|
|
405
|
+
}
|
|
406
|
+
return this.set(current.commitHash, text);
|
|
407
|
+
}
|
|
408
|
+
/**
|
|
409
|
+
* Return a NotesBatch that collects writes/deletes and applies them
|
|
410
|
+
* in a single commit when `commit()` is called.
|
|
411
|
+
*
|
|
412
|
+
* @returns A new {@link NotesBatch} instance.
|
|
413
|
+
*/
|
|
414
|
+
batch() {
|
|
415
|
+
return new NotesBatch(this);
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
// -----------------------------------------------------------------------
|
|
419
|
+
// NotesBatch
|
|
420
|
+
// -----------------------------------------------------------------------
|
|
421
|
+
/**
|
|
422
|
+
* Collects note writes and deletes, applying them in one commit.
|
|
423
|
+
*
|
|
424
|
+
* Call `set()` and `delete()` to stage changes, then `commit()` to flush.
|
|
425
|
+
*/
|
|
426
|
+
export class NotesBatch {
|
|
427
|
+
_ns;
|
|
428
|
+
_writes = new Map();
|
|
429
|
+
_deletes = new Set();
|
|
430
|
+
_closed = false;
|
|
431
|
+
constructor(ns) {
|
|
432
|
+
this._ns = ns;
|
|
433
|
+
}
|
|
434
|
+
/**
|
|
435
|
+
* Stage a note write.
|
|
436
|
+
*
|
|
437
|
+
* @param hash - 40-char lowercase hex commit hash.
|
|
438
|
+
* @param text - Note text (UTF-8 string).
|
|
439
|
+
*/
|
|
440
|
+
async set(hash, text) {
|
|
441
|
+
if (this._closed)
|
|
442
|
+
throw new BatchClosedError('Batch is closed');
|
|
443
|
+
validateHash(hash);
|
|
444
|
+
this._deletes.delete(hash);
|
|
445
|
+
this._writes.set(hash, text);
|
|
446
|
+
}
|
|
447
|
+
/**
|
|
448
|
+
* Stage a note deletion.
|
|
449
|
+
*
|
|
450
|
+
* @param hash - 40-char lowercase hex commit hash.
|
|
451
|
+
*/
|
|
452
|
+
delete(hash) {
|
|
453
|
+
if (this._closed)
|
|
454
|
+
throw new BatchClosedError('Batch is closed');
|
|
455
|
+
validateHash(hash);
|
|
456
|
+
this._writes.delete(hash);
|
|
457
|
+
this._deletes.add(hash);
|
|
458
|
+
}
|
|
459
|
+
/**
|
|
460
|
+
* Commit all staged writes and deletes in a single commit.
|
|
461
|
+
*
|
|
462
|
+
* After calling this the batch is closed and no further changes are allowed.
|
|
463
|
+
*/
|
|
464
|
+
async commit() {
|
|
465
|
+
if (this._closed)
|
|
466
|
+
throw new BatchClosedError('Batch is already committed');
|
|
467
|
+
this._closed = true;
|
|
468
|
+
if (this._writes.size === 0 && this._deletes.size === 0) {
|
|
469
|
+
return;
|
|
470
|
+
}
|
|
471
|
+
const treeOid = await this._ns._treeOid();
|
|
472
|
+
const newTreeOid = await this._ns._buildNoteTree(treeOid, this._writes, this._deletes);
|
|
473
|
+
const count = this._writes.size + this._deletes.size;
|
|
474
|
+
await this._ns._commitNoteTree(newTreeOid, `Notes batch update (${count} changes)`);
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
// -----------------------------------------------------------------------
|
|
478
|
+
// NoteDict
|
|
479
|
+
// -----------------------------------------------------------------------
|
|
480
|
+
/**
|
|
481
|
+
* Outer container for git notes namespaces on a GitStore.
|
|
482
|
+
*
|
|
483
|
+
* `store.notes.commits` returns the default namespace (`refs/notes/commits`).
|
|
484
|
+
* `store.notes.namespace('reviews')` returns a custom namespace.
|
|
485
|
+
*/
|
|
486
|
+
export class NoteDict {
|
|
487
|
+
_store;
|
|
488
|
+
constructor(store) {
|
|
489
|
+
this._store = store;
|
|
490
|
+
}
|
|
491
|
+
toString() {
|
|
492
|
+
return `NoteDict(${this._store.toString()})`;
|
|
493
|
+
}
|
|
494
|
+
/** The default `refs/notes/commits` namespace. */
|
|
495
|
+
get commits() {
|
|
496
|
+
return new NoteNamespace(this._store, 'commits');
|
|
497
|
+
}
|
|
498
|
+
/**
|
|
499
|
+
* Access a custom notes namespace.
|
|
500
|
+
*
|
|
501
|
+
* @param name - Namespace name (e.g. 'reviews').
|
|
502
|
+
* @returns NoteNamespace for `refs/notes/<name>`.
|
|
503
|
+
*/
|
|
504
|
+
namespace(name) {
|
|
505
|
+
return new NoteNamespace(this._store, name);
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
//# sourceMappingURL=notes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notes.js","sourceRoot":"","sources":["../src/notes.ts"],"names":[],"mappings":"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"}
|
package/dist/paths.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Path normalization and validation utilities.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Return true if path represents the root (empty or only slashes).
|
|
6
|
+
*/
|
|
7
|
+
export declare function isRootPath(path: string): boolean;
|
|
8
|
+
/**
|
|
9
|
+
* Normalize a repo path: strip leading/trailing slashes, reject bad segments.
|
|
10
|
+
* Always uses forward slashes.
|
|
11
|
+
*/
|
|
12
|
+
export declare function normalizePath(path: string): string;
|
|
13
|
+
/**
|
|
14
|
+
* Reject ref names containing ':', space, tab, or newline.
|
|
15
|
+
*/
|
|
16
|
+
export declare function validateRefName(name: string): void;
|
package/dist/paths.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Path normalization and validation utilities.
|
|
3
|
+
*/
|
|
4
|
+
import { InvalidPathError, InvalidRefNameError } from './types.js';
|
|
5
|
+
/**
|
|
6
|
+
* Return true if path represents the root (empty or only slashes).
|
|
7
|
+
*/
|
|
8
|
+
export function isRootPath(path) {
|
|
9
|
+
return path.replace(/[/\\]/g, '') === '';
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Normalize a repo path: strip leading/trailing slashes, reject bad segments.
|
|
13
|
+
* Always uses forward slashes.
|
|
14
|
+
*/
|
|
15
|
+
export function normalizePath(path) {
|
|
16
|
+
path = path.replace(/\\/g, '/').replace(/^\/+|\/+$/g, '');
|
|
17
|
+
if (!path)
|
|
18
|
+
throw new InvalidPathError('Path must not be empty');
|
|
19
|
+
const segments = path.split('/');
|
|
20
|
+
for (const seg of segments) {
|
|
21
|
+
if (!seg)
|
|
22
|
+
throw new InvalidPathError(`Empty segment in path: '${path}'`);
|
|
23
|
+
if (seg === '.' || seg === '..')
|
|
24
|
+
throw new InvalidPathError(`Invalid path segment: '${seg}'`);
|
|
25
|
+
}
|
|
26
|
+
return segments.join('/');
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Reject ref names containing ':', space, tab, or newline.
|
|
30
|
+
*/
|
|
31
|
+
export function validateRefName(name) {
|
|
32
|
+
const bad = [
|
|
33
|
+
[':', 'colon'],
|
|
34
|
+
[' ', 'space'],
|
|
35
|
+
['\t', 'tab'],
|
|
36
|
+
['\n', 'newline'],
|
|
37
|
+
];
|
|
38
|
+
for (const [ch, label] of bad) {
|
|
39
|
+
if (name.includes(ch)) {
|
|
40
|
+
throw new InvalidRefNameError(`Invalid ref name '${name}': contains ${label}`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=paths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAEnE;;GAEG;AACH,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,KAAK,EAAE,CAAC;AAC3C,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,IAAY;IACxC,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;IAC1D,IAAI,CAAC,IAAI;QAAE,MAAM,IAAI,gBAAgB,CAAC,wBAAwB,CAAC,CAAC;IAChE,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACjC,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;QAC3B,IAAI,CAAC,GAAG;YAAE,MAAM,IAAI,gBAAgB,CAAC,2BAA2B,IAAI,GAAG,CAAC,CAAC;QACzE,IAAI,GAAG,KAAK,GAAG,IAAI,GAAG,KAAK,IAAI;YAAE,MAAM,IAAI,gBAAgB,CAAC,0BAA0B,GAAG,GAAG,CAAC,CAAC;IAChG,CAAC;IACD,OAAO,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC5B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,IAAY;IAC1C,MAAM,GAAG,GAAuB;QAC9B,CAAC,GAAG,EAAE,OAAO,CAAC;QACd,CAAC,GAAG,EAAE,OAAO,CAAC;QACd,CAAC,IAAI,EAAE,KAAK,CAAC;QACb,CAAC,IAAI,EAAE,SAAS,CAAC;KAClB,CAAC;IACF,KAAK,MAAM,CAAC,EAAE,EAAE,KAAK,CAAC,IAAI,GAAG,EAAE,CAAC;QAC9B,IAAI,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC;YACtB,MAAM,IAAI,mBAAmB,CAAC,qBAAqB,IAAI,eAAe,KAAK,EAAE,CAAC,CAAC;QACjF,CAAC;IACH,CAAC;AACH,CAAC"}
|