@vibe-validate/git 0.18.1 → 0.18.2-rc.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/dist/git-executor.d.ts +8 -0
- package/dist/git-executor.d.ts.map +1 -1
- package/dist/git-executor.js +5 -1
- package/dist/git-executor.js.map +1 -1
- package/dist/git-notes.d.ts +13 -3
- package/dist/git-notes.d.ts.map +1 -1
- package/dist/git-notes.js +236 -8
- package/dist/git-notes.js.map +1 -1
- package/dist/tree-hash.d.ts.map +1 -1
- package/dist/tree-hash.js +106 -2
- package/dist/tree-hash.js.map +1 -1
- package/package.json +2 -2
package/dist/git-executor.d.ts
CHANGED
|
@@ -42,6 +42,11 @@ export interface GitExecutionOptions {
|
|
|
42
42
|
* Merged with process.env
|
|
43
43
|
*/
|
|
44
44
|
env?: NodeJS.ProcessEnv;
|
|
45
|
+
/**
|
|
46
|
+
* Working directory for git command execution
|
|
47
|
+
* @default process.cwd()
|
|
48
|
+
*/
|
|
49
|
+
cwd?: string;
|
|
45
50
|
}
|
|
46
51
|
/**
|
|
47
52
|
* Result of a git command execution
|
|
@@ -89,6 +94,9 @@ export interface GitCommandError extends Error {
|
|
|
89
94
|
* ['notes', '--ref=vibe-validate/validate', 'add', '-f', '-F', '-', treeHash],
|
|
90
95
|
* { stdin: noteContent }
|
|
91
96
|
* );
|
|
97
|
+
*
|
|
98
|
+
* // Execute in specific directory
|
|
99
|
+
* executeGitCommand(['status'], { cwd: '/path/to/repo' });
|
|
92
100
|
* ```
|
|
93
101
|
*/
|
|
94
102
|
export declare function executeGitCommand(args: string[], options?: GitExecutionOptions): GitExecutionResult;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"git-executor.d.ts","sourceRoot":"","sources":["../src/git-executor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AASH,MAAM,WAAW,mBAAmB;IAClC;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;;OAGG;IACH,QAAQ,CAAC,EAAE,cAAc,CAAC;IAE1B;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;;OAGG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IAEvB;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IAEzB;;;OAGG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"git-executor.d.ts","sourceRoot":"","sources":["../src/git-executor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AASH,MAAM,WAAW,mBAAmB;IAClC;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;;OAGG;IACH,QAAQ,CAAC,EAAE,cAAc,CAAC;IAE1B;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;;OAGG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IAEvB;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IAEzB;;;OAGG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IAExB;;;OAGG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,uCAAuC;IACvC,MAAM,EAAE,MAAM,CAAC;IACf,sCAAsC;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,gCAAgC;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,oCAAoC;IACpC,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,eAAgB,SAAQ,KAAK;IAC5C,qCAAqC;IACrC,QAAQ,EAAE,MAAM,CAAC;IACjB,4BAA4B;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,sBAAsB;IACtB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,GAAE,mBAAwB,GAChC,kBAAkB,CAyDpB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,OAAO,GAAE,mBAAwB,GAAG,MAAM,CAGxF;AAED;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,OAAO,GAAE,mBAAwB,GAAG,OAAO,CAGxF;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CA6BhD;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CASvD;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAqBvD"}
|
package/dist/git-executor.js
CHANGED
|
@@ -39,10 +39,13 @@ const GIT_TIMEOUT = 30000; // 30 seconds
|
|
|
39
39
|
* ['notes', '--ref=vibe-validate/validate', 'add', '-f', '-F', '-', treeHash],
|
|
40
40
|
* { stdin: noteContent }
|
|
41
41
|
* );
|
|
42
|
+
*
|
|
43
|
+
* // Execute in specific directory
|
|
44
|
+
* executeGitCommand(['status'], { cwd: '/path/to/repo' });
|
|
42
45
|
* ```
|
|
43
46
|
*/
|
|
44
47
|
export function executeGitCommand(args, options = {}) {
|
|
45
|
-
const { timeout = GIT_TIMEOUT, encoding = 'utf8', stdin, ignoreErrors = false, suppressStderr = false, env, } = options;
|
|
48
|
+
const { timeout = GIT_TIMEOUT, encoding = 'utf8', stdin, ignoreErrors = false, suppressStderr = false, env, cwd, } = options;
|
|
46
49
|
// Validate arguments
|
|
47
50
|
if (!Array.isArray(args) || args.length === 0) {
|
|
48
51
|
throw new Error('Git command arguments must be a non-empty array');
|
|
@@ -53,6 +56,7 @@ export function executeGitCommand(args, options = {}) {
|
|
|
53
56
|
timeout,
|
|
54
57
|
maxBuffer: 10 * 1024 * 1024, // 10MB buffer
|
|
55
58
|
env: env ? { ...process.env, ...env } : process.env,
|
|
59
|
+
cwd,
|
|
56
60
|
};
|
|
57
61
|
// Configure stdio
|
|
58
62
|
if (stdin === undefined) {
|
package/dist/git-executor.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"git-executor.js","sourceRoot":"","sources":["../src/git-executor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,SAAS,EAAyB,MAAM,oBAAoB,CAAC;AAEtE;;GAEG;AACH,MAAM,WAAW,GAAG,KAAK,CAAC,CAAC,aAAa;
|
|
1
|
+
{"version":3,"file":"git-executor.js","sourceRoot":"","sources":["../src/git-executor.ts"],"names":[],"mappings":"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"}
|
package/dist/git-notes.d.ts
CHANGED
|
@@ -8,18 +8,28 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import type { TreeHash, NotesRef } from './types.js';
|
|
10
10
|
/**
|
|
11
|
-
* Add or update a git note
|
|
11
|
+
* Add or update a git note with atomic compare-and-swap
|
|
12
|
+
*
|
|
13
|
+
* Implements atomic optimistic locking using git plumbing commands.
|
|
14
|
+
* When a conflict is detected:
|
|
15
|
+
* 1. Read the current notes ref commit SHA (snapshot)
|
|
16
|
+
* 2. Read and merge the existing note
|
|
17
|
+
* 3. Build a new notes commit with merged content
|
|
18
|
+
* 4. Atomically update the ref only if it hasn't changed (compare-and-swap)
|
|
19
|
+
* 5. If ref changed, retry from step 1
|
|
20
|
+
*
|
|
21
|
+
* This prevents data loss when multiple worktrees validate simultaneously.
|
|
12
22
|
*
|
|
13
23
|
* @param notesRef - The notes reference (e.g., 'vibe-validate/validate')
|
|
14
24
|
* @param object - The git tree hash to attach the note to (must be from getGitTreeHash())
|
|
15
25
|
* @param content - The note content
|
|
16
|
-
* @param force - Whether to
|
|
26
|
+
* @param force - Whether to skip optimistic locking and force overwrite
|
|
17
27
|
* @returns true if note was added successfully
|
|
18
28
|
*
|
|
19
29
|
* @example
|
|
20
30
|
* ```typescript
|
|
21
31
|
* const treeHash = await getGitTreeHash();
|
|
22
|
-
* addNote('vibe-validate/validate', treeHash, noteContent,
|
|
32
|
+
* addNote('vibe-validate/validate', treeHash, noteContent, false);
|
|
23
33
|
* ```
|
|
24
34
|
*/
|
|
25
35
|
export declare function addNote(notesRef: NotesRef, object: TreeHash, content: string, force?: boolean): boolean;
|
package/dist/git-notes.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"git-notes.d.ts","sourceRoot":"","sources":["../src/git-notes.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAQH,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"git-notes.d.ts","sourceRoot":"","sources":["../src/git-notes.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAQH,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AA2OrD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,OAAO,CACrB,QAAQ,EAAE,QAAQ,EAClB,MAAM,EAAE,QAAQ,EAChB,OAAO,EAAE,MAAM,EACf,KAAK,GAAE,OAAe,GACrB,OAAO,CA2DT;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,GAAG,MAAM,GAAG,IAAI,CAU5E;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,UAAU,CAAC,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,GAAG,OAAO,CAOxE;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,SAAS,CAAC,QAAQ,EAAE,QAAQ,GAAG,KAAK,CAAC,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CA4BvE;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,OAAO,CAAC,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,GAAG,OAAO,CAOrE;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,CAczD;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAgCzD;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAWrD;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAa9D"}
|
package/dist/git-notes.js
CHANGED
|
@@ -8,34 +8,262 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import { executeGitCommand, tryGitCommand, validateNotesRef, validateTreeHash, } from './git-executor.js';
|
|
10
10
|
/**
|
|
11
|
-
*
|
|
11
|
+
* Create a blob from content using git hash-object
|
|
12
|
+
*
|
|
13
|
+
* @param content - The content to store as a blob
|
|
14
|
+
* @returns The blob SHA
|
|
15
|
+
*/
|
|
16
|
+
function createBlob(content) {
|
|
17
|
+
const result = executeGitCommand(['hash-object', '-w', '--stdin'], {
|
|
18
|
+
stdin: content,
|
|
19
|
+
});
|
|
20
|
+
return result.stdout;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Read tree entries from a commit
|
|
24
|
+
*
|
|
25
|
+
* @param commitSha - The commit SHA to read the tree from
|
|
26
|
+
* @returns Array of tree entries
|
|
27
|
+
*/
|
|
28
|
+
function readTreeEntries(commitSha) {
|
|
29
|
+
const result = executeGitCommand(['ls-tree', commitSha], {
|
|
30
|
+
ignoreErrors: true,
|
|
31
|
+
});
|
|
32
|
+
if (!result.success || !result.stdout) {
|
|
33
|
+
return [];
|
|
34
|
+
}
|
|
35
|
+
const entries = [];
|
|
36
|
+
for (const line of result.stdout.split('\n')) {
|
|
37
|
+
if (!line)
|
|
38
|
+
continue;
|
|
39
|
+
// Format: "MODE TYPE SHA\tNAME" (note: TAB before name, not space)
|
|
40
|
+
// Use split to avoid backtracking regex issues
|
|
41
|
+
const parts = line.split(/\s+/);
|
|
42
|
+
if (parts.length < 4)
|
|
43
|
+
continue;
|
|
44
|
+
const mode = parts[0];
|
|
45
|
+
const type = parts[1];
|
|
46
|
+
const sha = parts[2];
|
|
47
|
+
// Name may contain spaces, so join the rest
|
|
48
|
+
const name = parts.slice(3).join(' ');
|
|
49
|
+
// Validate format
|
|
50
|
+
if (!/^\d+$/.test(mode))
|
|
51
|
+
continue;
|
|
52
|
+
if (type !== 'blob' && type !== 'tree')
|
|
53
|
+
continue;
|
|
54
|
+
if (!/^[0-9a-f]+$/.test(sha))
|
|
55
|
+
continue;
|
|
56
|
+
entries.push({
|
|
57
|
+
mode,
|
|
58
|
+
type,
|
|
59
|
+
sha,
|
|
60
|
+
name,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
return entries;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Create a tree from entries using git mktree
|
|
67
|
+
*
|
|
68
|
+
* @param entries - Array of tree entries
|
|
69
|
+
* @returns The tree SHA
|
|
70
|
+
*/
|
|
71
|
+
function createTree(entries) {
|
|
72
|
+
// Format for mktree: "MODE TYPE SHA\tNAME"
|
|
73
|
+
const input = entries
|
|
74
|
+
.map((e) => `${e.mode} ${e.type} ${e.sha}\t${e.name}`)
|
|
75
|
+
.join('\n');
|
|
76
|
+
const result = executeGitCommand(['mktree'], {
|
|
77
|
+
stdin: input,
|
|
78
|
+
});
|
|
79
|
+
return result.stdout;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Create a notes commit using git commit-tree
|
|
83
|
+
*
|
|
84
|
+
* @param treeSha - The tree SHA
|
|
85
|
+
* @param parentSha - The parent commit SHA (or null for first commit)
|
|
86
|
+
* @param message - Commit message
|
|
87
|
+
* @returns The commit SHA
|
|
88
|
+
*/
|
|
89
|
+
function createNotesCommit(treeSha, parentSha, message) {
|
|
90
|
+
const args = ['commit-tree', treeSha, '-m', message];
|
|
91
|
+
if (parentSha) {
|
|
92
|
+
args.push('-p', parentSha);
|
|
93
|
+
}
|
|
94
|
+
const result = executeGitCommand(args);
|
|
95
|
+
return result.stdout;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Atomically update a ref using compare-and-swap
|
|
99
|
+
*
|
|
100
|
+
* @param ref - The ref to update (e.g., 'refs/notes/vibe-validate/validate')
|
|
101
|
+
* @param newSha - The new commit SHA
|
|
102
|
+
* @param oldSha - The expected current commit SHA (or null for new ref)
|
|
103
|
+
* @returns true if update succeeded, false if ref changed (CAS failure)
|
|
104
|
+
*/
|
|
105
|
+
function atomicUpdateRef(ref, newSha, oldSha) {
|
|
106
|
+
const args = ['update-ref', ref, newSha];
|
|
107
|
+
if (oldSha) {
|
|
108
|
+
args.push(oldSha);
|
|
109
|
+
}
|
|
110
|
+
const result = executeGitCommand(args, {
|
|
111
|
+
ignoreErrors: true,
|
|
112
|
+
suppressStderr: true,
|
|
113
|
+
});
|
|
114
|
+
return result.success;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Attempt atomic merge of a note (single retry attempt)
|
|
118
|
+
*
|
|
119
|
+
* @param notesRef - The notes reference
|
|
120
|
+
* @param fullRef - The full ref path (refs/notes/...)
|
|
121
|
+
* @param object - The object to attach the note to
|
|
122
|
+
* @param content - The new note content to merge
|
|
123
|
+
* @returns true if merge succeeded, false if CAS failed or error occurred
|
|
124
|
+
*/
|
|
125
|
+
function attemptAtomicMerge(notesRef, fullRef, object, content) {
|
|
126
|
+
// Step 1: Get current notes ref commit SHA (snapshot for compare-and-swap)
|
|
127
|
+
const currentCommitSha = getNotesRefSha(notesRef);
|
|
128
|
+
if (!currentCommitSha) {
|
|
129
|
+
return false; // Ref disappeared
|
|
130
|
+
}
|
|
131
|
+
// Step 2: Read existing note and merge
|
|
132
|
+
const existingNote = readNote(notesRef, object);
|
|
133
|
+
if (existingNote === null) {
|
|
134
|
+
return false; // Note disappeared
|
|
135
|
+
}
|
|
136
|
+
const merged = mergeNotes(existingNote, content);
|
|
137
|
+
// Step 3: Build new notes commit atomically
|
|
138
|
+
try {
|
|
139
|
+
// Read current tree entries
|
|
140
|
+
const entries = readTreeEntries(currentCommitSha);
|
|
141
|
+
// Create blob with merged content
|
|
142
|
+
const blobSha = createBlob(merged);
|
|
143
|
+
// Update or add entry for this object
|
|
144
|
+
const existingEntryIndex = entries.findIndex((e) => e.name === object);
|
|
145
|
+
const newEntry = {
|
|
146
|
+
mode: '100644',
|
|
147
|
+
type: 'blob',
|
|
148
|
+
sha: blobSha,
|
|
149
|
+
name: object,
|
|
150
|
+
};
|
|
151
|
+
if (existingEntryIndex >= 0) {
|
|
152
|
+
entries[existingEntryIndex] = newEntry;
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
entries.push(newEntry);
|
|
156
|
+
}
|
|
157
|
+
// Create new tree
|
|
158
|
+
const treeSha = createTree(entries);
|
|
159
|
+
// Create new commit
|
|
160
|
+
const commitSha = createNotesCommit(treeSha, currentCommitSha, 'Notes added by vibe-validate');
|
|
161
|
+
// Step 4: Atomically update ref (compare-and-swap)
|
|
162
|
+
return atomicUpdateRef(fullRef, commitSha, currentCommitSha);
|
|
163
|
+
}
|
|
164
|
+
catch {
|
|
165
|
+
return false; // Git plumbing operation failed
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Merge two git notes containing validation run history
|
|
170
|
+
*
|
|
171
|
+
* Strategy: Parse both notes as JSON, append new runs to existing runs.
|
|
172
|
+
* No conflict resolution needed - each run is independent and timestamped.
|
|
173
|
+
*
|
|
174
|
+
* @param existingNote - Existing note content (JSON)
|
|
175
|
+
* @param newNote - New note content to merge (JSON)
|
|
176
|
+
* @returns Merged note content
|
|
177
|
+
*/
|
|
178
|
+
function mergeNotes(existingNote, newNote) {
|
|
179
|
+
try {
|
|
180
|
+
const existing = JSON.parse(existingNote);
|
|
181
|
+
const newData = JSON.parse(newNote);
|
|
182
|
+
// Extract runs arrays (handle both single object and array formats)
|
|
183
|
+
const existingRuns = Array.isArray(existing.runs) ? existing.runs : [];
|
|
184
|
+
const newRuns = Array.isArray(newData.runs) ? newData.runs : [];
|
|
185
|
+
// Merge: append new runs to existing
|
|
186
|
+
const merged = {
|
|
187
|
+
...existing,
|
|
188
|
+
runs: [...existingRuns, ...newRuns],
|
|
189
|
+
};
|
|
190
|
+
return JSON.stringify(merged);
|
|
191
|
+
}
|
|
192
|
+
catch {
|
|
193
|
+
// If parsing fails, prefer new note (latest data)
|
|
194
|
+
return newNote;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Add or update a git note with atomic compare-and-swap
|
|
199
|
+
*
|
|
200
|
+
* Implements atomic optimistic locking using git plumbing commands.
|
|
201
|
+
* When a conflict is detected:
|
|
202
|
+
* 1. Read the current notes ref commit SHA (snapshot)
|
|
203
|
+
* 2. Read and merge the existing note
|
|
204
|
+
* 3. Build a new notes commit with merged content
|
|
205
|
+
* 4. Atomically update the ref only if it hasn't changed (compare-and-swap)
|
|
206
|
+
* 5. If ref changed, retry from step 1
|
|
207
|
+
*
|
|
208
|
+
* This prevents data loss when multiple worktrees validate simultaneously.
|
|
12
209
|
*
|
|
13
210
|
* @param notesRef - The notes reference (e.g., 'vibe-validate/validate')
|
|
14
211
|
* @param object - The git tree hash to attach the note to (must be from getGitTreeHash())
|
|
15
212
|
* @param content - The note content
|
|
16
|
-
* @param force - Whether to
|
|
213
|
+
* @param force - Whether to skip optimistic locking and force overwrite
|
|
17
214
|
* @returns true if note was added successfully
|
|
18
215
|
*
|
|
19
216
|
* @example
|
|
20
217
|
* ```typescript
|
|
21
218
|
* const treeHash = await getGitTreeHash();
|
|
22
|
-
* addNote('vibe-validate/validate', treeHash, noteContent,
|
|
219
|
+
* addNote('vibe-validate/validate', treeHash, noteContent, false);
|
|
23
220
|
* ```
|
|
24
221
|
*/
|
|
25
222
|
export function addNote(notesRef, object, content, force = false) {
|
|
26
223
|
validateNotesRef(notesRef);
|
|
27
224
|
validateTreeHash(object);
|
|
28
|
-
|
|
225
|
+
// Convert short ref to full ref
|
|
226
|
+
const fullRef = notesRef.startsWith('refs/')
|
|
227
|
+
? notesRef
|
|
228
|
+
: `refs/notes/${notesRef}`;
|
|
229
|
+
// If force is true, skip optimistic locking (legacy behavior)
|
|
29
230
|
if (force) {
|
|
30
|
-
args
|
|
231
|
+
const args = ['notes', `--ref=${notesRef}`, 'add', '-f', '-F', '-', object];
|
|
232
|
+
const result = executeGitCommand(args, {
|
|
233
|
+
stdin: content,
|
|
234
|
+
ignoreErrors: true,
|
|
235
|
+
suppressStderr: true,
|
|
236
|
+
});
|
|
237
|
+
return result.success;
|
|
31
238
|
}
|
|
32
|
-
|
|
33
|
-
const
|
|
239
|
+
// Fast path: Try to add note without force (for new notes)
|
|
240
|
+
const addResult = executeGitCommand(['notes', `--ref=${notesRef}`, 'add', '-F', '-', object], {
|
|
34
241
|
stdin: content,
|
|
35
242
|
ignoreErrors: true,
|
|
36
243
|
suppressStderr: true,
|
|
37
244
|
});
|
|
38
|
-
|
|
245
|
+
if (addResult.success) {
|
|
246
|
+
return true; // Success! Note didn't exist, added cleanly
|
|
247
|
+
}
|
|
248
|
+
// Check if this is a conflict (note already exists)
|
|
249
|
+
const isConflict = addResult.stderr.includes('already exists');
|
|
250
|
+
if (!isConflict) {
|
|
251
|
+
// Not a conflict - real error, return failure
|
|
252
|
+
return false;
|
|
253
|
+
}
|
|
254
|
+
// Conflict detected - enter atomic merge path with retry
|
|
255
|
+
const maxRetries = 3;
|
|
256
|
+
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
|
257
|
+
const success = attemptAtomicMerge(notesRef, fullRef, object, content);
|
|
258
|
+
if (success) {
|
|
259
|
+
return true; // Success! Atomic merge succeeded
|
|
260
|
+
}
|
|
261
|
+
// Failed - retry if not last attempt
|
|
262
|
+
if (attempt === maxRetries) {
|
|
263
|
+
return false;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
return false;
|
|
39
267
|
}
|
|
40
268
|
/**
|
|
41
269
|
* Read a git note
|
package/dist/git-notes.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"git-notes.js","sourceRoot":"","sources":["../src/git-notes.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EACL,iBAAiB,EACjB,aAAa,EACb,gBAAgB,EAChB,gBAAgB,GACjB,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"git-notes.js","sourceRoot":"","sources":["../src/git-notes.ts"],"names":[],"mappings":"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"}
|
package/dist/tree-hash.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tree-hash.d.ts","sourceRoot":"","sources":["../src/tree-hash.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;
|
|
1
|
+
{"version":3,"file":"tree-hash.d.ts","sourceRoot":"","sources":["../src/tree-hash.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAQH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AA+G3C;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,QAAQ,CAAC,CAuFxD;AAED;;;;;;;GAOG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,QAAQ,CAAC,CAUzD;AAED;;;;GAIG;AACH,wBAAsB,qBAAqB,IAAI,OAAO,CAAC,OAAO,CAAC,CAS9D"}
|
package/dist/tree-hash.js
CHANGED
|
@@ -10,9 +10,112 @@
|
|
|
10
10
|
* git stash create includes timestamps, making hashes non-deterministic.
|
|
11
11
|
* git write-tree produces content-based hashes only (no timestamps).
|
|
12
12
|
*/
|
|
13
|
-
import { copyFileSync, existsSync, unlinkSync } from 'node:fs';
|
|
13
|
+
import { copyFileSync, existsSync, unlinkSync, readdirSync, statSync } from 'node:fs';
|
|
14
|
+
import { join } from 'node:path';
|
|
15
|
+
import { isProcessRunning } from '@vibe-validate/utils';
|
|
14
16
|
import { executeGitCommand } from './git-executor.js';
|
|
15
17
|
const GIT_TIMEOUT = 30000; // 30 seconds timeout for git operations
|
|
18
|
+
/**
|
|
19
|
+
* Minimum age (milliseconds) before cleaning up stale temp index files
|
|
20
|
+
*
|
|
21
|
+
* Rationale: 5 minutes balances:
|
|
22
|
+
* - Avoiding false positives (very slow validations in progress)
|
|
23
|
+
* - Timely cleanup (don't accumulate too many stale files)
|
|
24
|
+
* - Typical validation duration (< 2 minutes in most projects)
|
|
25
|
+
*/
|
|
26
|
+
const STALE_INDEX_AGE_MS = 5 * 60 * 1000; // 5 minutes
|
|
27
|
+
/**
|
|
28
|
+
* Try to clean up a legacy temp index file (no PID suffix)
|
|
29
|
+
* @param gitDir - Git directory path
|
|
30
|
+
*/
|
|
31
|
+
function tryCleanupLegacyTempIndex(gitDir) {
|
|
32
|
+
try {
|
|
33
|
+
const filePath = join(gitDir, 'vibe-validate-temp-index');
|
|
34
|
+
const stats = statSync(filePath);
|
|
35
|
+
const ageMs = Date.now() - stats.mtimeMs;
|
|
36
|
+
if (ageMs >= STALE_INDEX_AGE_MS) {
|
|
37
|
+
unlinkSync(filePath);
|
|
38
|
+
console.warn(`⚠️ Cleaned up legacy temp index (${Math.round(ageMs / 1000)}s old)`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
// Ignore cleanup errors (file may not exist or be in use)
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Try to clean up a PID-suffixed temp index file if it's stale
|
|
47
|
+
* @param gitDir - Git directory path
|
|
48
|
+
* @param file - Filename to check
|
|
49
|
+
* @param pid - Process ID from filename
|
|
50
|
+
*/
|
|
51
|
+
function tryCleanupPidTempIndex(gitDir, file, pid) {
|
|
52
|
+
try {
|
|
53
|
+
const filePath = join(gitDir, file);
|
|
54
|
+
const stats = statSync(filePath);
|
|
55
|
+
const ageMs = Date.now() - stats.mtimeMs;
|
|
56
|
+
// Skip if younger than threshold
|
|
57
|
+
if (ageMs < STALE_INDEX_AGE_MS)
|
|
58
|
+
return;
|
|
59
|
+
// Skip if process is still running
|
|
60
|
+
if (isProcessRunning(pid))
|
|
61
|
+
return;
|
|
62
|
+
// Stale file - clean it up
|
|
63
|
+
try {
|
|
64
|
+
unlinkSync(filePath);
|
|
65
|
+
const ageSec = Math.round(ageMs / 1000);
|
|
66
|
+
console.warn(`⚠️ Cleaned up stale temp index from PID ${pid} (${ageSec}s old, process not running)`);
|
|
67
|
+
}
|
|
68
|
+
catch (err) {
|
|
69
|
+
const error = err;
|
|
70
|
+
console.warn(`⚠️ Failed to clean up stale temp index ${file}: ${error.message}`);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
// Ignore errors reading file stats (file may have been deleted)
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Clean up stale temp index files from crashed processes
|
|
79
|
+
*
|
|
80
|
+
* Scans git directory for temp index files and removes those that are:
|
|
81
|
+
* - Older than 5 minutes AND
|
|
82
|
+
* - Process no longer running
|
|
83
|
+
*
|
|
84
|
+
* Warns to stderr when cleanup occurs (bug detection canary).
|
|
85
|
+
* Fails gracefully if cleanup fails (warn and continue).
|
|
86
|
+
*/
|
|
87
|
+
function cleanupStaleIndexes(gitDir) {
|
|
88
|
+
const pattern = /^vibe-validate-temp-index-(\d+)$/;
|
|
89
|
+
try {
|
|
90
|
+
const files = readdirSync(gitDir);
|
|
91
|
+
for (const file of files) {
|
|
92
|
+
// Handle legacy temp index (no PID suffix)
|
|
93
|
+
if (file === 'vibe-validate-temp-index') {
|
|
94
|
+
tryCleanupLegacyTempIndex(gitDir);
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
// Handle PID-suffixed temp index
|
|
98
|
+
const match = pattern.exec(file);
|
|
99
|
+
if (!match)
|
|
100
|
+
continue;
|
|
101
|
+
const pid = Number.parseInt(match[1], 10);
|
|
102
|
+
tryCleanupPidTempIndex(gitDir, file, pid);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
catch (error) {
|
|
106
|
+
// Expected errors (fail-safe, no action needed):
|
|
107
|
+
// - ENOENT: .git directory doesn't exist (fresh repo)
|
|
108
|
+
// - ENOTDIR: gitDir points to a file, not directory
|
|
109
|
+
const err = error;
|
|
110
|
+
if (err.code === 'ENOENT' || err.code === 'ENOTDIR') {
|
|
111
|
+
return; // Expected failure - skip cleanup
|
|
112
|
+
}
|
|
113
|
+
// Unexpected errors (should warn for debugging)
|
|
114
|
+
console.warn(`⚠️ Unexpected error during temp index cleanup: ${err.message}`);
|
|
115
|
+
console.warn(` Git dir: ${gitDir}`);
|
|
116
|
+
console.warn(` This may indicate a bug - please report if you see this often`);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
16
119
|
/**
|
|
17
120
|
* Get deterministic git tree hash representing current working tree state
|
|
18
121
|
*
|
|
@@ -38,7 +141,8 @@ export async function getGitTreeHash() {
|
|
|
38
141
|
executeGitCommand(['rev-parse', '--is-inside-work-tree'], { timeout: GIT_TIMEOUT });
|
|
39
142
|
// Get git directory and create temp index path
|
|
40
143
|
const gitDir = executeGitCommand(['rev-parse', '--git-dir'], { timeout: GIT_TIMEOUT }).stdout.trim();
|
|
41
|
-
|
|
144
|
+
cleanupStaleIndexes(gitDir);
|
|
145
|
+
const tempIndexFile = `${gitDir}/vibe-validate-temp-index-${process.pid}`;
|
|
42
146
|
try {
|
|
43
147
|
// Step 1: Copy current index to temp index (if it exists)
|
|
44
148
|
const currentIndex = `${gitDir}/index`;
|
package/dist/tree-hash.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tree-hash.js","sourceRoot":"","sources":["../src/tree-hash.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"tree-hash.js","sourceRoot":"","sources":["../src/tree-hash.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vibe-validate/git",
|
|
3
|
-
"version": "0.18.1",
|
|
3
|
+
"version": "0.18.2-rc.1",
|
|
4
4
|
"description": "Git utilities for vibe-validate - tree hash calculation, branch sync, and post-merge cleanup",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"access": "public"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@vibe-validate/utils": "0.18.1"
|
|
41
|
+
"@vibe-validate/utils": "0.18.2-rc.1"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"@types/node": "^22.19.2",
|