@vibe-validate/git 0.17.0-rc.6 → 0.17.0-rc.7
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-commands.d.ts +2 -2
- package/dist/git-commands.d.ts.map +1 -1
- package/dist/git-commands.js +12 -58
- package/dist/git-commands.js.map +1 -1
- package/dist/git-executor.d.ts +144 -0
- package/dist/git-executor.d.ts.map +1 -0
- package/dist/git-executor.js +192 -0
- package/dist/git-executor.js.map +1 -0
- package/dist/git-notes.d.ts +142 -0
- package/dist/git-notes.d.ts.map +1 -0
- package/dist/git-notes.js +251 -0
- package/dist/git-notes.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/git-commands.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Git Command Utilities
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* High-level git operations built on top of the secure git-executor.
|
|
5
|
+
* These functions provide convenient access to common git commands.
|
|
6
6
|
*/
|
|
7
7
|
/**
|
|
8
8
|
* Check if the current directory is inside a git repository
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"git-commands.d.ts","sourceRoot":"","sources":["../src/git-commands.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;
|
|
1
|
+
{"version":3,"file":"git-commands.d.ts","sourceRoot":"","sources":["../src/git-commands.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH;;;GAGG;AACH,wBAAgB,eAAe,IAAI,OAAO,CAEzC;AAED;;;;GAIG;AACH,wBAAgB,SAAS,IAAI,MAAM,CAElC;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAEzC;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAEzC;AAED;;;;GAIG;AACH,wBAAgB,cAAc,IAAI,MAAM,CAEvC;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAE9C;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAErD"}
|
package/dist/git-commands.js
CHANGED
|
@@ -1,46 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Git Command Utilities
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* High-level git operations built on top of the secure git-executor.
|
|
5
|
+
* These functions provide convenient access to common git commands.
|
|
6
6
|
*/
|
|
7
|
-
import {
|
|
8
|
-
/**
|
|
9
|
-
* Standard options for git command execution
|
|
10
|
-
*/
|
|
11
|
-
const GIT_OPTIONS = {
|
|
12
|
-
encoding: 'utf8',
|
|
13
|
-
timeout: 30000, // 30 seconds
|
|
14
|
-
stdio: 'pipe',
|
|
15
|
-
};
|
|
16
|
-
/**
|
|
17
|
-
* Execute a git command with standard options
|
|
18
|
-
* @param command - The git command to execute
|
|
19
|
-
* @param options - Optional overrides for execution options
|
|
20
|
-
* @returns The command output, trimmed of whitespace
|
|
21
|
-
* @throws Error if the command fails
|
|
22
|
-
*/
|
|
23
|
-
function execGitCommand(command, options) {
|
|
24
|
-
try {
|
|
25
|
-
const result = execSync(command, { ...GIT_OPTIONS, ...options });
|
|
26
|
-
return result.trim();
|
|
27
|
-
}
|
|
28
|
-
catch (error) {
|
|
29
|
-
throw new Error(`Git command failed: ${command}`, { cause: error });
|
|
30
|
-
}
|
|
31
|
-
}
|
|
7
|
+
import { execGitCommand, tryGitCommand } from './git-executor.js';
|
|
32
8
|
/**
|
|
33
9
|
* Check if the current directory is inside a git repository
|
|
34
10
|
* @returns true if inside a git repository, false otherwise
|
|
35
11
|
*/
|
|
36
12
|
export function isGitRepository() {
|
|
37
|
-
|
|
38
|
-
execGitCommand('git rev-parse --is-inside-work-tree');
|
|
39
|
-
return true;
|
|
40
|
-
}
|
|
41
|
-
catch {
|
|
42
|
-
return false;
|
|
43
|
-
}
|
|
13
|
+
return tryGitCommand(['rev-parse', '--is-inside-work-tree']);
|
|
44
14
|
}
|
|
45
15
|
/**
|
|
46
16
|
* Get the path to the .git directory
|
|
@@ -48,7 +18,7 @@ export function isGitRepository() {
|
|
|
48
18
|
* @throws Error if not in a git repository
|
|
49
19
|
*/
|
|
50
20
|
export function getGitDir() {
|
|
51
|
-
return execGitCommand('
|
|
21
|
+
return execGitCommand(['rev-parse', '--git-dir']);
|
|
52
22
|
}
|
|
53
23
|
/**
|
|
54
24
|
* Get the root directory of the git repository
|
|
@@ -56,7 +26,7 @@ export function getGitDir() {
|
|
|
56
26
|
* @throws Error if not in a git repository
|
|
57
27
|
*/
|
|
58
28
|
export function getRepositoryRoot() {
|
|
59
|
-
return execGitCommand('
|
|
29
|
+
return execGitCommand(['rev-parse', '--show-toplevel']);
|
|
60
30
|
}
|
|
61
31
|
/**
|
|
62
32
|
* Get the current branch name
|
|
@@ -64,7 +34,7 @@ export function getRepositoryRoot() {
|
|
|
64
34
|
* @throws Error if not on a branch (detached HEAD)
|
|
65
35
|
*/
|
|
66
36
|
export function getCurrentBranch() {
|
|
67
|
-
return execGitCommand('
|
|
37
|
+
return execGitCommand(['rev-parse', '--abbrev-ref', 'HEAD']);
|
|
68
38
|
}
|
|
69
39
|
/**
|
|
70
40
|
* Get the commit SHA of HEAD
|
|
@@ -72,7 +42,7 @@ export function getCurrentBranch() {
|
|
|
72
42
|
* @throws Error if not in a git repository or HEAD is invalid
|
|
73
43
|
*/
|
|
74
44
|
export function getHeadCommitSha() {
|
|
75
|
-
return execGitCommand('
|
|
45
|
+
return execGitCommand(['rev-parse', 'HEAD']);
|
|
76
46
|
}
|
|
77
47
|
/**
|
|
78
48
|
* Get the tree hash of the current HEAD commit
|
|
@@ -80,7 +50,7 @@ export function getHeadCommitSha() {
|
|
|
80
50
|
* @throws Error if not in a git repository or HEAD is invalid
|
|
81
51
|
*/
|
|
82
52
|
export function getHeadTreeSha() {
|
|
83
|
-
return execGitCommand('
|
|
53
|
+
return execGitCommand(['rev-parse', 'HEAD^{tree}']);
|
|
84
54
|
}
|
|
85
55
|
/**
|
|
86
56
|
* Verify that a git reference exists
|
|
@@ -88,13 +58,7 @@ export function getHeadTreeSha() {
|
|
|
88
58
|
* @returns true if the reference exists, false otherwise
|
|
89
59
|
*/
|
|
90
60
|
export function verifyRef(ref) {
|
|
91
|
-
|
|
92
|
-
execGitCommand(`git rev-parse --verify ${ref}`);
|
|
93
|
-
return true;
|
|
94
|
-
}
|
|
95
|
-
catch {
|
|
96
|
-
return false;
|
|
97
|
-
}
|
|
61
|
+
return tryGitCommand(['rev-parse', '--verify', ref]);
|
|
98
62
|
}
|
|
99
63
|
/**
|
|
100
64
|
* Verify that a git reference exists (alternate form for backwards compatibility)
|
|
@@ -103,7 +67,7 @@ export function verifyRef(ref) {
|
|
|
103
67
|
* @throws Error if the reference doesn't exist
|
|
104
68
|
*/
|
|
105
69
|
export function verifyRefOrThrow(ref) {
|
|
106
|
-
return execGitCommand(
|
|
70
|
+
return execGitCommand(['rev-parse', '--verify', ref]);
|
|
107
71
|
}
|
|
108
72
|
/**
|
|
109
73
|
* Check if git notes exist for a specific ref
|
|
@@ -111,16 +75,6 @@ export function verifyRefOrThrow(ref) {
|
|
|
111
75
|
* @returns true if the notes ref exists, false otherwise
|
|
112
76
|
*/
|
|
113
77
|
export function hasNotesRef(notesRef) {
|
|
114
|
-
|
|
115
|
-
// Use || true to prevent error when notes don't exist
|
|
116
|
-
const result = execSync(`git rev-parse --verify ${notesRef} 2>/dev/null || true`, {
|
|
117
|
-
encoding: 'utf8',
|
|
118
|
-
timeout: GIT_OPTIONS.timeout,
|
|
119
|
-
}).trim();
|
|
120
|
-
return result.length > 0;
|
|
121
|
-
}
|
|
122
|
-
catch {
|
|
123
|
-
return false;
|
|
124
|
-
}
|
|
78
|
+
return tryGitCommand(['rev-parse', '--verify', notesRef]);
|
|
125
79
|
}
|
|
126
80
|
//# sourceMappingURL=git-commands.js.map
|
package/dist/git-commands.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"git-commands.js","sourceRoot":"","sources":["../src/git-commands.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"git-commands.js","sourceRoot":"","sources":["../src/git-commands.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAElE;;;GAGG;AACH,MAAM,UAAU,eAAe;IAC7B,OAAO,aAAa,CAAC,CAAC,WAAW,EAAE,uBAAuB,CAAC,CAAC,CAAC;AAC/D,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,SAAS;IACvB,OAAO,cAAc,CAAC,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC,CAAC;AACpD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,iBAAiB;IAC/B,OAAO,cAAc,CAAC,CAAC,WAAW,EAAE,iBAAiB,CAAC,CAAC,CAAC;AAC1D,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,gBAAgB;IAC9B,OAAO,cAAc,CAAC,CAAC,WAAW,EAAE,cAAc,EAAE,MAAM,CAAC,CAAC,CAAC;AAC/D,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,gBAAgB;IAC9B,OAAO,cAAc,CAAC,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC,CAAC;AAC/C,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc;IAC5B,OAAO,cAAc,CAAC,CAAC,WAAW,EAAE,aAAa,CAAC,CAAC,CAAC;AACtD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,SAAS,CAAC,GAAW;IACnC,OAAO,aAAa,CAAC,CAAC,WAAW,EAAE,UAAU,EAAE,GAAG,CAAC,CAAC,CAAC;AACvD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAAC,GAAW;IAC1C,OAAO,cAAc,CAAC,CAAC,WAAW,EAAE,UAAU,EAAE,GAAG,CAAC,CAAC,CAAC;AACxD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,WAAW,CAAC,QAAgB;IAC1C,OAAO,aAAa,CAAC,CAAC,WAAW,EAAE,UAAU,EAAE,QAAQ,CAAC,CAAC,CAAC;AAC5D,CAAC"}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Secure Git Command Execution
|
|
3
|
+
*
|
|
4
|
+
* This module provides a centralized, secure way to execute git commands.
|
|
5
|
+
* ALL git command execution in vibe-validate MUST go through this module.
|
|
6
|
+
*
|
|
7
|
+
* Security principles:
|
|
8
|
+
* 1. Use spawnSync with array arguments (never string interpolation)
|
|
9
|
+
* 2. Validate all user-controlled inputs
|
|
10
|
+
* 3. No shell piping or heredocs
|
|
11
|
+
* 4. Explicit argument construction
|
|
12
|
+
*
|
|
13
|
+
* @packageDocumentation
|
|
14
|
+
*/
|
|
15
|
+
export interface GitExecutionOptions {
|
|
16
|
+
/**
|
|
17
|
+
* Maximum time to wait for git command (ms)
|
|
18
|
+
* @default 30000
|
|
19
|
+
*/
|
|
20
|
+
timeout?: number;
|
|
21
|
+
/**
|
|
22
|
+
* Encoding for stdout/stderr
|
|
23
|
+
* @default 'utf8'
|
|
24
|
+
*/
|
|
25
|
+
encoding?: BufferEncoding;
|
|
26
|
+
/**
|
|
27
|
+
* Standard input to pass to command
|
|
28
|
+
*/
|
|
29
|
+
stdin?: string;
|
|
30
|
+
/**
|
|
31
|
+
* Whether to ignore errors (return empty string instead of throwing)
|
|
32
|
+
* @default false
|
|
33
|
+
*/
|
|
34
|
+
ignoreErrors?: boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Whether to suppress stderr
|
|
37
|
+
* @default false
|
|
38
|
+
*/
|
|
39
|
+
suppressStderr?: boolean;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Result of a git command execution
|
|
43
|
+
*/
|
|
44
|
+
export interface GitExecutionResult {
|
|
45
|
+
/** Standard output from the command */
|
|
46
|
+
stdout: string;
|
|
47
|
+
/** Standard error from the command */
|
|
48
|
+
stderr: string;
|
|
49
|
+
/** Exit code (0 for success) */
|
|
50
|
+
exitCode: number;
|
|
51
|
+
/** Whether the command succeeded */
|
|
52
|
+
success: boolean;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Error thrown when a git command fails
|
|
56
|
+
*/
|
|
57
|
+
export interface GitCommandError extends Error {
|
|
58
|
+
/** Exit code from the git command */
|
|
59
|
+
exitCode: number;
|
|
60
|
+
/** Standard error output */
|
|
61
|
+
stderr: string;
|
|
62
|
+
/** Standard output */
|
|
63
|
+
stdout: string;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Execute a git command securely using spawnSync with array arguments
|
|
67
|
+
*
|
|
68
|
+
* This is the ONLY function that should execute git commands. All other
|
|
69
|
+
* git operations must go through this function or higher-level abstractions.
|
|
70
|
+
*
|
|
71
|
+
* @param args - Git command arguments (e.g., ['rev-parse', '--git-dir'])
|
|
72
|
+
* @param options - Execution options
|
|
73
|
+
* @returns Execution result
|
|
74
|
+
* @throws Error if command fails and ignoreErrors is false
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* ```typescript
|
|
78
|
+
* // Get git directory
|
|
79
|
+
* const result = executeGitCommand(['rev-parse', '--git-dir']);
|
|
80
|
+
* console.log(result.stdout); // ".git"
|
|
81
|
+
*
|
|
82
|
+
* // Add note with stdin
|
|
83
|
+
* executeGitCommand(
|
|
84
|
+
* ['notes', '--ref=vibe-validate/validate', 'add', '-f', '-F', '-', treeHash],
|
|
85
|
+
* { stdin: noteContent }
|
|
86
|
+
* );
|
|
87
|
+
* ```
|
|
88
|
+
*/
|
|
89
|
+
export declare function executeGitCommand(args: string[], options?: GitExecutionOptions): GitExecutionResult;
|
|
90
|
+
/**
|
|
91
|
+
* Execute a git command and return stdout, throwing on error
|
|
92
|
+
*
|
|
93
|
+
* Convenience wrapper for the common case of executing a git command
|
|
94
|
+
* and only caring about the stdout result.
|
|
95
|
+
*
|
|
96
|
+
* @param args - Git command arguments
|
|
97
|
+
* @param options - Execution options
|
|
98
|
+
* @returns Command stdout, trimmed
|
|
99
|
+
* @throws Error if command fails
|
|
100
|
+
*/
|
|
101
|
+
export declare function execGitCommand(args: string[], options?: GitExecutionOptions): string;
|
|
102
|
+
/**
|
|
103
|
+
* Execute a git command and return success status (no throw)
|
|
104
|
+
*
|
|
105
|
+
* Useful for checking if a git operation would succeed without
|
|
106
|
+
* handling exceptions.
|
|
107
|
+
*
|
|
108
|
+
* @param args - Git command arguments
|
|
109
|
+
* @param options - Execution options
|
|
110
|
+
* @returns true if command succeeded, false otherwise
|
|
111
|
+
*/
|
|
112
|
+
export declare function tryGitCommand(args: string[], options?: GitExecutionOptions): boolean;
|
|
113
|
+
/**
|
|
114
|
+
* Validate that a string is safe to use as a git ref
|
|
115
|
+
*
|
|
116
|
+
* Git refs must:
|
|
117
|
+
* - Not contain special shell characters
|
|
118
|
+
* - Not start with a dash (looks like an option)
|
|
119
|
+
* - Not contain path traversal sequences
|
|
120
|
+
* - Match git's ref format rules
|
|
121
|
+
*
|
|
122
|
+
* @param ref - The ref to validate
|
|
123
|
+
* @throws Error if ref is invalid
|
|
124
|
+
*/
|
|
125
|
+
export declare function validateGitRef(ref: string): void;
|
|
126
|
+
/**
|
|
127
|
+
* Validate that a string is safe to use as a git notes ref
|
|
128
|
+
*
|
|
129
|
+
* Notes refs have additional restrictions beyond normal refs.
|
|
130
|
+
*
|
|
131
|
+
* @param notesRef - The notes ref to validate
|
|
132
|
+
* @throws Error if notes ref is invalid
|
|
133
|
+
*/
|
|
134
|
+
export declare function validateNotesRef(notesRef: string): void;
|
|
135
|
+
/**
|
|
136
|
+
* Validate that a string is safe to use as a tree hash
|
|
137
|
+
*
|
|
138
|
+
* Tree hashes must be valid git object IDs (40-char hex or abbreviated).
|
|
139
|
+
*
|
|
140
|
+
* @param treeHash - The tree hash to validate
|
|
141
|
+
* @throws Error if tree hash is invalid
|
|
142
|
+
*/
|
|
143
|
+
export declare function validateTreeHash(treeHash: string): void;
|
|
144
|
+
//# sourceMappingURL=git-executor.d.ts.map
|
|
@@ -0,0 +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;CAC1B;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;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,GAAE,mBAAwB,GAChC,kBAAkB,CAqDpB;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,CAWvD;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAcvD"}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Secure Git Command Execution
|
|
3
|
+
*
|
|
4
|
+
* This module provides a centralized, secure way to execute git commands.
|
|
5
|
+
* ALL git command execution in vibe-validate MUST go through this module.
|
|
6
|
+
*
|
|
7
|
+
* Security principles:
|
|
8
|
+
* 1. Use spawnSync with array arguments (never string interpolation)
|
|
9
|
+
* 2. Validate all user-controlled inputs
|
|
10
|
+
* 3. No shell piping or heredocs
|
|
11
|
+
* 4. Explicit argument construction
|
|
12
|
+
*
|
|
13
|
+
* @packageDocumentation
|
|
14
|
+
*/
|
|
15
|
+
import { spawnSync } from 'node:child_process';
|
|
16
|
+
/**
|
|
17
|
+
* Standard options for git command execution
|
|
18
|
+
*/
|
|
19
|
+
const GIT_TIMEOUT = 30000; // 30 seconds
|
|
20
|
+
/**
|
|
21
|
+
* Execute a git command securely using spawnSync with array arguments
|
|
22
|
+
*
|
|
23
|
+
* This is the ONLY function that should execute git commands. All other
|
|
24
|
+
* git operations must go through this function or higher-level abstractions.
|
|
25
|
+
*
|
|
26
|
+
* @param args - Git command arguments (e.g., ['rev-parse', '--git-dir'])
|
|
27
|
+
* @param options - Execution options
|
|
28
|
+
* @returns Execution result
|
|
29
|
+
* @throws Error if command fails and ignoreErrors is false
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```typescript
|
|
33
|
+
* // Get git directory
|
|
34
|
+
* const result = executeGitCommand(['rev-parse', '--git-dir']);
|
|
35
|
+
* console.log(result.stdout); // ".git"
|
|
36
|
+
*
|
|
37
|
+
* // Add note with stdin
|
|
38
|
+
* executeGitCommand(
|
|
39
|
+
* ['notes', '--ref=vibe-validate/validate', 'add', '-f', '-F', '-', treeHash],
|
|
40
|
+
* { stdin: noteContent }
|
|
41
|
+
* );
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
export function executeGitCommand(args, options = {}) {
|
|
45
|
+
const { timeout = GIT_TIMEOUT, encoding = 'utf8', stdin, ignoreErrors = false, suppressStderr = false, } = options;
|
|
46
|
+
// Validate arguments
|
|
47
|
+
if (!Array.isArray(args) || args.length === 0) {
|
|
48
|
+
throw new Error('Git command arguments must be a non-empty array');
|
|
49
|
+
}
|
|
50
|
+
// Build spawn options
|
|
51
|
+
const spawnOptions = {
|
|
52
|
+
encoding,
|
|
53
|
+
timeout,
|
|
54
|
+
maxBuffer: 10 * 1024 * 1024, // 10MB buffer
|
|
55
|
+
};
|
|
56
|
+
// Configure stdio
|
|
57
|
+
if (stdin !== undefined) {
|
|
58
|
+
spawnOptions.input = stdin;
|
|
59
|
+
spawnOptions.stdio = ['pipe', 'pipe', suppressStderr ? 'ignore' : 'pipe'];
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
spawnOptions.stdio = ['ignore', 'pipe', suppressStderr ? 'ignore' : 'pipe'];
|
|
63
|
+
}
|
|
64
|
+
// Execute command
|
|
65
|
+
const result = spawnSync('git', args, spawnOptions);
|
|
66
|
+
const stdout = (result.stdout?.toString() || '').trim();
|
|
67
|
+
const stderr = (result.stderr?.toString() || '').trim();
|
|
68
|
+
const exitCode = result.status ?? 1;
|
|
69
|
+
const success = exitCode === 0;
|
|
70
|
+
// Handle errors
|
|
71
|
+
if (success || ignoreErrors) {
|
|
72
|
+
return {
|
|
73
|
+
stdout,
|
|
74
|
+
stderr,
|
|
75
|
+
exitCode,
|
|
76
|
+
success,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
const errorMessage = stderr || stdout || 'Git command failed';
|
|
80
|
+
const error = new Error(`Git command failed: git ${args.join(' ')}\n${errorMessage}`);
|
|
81
|
+
error.exitCode = exitCode;
|
|
82
|
+
error.stderr = stderr;
|
|
83
|
+
error.stdout = stdout;
|
|
84
|
+
throw error;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Execute a git command and return stdout, throwing on error
|
|
88
|
+
*
|
|
89
|
+
* Convenience wrapper for the common case of executing a git command
|
|
90
|
+
* and only caring about the stdout result.
|
|
91
|
+
*
|
|
92
|
+
* @param args - Git command arguments
|
|
93
|
+
* @param options - Execution options
|
|
94
|
+
* @returns Command stdout, trimmed
|
|
95
|
+
* @throws Error if command fails
|
|
96
|
+
*/
|
|
97
|
+
export function execGitCommand(args, options = {}) {
|
|
98
|
+
const result = executeGitCommand(args, options);
|
|
99
|
+
return result.stdout;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Execute a git command and return success status (no throw)
|
|
103
|
+
*
|
|
104
|
+
* Useful for checking if a git operation would succeed without
|
|
105
|
+
* handling exceptions.
|
|
106
|
+
*
|
|
107
|
+
* @param args - Git command arguments
|
|
108
|
+
* @param options - Execution options
|
|
109
|
+
* @returns true if command succeeded, false otherwise
|
|
110
|
+
*/
|
|
111
|
+
export function tryGitCommand(args, options = {}) {
|
|
112
|
+
const result = executeGitCommand(args, { ...options, ignoreErrors: true });
|
|
113
|
+
return result.success;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Validate that a string is safe to use as a git ref
|
|
117
|
+
*
|
|
118
|
+
* Git refs must:
|
|
119
|
+
* - Not contain special shell characters
|
|
120
|
+
* - Not start with a dash (looks like an option)
|
|
121
|
+
* - Not contain path traversal sequences
|
|
122
|
+
* - Match git's ref format rules
|
|
123
|
+
*
|
|
124
|
+
* @param ref - The ref to validate
|
|
125
|
+
* @throws Error if ref is invalid
|
|
126
|
+
*/
|
|
127
|
+
export function validateGitRef(ref) {
|
|
128
|
+
if (typeof ref !== 'string' || ref.length === 0) {
|
|
129
|
+
throw new Error('Git ref must be a non-empty string');
|
|
130
|
+
}
|
|
131
|
+
// Check for shell special characters
|
|
132
|
+
if (/[;&|`$(){}[\]<>!\\"]/.test(ref)) {
|
|
133
|
+
throw new Error(`Invalid git ref: contains shell special characters: ${ref}`);
|
|
134
|
+
}
|
|
135
|
+
// Check for leading dash (looks like an option)
|
|
136
|
+
if (ref.startsWith('-')) {
|
|
137
|
+
throw new Error(`Invalid git ref: starts with dash: ${ref}`);
|
|
138
|
+
}
|
|
139
|
+
// Check for path traversal
|
|
140
|
+
if (ref.includes('..') || ref.includes('//')) {
|
|
141
|
+
throw new Error(`Invalid git ref: contains path traversal: ${ref}`);
|
|
142
|
+
}
|
|
143
|
+
// Check for null bytes
|
|
144
|
+
if (ref.includes('\0')) {
|
|
145
|
+
throw new Error('Invalid git ref: contains null byte');
|
|
146
|
+
}
|
|
147
|
+
// Check for newlines (could break command)
|
|
148
|
+
if (ref.includes('\n') || ref.includes('\r')) {
|
|
149
|
+
throw new Error('Invalid git ref: contains newline');
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Validate that a string is safe to use as a git notes ref
|
|
154
|
+
*
|
|
155
|
+
* Notes refs have additional restrictions beyond normal refs.
|
|
156
|
+
*
|
|
157
|
+
* @param notesRef - The notes ref to validate
|
|
158
|
+
* @throws Error if notes ref is invalid
|
|
159
|
+
*/
|
|
160
|
+
export function validateNotesRef(notesRef) {
|
|
161
|
+
validateGitRef(notesRef);
|
|
162
|
+
// Notes refs should follow refs/notes/* pattern or short form
|
|
163
|
+
// Short form: 'vibe-validate/validate' → 'refs/notes/vibe-validate/validate'
|
|
164
|
+
if (!notesRef.startsWith('refs/notes/') && notesRef.includes('/')) {
|
|
165
|
+
// Short form is valid, but must not contain spaces
|
|
166
|
+
if (/\s/.test(notesRef)) {
|
|
167
|
+
throw new Error(`Invalid notes ref: contains whitespace: ${notesRef}`);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Validate that a string is safe to use as a tree hash
|
|
173
|
+
*
|
|
174
|
+
* Tree hashes must be valid git object IDs (40-char hex or abbreviated).
|
|
175
|
+
*
|
|
176
|
+
* @param treeHash - The tree hash to validate
|
|
177
|
+
* @throws Error if tree hash is invalid
|
|
178
|
+
*/
|
|
179
|
+
export function validateTreeHash(treeHash) {
|
|
180
|
+
if (typeof treeHash !== 'string' || treeHash.length === 0) {
|
|
181
|
+
throw new Error('Tree hash must be a non-empty string');
|
|
182
|
+
}
|
|
183
|
+
// Must be hex characters only
|
|
184
|
+
if (!/^[0-9a-f]+$/.test(treeHash)) {
|
|
185
|
+
throw new Error(`Invalid tree hash: must be hexadecimal: ${treeHash}`);
|
|
186
|
+
}
|
|
187
|
+
// Must be reasonable length (4-40 chars for abbreviated or full hash)
|
|
188
|
+
if (treeHash.length < 4 || treeHash.length > 40) {
|
|
189
|
+
throw new Error(`Invalid tree hash: invalid length: ${treeHash}`);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
//# sourceMappingURL=git-executor.js.map
|
|
@@ -0,0 +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;AA2DxC;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,UAAU,iBAAiB,CAC/B,IAAc,EACd,UAA+B,EAAE;IAEjC,MAAM,EACJ,OAAO,GAAG,WAAW,EACrB,QAAQ,GAAG,MAAM,EACjB,KAAK,EACL,YAAY,GAAG,KAAK,EACpB,cAAc,GAAG,KAAK,GACvB,GAAG,OAAO,CAAC;IAEZ,qBAAqB;IACrB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC9C,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;IACrE,CAAC;IAED,sBAAsB;IACtB,MAAM,YAAY,GAAqB;QACrC,QAAQ;QACR,OAAO;QACP,SAAS,EAAE,EAAE,GAAG,IAAI,GAAG,IAAI,EAAE,cAAc;KAC5C,CAAC;IAEF,kBAAkB;IAClB,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,YAAY,CAAC,KAAK,GAAG,KAAK,CAAC;QAC3B,YAAY,CAAC,KAAK,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,cAAc,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;IAC5E,CAAC;SAAM,CAAC;QACN,YAAY,CAAC,KAAK,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,cAAc,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;IAC9E,CAAC;IAED,kBAAkB;IAClB,MAAM,MAAM,GAAG,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,YAAY,CAAC,CAAC;IAEpD,MAAM,MAAM,GAAG,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACxD,MAAM,MAAM,GAAG,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACxD,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC;IACpC,MAAM,OAAO,GAAG,QAAQ,KAAK,CAAC,CAAC;IAE/B,gBAAgB;IAChB,IAAI,OAAO,IAAI,YAAY,EAAE,CAAC;QAC5B,OAAO;YACL,MAAM;YACN,MAAM;YACN,QAAQ;YACR,OAAO;SACR,CAAC;IACJ,CAAC;IAED,MAAM,YAAY,GAAG,MAAM,IAAI,MAAM,IAAI,oBAAoB,CAAC;IAC9D,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,2BAA2B,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,YAAY,EAAE,CAAoB,CAAC;IACzG,KAAK,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC1B,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC;IACtB,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC;IACtB,MAAM,KAAK,CAAC;AACd,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,cAAc,CAAC,IAAc,EAAE,UAA+B,EAAE;IAC9E,MAAM,MAAM,GAAG,iBAAiB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAChD,OAAO,MAAM,CAAC,MAAM,CAAC;AACvB,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,aAAa,CAAC,IAAc,EAAE,UAA+B,EAAE;IAC7E,MAAM,MAAM,GAAG,iBAAiB,CAAC,IAAI,EAAE,EAAE,GAAG,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3E,OAAO,MAAM,CAAC,OAAO,CAAC;AACxB,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,cAAc,CAAC,GAAW;IACxC,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAChD,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;IACxD,CAAC;IAED,qCAAqC;IACrC,IAAI,sBAAsB,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QACrC,MAAM,IAAI,KAAK,CAAC,uDAAuD,GAAG,EAAE,CAAC,CAAC;IAChF,CAAC;IAED,gDAAgD;IAChD,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,sCAAsC,GAAG,EAAE,CAAC,CAAC;IAC/D,CAAC;IAED,2BAA2B;IAC3B,IAAI,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QAC7C,MAAM,IAAI,KAAK,CAAC,6CAA6C,GAAG,EAAE,CAAC,CAAC;IACtE,CAAC;IAED,uBAAuB;IACvB,IAAI,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;IACzD,CAAC;IAED,2CAA2C;IAC3C,IAAI,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QAC7C,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;IACvD,CAAC;AACH,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,gBAAgB,CAAC,QAAgB;IAC/C,cAAc,CAAC,QAAQ,CAAC,CAAC;IAEzB,8DAA8D;IAC9D,6EAA6E;IAC7E,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,aAAa,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QAClE,mDAAmD;QACnD,IAAI,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;YACxB,MAAM,IAAI,KAAK,CAAC,2CAA2C,QAAQ,EAAE,CAAC,CAAC;QACzE,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,gBAAgB,CAAC,QAAgB;IAC/C,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1D,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;IAC1D,CAAC;IAED,8BAA8B;IAC9B,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;QAClC,MAAM,IAAI,KAAK,CAAC,2CAA2C,QAAQ,EAAE,CAAC,CAAC;IACzE,CAAC;IAED,sEAAsE;IACtE,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,IAAI,QAAQ,CAAC,MAAM,GAAG,EAAE,EAAE,CAAC;QAChD,MAAM,IAAI,KAAK,CAAC,sCAAsC,QAAQ,EAAE,CAAC,CAAC;IACpE,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Git Notes Operations
|
|
3
|
+
*
|
|
4
|
+
* High-level abstraction for git notes operations. All notes-related
|
|
5
|
+
* commands in vibe-validate must use these functions.
|
|
6
|
+
*
|
|
7
|
+
* @packageDocumentation
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Add or update a git note
|
|
11
|
+
*
|
|
12
|
+
* @param notesRef - The notes reference (e.g., 'vibe-validate/validate')
|
|
13
|
+
* @param object - The git object to attach the note to (tree hash, commit SHA, etc.)
|
|
14
|
+
* @param content - The note content
|
|
15
|
+
* @param force - Whether to overwrite existing note
|
|
16
|
+
* @returns true if note was added successfully
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```typescript
|
|
20
|
+
* addNote('vibe-validate/validate', treeHash, noteContent, true);
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export declare function addNote(notesRef: string, object: string, content: string, force?: boolean): boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Read a git note
|
|
26
|
+
*
|
|
27
|
+
* @param notesRef - The notes reference
|
|
28
|
+
* @param object - The git object to read the note from
|
|
29
|
+
* @returns The note content, or null if no note exists
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```typescript
|
|
33
|
+
* const note = readNote('vibe-validate/validate', treeHash);
|
|
34
|
+
* if (note) {
|
|
35
|
+
* console.log('Note content:', note);
|
|
36
|
+
* }
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
export declare function readNote(notesRef: string, object: string): string | null;
|
|
40
|
+
/**
|
|
41
|
+
* Remove a git note
|
|
42
|
+
*
|
|
43
|
+
* @param notesRef - The notes reference
|
|
44
|
+
* @param object - The git object to remove the note from
|
|
45
|
+
* @returns true if note was removed, false if it didn't exist
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* ```typescript
|
|
49
|
+
* const removed = removeNote('vibe-validate/validate', treeHash);
|
|
50
|
+
* console.log(removed ? 'Removed' : 'Did not exist');
|
|
51
|
+
* ```
|
|
52
|
+
*/
|
|
53
|
+
export declare function removeNote(notesRef: string, object: string): boolean;
|
|
54
|
+
/**
|
|
55
|
+
* List all notes in a notes reference
|
|
56
|
+
*
|
|
57
|
+
* @param notesRef - The notes reference
|
|
58
|
+
* @returns Array of [object, content] pairs, or empty array if no notes
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* ```typescript
|
|
62
|
+
* const notes = listNotes('vibe-validate/validate');
|
|
63
|
+
* for (const [treeHash, content] of notes) {
|
|
64
|
+
* console.log(`${treeHash}: ${content}`);
|
|
65
|
+
* }
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
68
|
+
export declare function listNotes(notesRef: string): Array<[string, string]>;
|
|
69
|
+
/**
|
|
70
|
+
* Check if a note exists
|
|
71
|
+
*
|
|
72
|
+
* @param notesRef - The notes reference
|
|
73
|
+
* @param object - The git object to check
|
|
74
|
+
* @returns true if note exists, false otherwise
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* ```typescript
|
|
78
|
+
* if (hasNote('vibe-validate/validate', treeHash)) {
|
|
79
|
+
* console.log('Note exists');
|
|
80
|
+
* }
|
|
81
|
+
* ```
|
|
82
|
+
*/
|
|
83
|
+
export declare function hasNote(notesRef: string, object: string): boolean;
|
|
84
|
+
/**
|
|
85
|
+
* List all refs under a notes namespace
|
|
86
|
+
*
|
|
87
|
+
* This is useful for finding all notes under a particular path,
|
|
88
|
+
* such as all run cache entries under refs/notes/vibe-validate/run/
|
|
89
|
+
*
|
|
90
|
+
* @param notesPath - The notes path (e.g., 'refs/notes/vibe-validate/run')
|
|
91
|
+
* @returns Array of full ref names
|
|
92
|
+
*
|
|
93
|
+
* @example
|
|
94
|
+
* ```typescript
|
|
95
|
+
* const refs = listNotesRefs('refs/notes/vibe-validate/run');
|
|
96
|
+
* for (const ref of refs) {
|
|
97
|
+
* console.log('Found note ref:', ref);
|
|
98
|
+
* }
|
|
99
|
+
* ```
|
|
100
|
+
*/
|
|
101
|
+
export declare function listNotesRefs(notesPath: string): string[];
|
|
102
|
+
/**
|
|
103
|
+
* Remove all notes refs under a namespace
|
|
104
|
+
*
|
|
105
|
+
* This is used for bulk cleanup operations, such as pruning all
|
|
106
|
+
* run cache entries under a tree hash.
|
|
107
|
+
*
|
|
108
|
+
* SECURITY: This function validates each ref before deletion to prevent
|
|
109
|
+
* accidental deletion of non-notes refs.
|
|
110
|
+
*
|
|
111
|
+
* @param notesPath - The notes path (e.g., 'refs/notes/vibe-validate/run/abc123')
|
|
112
|
+
* @returns Number of refs deleted
|
|
113
|
+
*
|
|
114
|
+
* @example
|
|
115
|
+
* ```typescript
|
|
116
|
+
* const deleted = removeNotesRefs('refs/notes/vibe-validate/run/abc123');
|
|
117
|
+
* console.log(`Deleted ${deleted} refs`);
|
|
118
|
+
* ```
|
|
119
|
+
*/
|
|
120
|
+
export declare function removeNotesRefs(notesPath: string): number;
|
|
121
|
+
/**
|
|
122
|
+
* Check if a notes ref exists
|
|
123
|
+
*
|
|
124
|
+
* @param notesRef - The notes reference
|
|
125
|
+
* @returns true if the notes ref exists, false otherwise
|
|
126
|
+
*
|
|
127
|
+
* @example
|
|
128
|
+
* ```typescript
|
|
129
|
+
* if (hasNotesRef('vibe-validate/validate')) {
|
|
130
|
+
* console.log('Notes ref exists');
|
|
131
|
+
* }
|
|
132
|
+
* ```
|
|
133
|
+
*/
|
|
134
|
+
export declare function hasNotesRef(notesRef: string): boolean;
|
|
135
|
+
/**
|
|
136
|
+
* Get the commit SHA that a notes ref points to
|
|
137
|
+
*
|
|
138
|
+
* @param notesRef - The notes reference
|
|
139
|
+
* @returns The commit SHA, or null if ref doesn't exist
|
|
140
|
+
*/
|
|
141
|
+
export declare function getNotesRefSha(notesRef: string): string | null;
|
|
142
|
+
//# sourceMappingURL=git-notes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-notes.d.ts","sourceRoot":"","sources":["../src/git-notes.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AASH;;;;;;;;;;;;;GAaG;AACH,wBAAgB,OAAO,CACrB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,KAAK,GAAE,OAAe,GACrB,OAAO,CAiBT;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAUxE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAOpE;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CA4BnE;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAOjE;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"}
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Git Notes Operations
|
|
3
|
+
*
|
|
4
|
+
* High-level abstraction for git notes operations. All notes-related
|
|
5
|
+
* commands in vibe-validate must use these functions.
|
|
6
|
+
*
|
|
7
|
+
* @packageDocumentation
|
|
8
|
+
*/
|
|
9
|
+
import { executeGitCommand, tryGitCommand, validateNotesRef, validateTreeHash, } from './git-executor.js';
|
|
10
|
+
/**
|
|
11
|
+
* Add or update a git note
|
|
12
|
+
*
|
|
13
|
+
* @param notesRef - The notes reference (e.g., 'vibe-validate/validate')
|
|
14
|
+
* @param object - The git object to attach the note to (tree hash, commit SHA, etc.)
|
|
15
|
+
* @param content - The note content
|
|
16
|
+
* @param force - Whether to overwrite existing note
|
|
17
|
+
* @returns true if note was added successfully
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```typescript
|
|
21
|
+
* addNote('vibe-validate/validate', treeHash, noteContent, true);
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export function addNote(notesRef, object, content, force = false) {
|
|
25
|
+
validateNotesRef(notesRef);
|
|
26
|
+
validateTreeHash(object);
|
|
27
|
+
const args = ['notes', `--ref=${notesRef}`, 'add'];
|
|
28
|
+
if (force) {
|
|
29
|
+
args.push('-f');
|
|
30
|
+
}
|
|
31
|
+
args.push('-F', '-', object);
|
|
32
|
+
const result = executeGitCommand(args, {
|
|
33
|
+
stdin: content,
|
|
34
|
+
ignoreErrors: true,
|
|
35
|
+
suppressStderr: true,
|
|
36
|
+
});
|
|
37
|
+
return result.success;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Read a git note
|
|
41
|
+
*
|
|
42
|
+
* @param notesRef - The notes reference
|
|
43
|
+
* @param object - The git object to read the note from
|
|
44
|
+
* @returns The note content, or null if no note exists
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```typescript
|
|
48
|
+
* const note = readNote('vibe-validate/validate', treeHash);
|
|
49
|
+
* if (note) {
|
|
50
|
+
* console.log('Note content:', note);
|
|
51
|
+
* }
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
54
|
+
export function readNote(notesRef, object) {
|
|
55
|
+
validateNotesRef(notesRef);
|
|
56
|
+
validateTreeHash(object);
|
|
57
|
+
const result = executeGitCommand(['notes', `--ref=${notesRef}`, 'show', object], {
|
|
58
|
+
ignoreErrors: true,
|
|
59
|
+
suppressStderr: true,
|
|
60
|
+
});
|
|
61
|
+
return result.success ? result.stdout : null;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Remove a git note
|
|
65
|
+
*
|
|
66
|
+
* @param notesRef - The notes reference
|
|
67
|
+
* @param object - The git object to remove the note from
|
|
68
|
+
* @returns true if note was removed, false if it didn't exist
|
|
69
|
+
*
|
|
70
|
+
* @example
|
|
71
|
+
* ```typescript
|
|
72
|
+
* const removed = removeNote('vibe-validate/validate', treeHash);
|
|
73
|
+
* console.log(removed ? 'Removed' : 'Did not exist');
|
|
74
|
+
* ```
|
|
75
|
+
*/
|
|
76
|
+
export function removeNote(notesRef, object) {
|
|
77
|
+
validateNotesRef(notesRef);
|
|
78
|
+
validateTreeHash(object);
|
|
79
|
+
return tryGitCommand(['notes', `--ref=${notesRef}`, 'remove', object], {
|
|
80
|
+
suppressStderr: true,
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* List all notes in a notes reference
|
|
85
|
+
*
|
|
86
|
+
* @param notesRef - The notes reference
|
|
87
|
+
* @returns Array of [object, content] pairs, or empty array if no notes
|
|
88
|
+
*
|
|
89
|
+
* @example
|
|
90
|
+
* ```typescript
|
|
91
|
+
* const notes = listNotes('vibe-validate/validate');
|
|
92
|
+
* for (const [treeHash, content] of notes) {
|
|
93
|
+
* console.log(`${treeHash}: ${content}`);
|
|
94
|
+
* }
|
|
95
|
+
* ```
|
|
96
|
+
*/
|
|
97
|
+
export function listNotes(notesRef) {
|
|
98
|
+
validateNotesRef(notesRef);
|
|
99
|
+
// Get list of objects that have notes
|
|
100
|
+
const objectsResult = executeGitCommand(['notes', `--ref=${notesRef}`, 'list'], {
|
|
101
|
+
ignoreErrors: true,
|
|
102
|
+
suppressStderr: true,
|
|
103
|
+
});
|
|
104
|
+
if (!objectsResult.success || !objectsResult.stdout) {
|
|
105
|
+
return [];
|
|
106
|
+
}
|
|
107
|
+
const notes = [];
|
|
108
|
+
// Parse "note_sha object_sha" pairs
|
|
109
|
+
for (const line of objectsResult.stdout.split('\n')) {
|
|
110
|
+
const [, objectSha] = line.split(/\s+/);
|
|
111
|
+
if (!objectSha)
|
|
112
|
+
continue;
|
|
113
|
+
// Read the note content
|
|
114
|
+
const content = readNote(notesRef, objectSha);
|
|
115
|
+
if (content !== null) {
|
|
116
|
+
notes.push([objectSha, content]);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return notes;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Check if a note exists
|
|
123
|
+
*
|
|
124
|
+
* @param notesRef - The notes reference
|
|
125
|
+
* @param object - The git object to check
|
|
126
|
+
* @returns true if note exists, false otherwise
|
|
127
|
+
*
|
|
128
|
+
* @example
|
|
129
|
+
* ```typescript
|
|
130
|
+
* if (hasNote('vibe-validate/validate', treeHash)) {
|
|
131
|
+
* console.log('Note exists');
|
|
132
|
+
* }
|
|
133
|
+
* ```
|
|
134
|
+
*/
|
|
135
|
+
export function hasNote(notesRef, object) {
|
|
136
|
+
validateNotesRef(notesRef);
|
|
137
|
+
validateTreeHash(object);
|
|
138
|
+
return tryGitCommand(['notes', `--ref=${notesRef}`, 'show', object], {
|
|
139
|
+
suppressStderr: true,
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* List all refs under a notes namespace
|
|
144
|
+
*
|
|
145
|
+
* This is useful for finding all notes under a particular path,
|
|
146
|
+
* such as all run cache entries under refs/notes/vibe-validate/run/
|
|
147
|
+
*
|
|
148
|
+
* @param notesPath - The notes path (e.g., 'refs/notes/vibe-validate/run')
|
|
149
|
+
* @returns Array of full ref names
|
|
150
|
+
*
|
|
151
|
+
* @example
|
|
152
|
+
* ```typescript
|
|
153
|
+
* const refs = listNotesRefs('refs/notes/vibe-validate/run');
|
|
154
|
+
* for (const ref of refs) {
|
|
155
|
+
* console.log('Found note ref:', ref);
|
|
156
|
+
* }
|
|
157
|
+
* ```
|
|
158
|
+
*/
|
|
159
|
+
export function listNotesRefs(notesPath) {
|
|
160
|
+
// Normalize path
|
|
161
|
+
const fullPath = notesPath.startsWith('refs/') ? notesPath : `refs/notes/${notesPath}`;
|
|
162
|
+
const result = executeGitCommand(['for-each-ref', '--format=%(refname)', fullPath], { ignoreErrors: true, suppressStderr: true });
|
|
163
|
+
if (!result.success || !result.stdout) {
|
|
164
|
+
return [];
|
|
165
|
+
}
|
|
166
|
+
return result.stdout.split('\n').filter(Boolean);
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Remove all notes refs under a namespace
|
|
170
|
+
*
|
|
171
|
+
* This is used for bulk cleanup operations, such as pruning all
|
|
172
|
+
* run cache entries under a tree hash.
|
|
173
|
+
*
|
|
174
|
+
* SECURITY: This function validates each ref before deletion to prevent
|
|
175
|
+
* accidental deletion of non-notes refs.
|
|
176
|
+
*
|
|
177
|
+
* @param notesPath - The notes path (e.g., 'refs/notes/vibe-validate/run/abc123')
|
|
178
|
+
* @returns Number of refs deleted
|
|
179
|
+
*
|
|
180
|
+
* @example
|
|
181
|
+
* ```typescript
|
|
182
|
+
* const deleted = removeNotesRefs('refs/notes/vibe-validate/run/abc123');
|
|
183
|
+
* console.log(`Deleted ${deleted} refs`);
|
|
184
|
+
* ```
|
|
185
|
+
*/
|
|
186
|
+
export function removeNotesRefs(notesPath) {
|
|
187
|
+
// Normalize path
|
|
188
|
+
const fullPath = notesPath.startsWith('refs/') ? notesPath : `refs/notes/${notesPath}`;
|
|
189
|
+
// Security: Only allow deletion under refs/notes/vibe-validate/
|
|
190
|
+
if (!fullPath.startsWith('refs/notes/vibe-validate/')) {
|
|
191
|
+
throw new Error(`Refusing to delete refs outside vibe-validate namespace: ${fullPath}`);
|
|
192
|
+
}
|
|
193
|
+
// Get list of refs
|
|
194
|
+
const refs = listNotesRefs(fullPath);
|
|
195
|
+
let deleted = 0;
|
|
196
|
+
for (const ref of refs) {
|
|
197
|
+
// Double-check each ref is under the expected namespace
|
|
198
|
+
if (!ref.startsWith('refs/notes/vibe-validate/')) {
|
|
199
|
+
console.warn(`Skipping ref outside vibe-validate namespace: ${ref}`);
|
|
200
|
+
continue;
|
|
201
|
+
}
|
|
202
|
+
const success = tryGitCommand(['update-ref', '-d', ref], {
|
|
203
|
+
suppressStderr: true,
|
|
204
|
+
});
|
|
205
|
+
if (success) {
|
|
206
|
+
deleted++;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
return deleted;
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Check if a notes ref exists
|
|
213
|
+
*
|
|
214
|
+
* @param notesRef - The notes reference
|
|
215
|
+
* @returns true if the notes ref exists, false otherwise
|
|
216
|
+
*
|
|
217
|
+
* @example
|
|
218
|
+
* ```typescript
|
|
219
|
+
* if (hasNotesRef('vibe-validate/validate')) {
|
|
220
|
+
* console.log('Notes ref exists');
|
|
221
|
+
* }
|
|
222
|
+
* ```
|
|
223
|
+
*/
|
|
224
|
+
export function hasNotesRef(notesRef) {
|
|
225
|
+
validateNotesRef(notesRef);
|
|
226
|
+
// Convert short form to full form if needed
|
|
227
|
+
const fullRef = notesRef.startsWith('refs/')
|
|
228
|
+
? notesRef
|
|
229
|
+
: `refs/notes/${notesRef}`;
|
|
230
|
+
return tryGitCommand(['rev-parse', '--verify', fullRef], {
|
|
231
|
+
suppressStderr: true,
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Get the commit SHA that a notes ref points to
|
|
236
|
+
*
|
|
237
|
+
* @param notesRef - The notes reference
|
|
238
|
+
* @returns The commit SHA, or null if ref doesn't exist
|
|
239
|
+
*/
|
|
240
|
+
export function getNotesRefSha(notesRef) {
|
|
241
|
+
validateNotesRef(notesRef);
|
|
242
|
+
const fullRef = notesRef.startsWith('refs/')
|
|
243
|
+
? notesRef
|
|
244
|
+
: `refs/notes/${notesRef}`;
|
|
245
|
+
const result = executeGitCommand(['rev-parse', '--verify', fullRef], {
|
|
246
|
+
ignoreErrors: true,
|
|
247
|
+
suppressStderr: true,
|
|
248
|
+
});
|
|
249
|
+
return result.success ? result.stdout : null;
|
|
250
|
+
}
|
|
251
|
+
//# sourceMappingURL=git-notes.js.map
|
|
@@ -0,0 +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;AAE3B;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,OAAO,CACrB,QAAgB,EAChB,MAAc,EACd,OAAe,EACf,QAAiB,KAAK;IAEtB,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IAC3B,gBAAgB,CAAC,MAAM,CAAC,CAAC;IAEzB,MAAM,IAAI,GAAG,CAAC,OAAO,EAAE,SAAS,QAAQ,EAAE,EAAE,KAAK,CAAC,CAAC;IACnD,IAAI,KAAK,EAAE,CAAC;QACV,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAClB,CAAC;IACD,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;IAE7B,MAAM,MAAM,GAAG,iBAAiB,CAAC,IAAI,EAAE;QACrC,KAAK,EAAE,OAAO;QACd,YAAY,EAAE,IAAI;QAClB,cAAc,EAAE,IAAI;KACrB,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC,OAAO,CAAC;AACxB,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,QAAQ,CAAC,QAAgB,EAAE,MAAc;IACvD,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IAC3B,gBAAgB,CAAC,MAAM,CAAC,CAAC;IAEzB,MAAM,MAAM,GAAG,iBAAiB,CAAC,CAAC,OAAO,EAAE,SAAS,QAAQ,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE;QAC/E,YAAY,EAAE,IAAI;QAClB,cAAc,EAAE,IAAI;KACrB,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;AAC/C,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,UAAU,CAAC,QAAgB,EAAE,MAAc;IACzD,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IAC3B,gBAAgB,CAAC,MAAM,CAAC,CAAC;IAEzB,OAAO,aAAa,CAAC,CAAC,OAAO,EAAE,SAAS,QAAQ,EAAE,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE;QACrE,cAAc,EAAE,IAAI;KACrB,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,SAAS,CAAC,QAAgB;IACxC,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IAE3B,sCAAsC;IACtC,MAAM,aAAa,GAAG,iBAAiB,CAAC,CAAC,OAAO,EAAE,SAAS,QAAQ,EAAE,EAAE,MAAM,CAAC,EAAE;QAC9E,YAAY,EAAE,IAAI;QAClB,cAAc,EAAE,IAAI;KACrB,CAAC,CAAC;IAEH,IAAI,CAAC,aAAa,CAAC,OAAO,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,CAAC;QACpD,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,KAAK,GAA4B,EAAE,CAAC;IAE1C,oCAAoC;IACpC,KAAK,MAAM,IAAI,IAAI,aAAa,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACpD,MAAM,CAAC,EAAE,SAAS,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACxC,IAAI,CAAC,SAAS;YAAE,SAAS;QAEzB,wBAAwB;QACxB,MAAM,OAAO,GAAG,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;QAC9C,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;YACrB,KAAK,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC;QACnC,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,OAAO,CAAC,QAAgB,EAAE,MAAc;IACtD,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IAC3B,gBAAgB,CAAC,MAAM,CAAC,CAAC;IAEzB,OAAO,aAAa,CAAC,CAAC,OAAO,EAAE,SAAS,QAAQ,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE;QACnE,cAAc,EAAE,IAAI;KACrB,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,aAAa,CAAC,SAAiB;IAC7C,iBAAiB;IACjB,MAAM,QAAQ,GAAG,SAAS,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,cAAc,SAAS,EAAE,CAAC;IAEvF,MAAM,MAAM,GAAG,iBAAiB,CAC9B,CAAC,cAAc,EAAE,qBAAqB,EAAE,QAAQ,CAAC,EACjD,EAAE,YAAY,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,CAC7C,CAAC;IAEF,IAAI,CAAC,MAAM,CAAC,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;QACtC,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,OAAO,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;AACnD,CAAC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,eAAe,CAAC,SAAiB;IAC/C,iBAAiB;IACjB,MAAM,QAAQ,GAAG,SAAS,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,cAAc,SAAS,EAAE,CAAC;IAEvF,gEAAgE;IAChE,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,2BAA2B,CAAC,EAAE,CAAC;QACtD,MAAM,IAAI,KAAK,CACb,4DAA4D,QAAQ,EAAE,CACvE,CAAC;IACJ,CAAC;IAED,mBAAmB;IACnB,MAAM,IAAI,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;IAErC,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,wDAAwD;QACxD,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,2BAA2B,CAAC,EAAE,CAAC;YACjD,OAAO,CAAC,IAAI,CAAC,iDAAiD,GAAG,EAAE,CAAC,CAAC;YACrE,SAAS;QACX,CAAC;QAED,MAAM,OAAO,GAAG,aAAa,CAAC,CAAC,YAAY,EAAE,IAAI,EAAE,GAAG,CAAC,EAAE;YACvD,cAAc,EAAE,IAAI;SACrB,CAAC,CAAC;QAEH,IAAI,OAAO,EAAE,CAAC;YACZ,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,WAAW,CAAC,QAAgB;IAC1C,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IAE3B,4CAA4C;IAC5C,MAAM,OAAO,GAAG,QAAQ,CAAC,UAAU,CAAC,OAAO,CAAC;QAC1C,CAAC,CAAC,QAAQ;QACV,CAAC,CAAC,cAAc,QAAQ,EAAE,CAAC;IAE7B,OAAO,aAAa,CAAC,CAAC,WAAW,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE;QACvD,cAAc,EAAE,IAAI;KACrB,CAAC,CAAC;AACL,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,QAAgB;IAC7C,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IAE3B,MAAM,OAAO,GAAG,QAAQ,CAAC,UAAU,CAAC,OAAO,CAAC;QAC1C,CAAC,CAAC,QAAQ;QACV,CAAC,CAAC,cAAc,QAAQ,EAAE,CAAC;IAE7B,MAAM,MAAM,GAAG,iBAAiB,CAAC,CAAC,WAAW,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE;QACnE,YAAY,EAAE,IAAI;QAClB,cAAc,EAAE,IAAI;KACrB,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;AAC/C,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -12,4 +12,6 @@ export { PostPRMergeCleanup, cleanupMergedBranches, type CleanupResult, type Cle
|
|
|
12
12
|
export { encodeRunCacheKey } from './cache-key.js';
|
|
13
13
|
export { extractYamlContent, extractYamlWithPreamble } from './yaml-detection.js';
|
|
14
14
|
export { isGitRepository, getGitDir, getRepositoryRoot, getCurrentBranch, getHeadCommitSha, getHeadTreeSha, verifyRef, verifyRefOrThrow, hasNotesRef } from './git-commands.js';
|
|
15
|
+
export { executeGitCommand, execGitCommand, tryGitCommand, validateGitRef, validateNotesRef, validateTreeHash, type GitExecutionOptions, type GitExecutionResult } from './git-executor.js';
|
|
16
|
+
export { addNote, readNote, removeNote, listNotes, hasNote, listNotesRefs, removeNotesRefs, getNotesRefSha } from './git-notes.js';
|
|
15
17
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EACL,cAAc,EACd,eAAe,EACf,qBAAqB,EACtB,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EACL,iBAAiB,EACjB,eAAe,EACf,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACtB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,kBAAkB,EAClB,qBAAqB,EACrB,KAAK,aAAa,EAClB,KAAK,cAAc,EACpB,MAAM,yBAAyB,CAAC;AAGjC,OAAO,EACL,iBAAiB,EAClB,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EACL,kBAAkB,EAClB,uBAAuB,EACxB,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EACL,eAAe,EACf,SAAS,EACT,iBAAiB,EACjB,gBAAgB,EAChB,gBAAgB,EAChB,cAAc,EACd,SAAS,EACT,gBAAgB,EAChB,WAAW,EACZ,MAAM,mBAAmB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EACL,cAAc,EACd,eAAe,EACf,qBAAqB,EACtB,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EACL,iBAAiB,EACjB,eAAe,EACf,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACtB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,kBAAkB,EAClB,qBAAqB,EACrB,KAAK,aAAa,EAClB,KAAK,cAAc,EACpB,MAAM,yBAAyB,CAAC;AAGjC,OAAO,EACL,iBAAiB,EAClB,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EACL,kBAAkB,EAClB,uBAAuB,EACxB,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EACL,eAAe,EACf,SAAS,EACT,iBAAiB,EACjB,gBAAgB,EAChB,gBAAgB,EAChB,cAAc,EACd,SAAS,EACT,gBAAgB,EAChB,WAAW,EACZ,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EACL,iBAAiB,EACjB,cAAc,EACd,aAAa,EACb,cAAc,EACd,gBAAgB,EAChB,gBAAgB,EAChB,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EACxB,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EACL,OAAO,EACP,QAAQ,EACR,UAAU,EACV,SAAS,EACT,OAAO,EACP,aAAa,EACb,eAAe,EACf,cAAc,EACf,MAAM,gBAAgB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -18,4 +18,8 @@ export { encodeRunCacheKey } from './cache-key.js';
|
|
|
18
18
|
export { extractYamlContent, extractYamlWithPreamble } from './yaml-detection.js';
|
|
19
19
|
// Git command utilities (standardized rev-parse operations)
|
|
20
20
|
export { isGitRepository, getGitDir, getRepositoryRoot, getCurrentBranch, getHeadCommitSha, getHeadTreeSha, verifyRef, verifyRefOrThrow, hasNotesRef } from './git-commands.js';
|
|
21
|
+
// Secure git command execution (low-level - use high-level APIs when possible)
|
|
22
|
+
export { executeGitCommand, execGitCommand, tryGitCommand, validateGitRef, validateNotesRef, validateTreeHash } from './git-executor.js';
|
|
23
|
+
// Git notes operations (high-level abstraction)
|
|
24
|
+
export { addNote, readNote, removeNote, listNotes, hasNote, listNotesRefs, removeNotesRefs, getNotesRefSha } from './git-notes.js';
|
|
21
25
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,uDAAuD;AACvD,OAAO,EACL,cAAc,EACd,eAAe,EACf,qBAAqB,EACtB,MAAM,gBAAgB,CAAC;AAExB,6CAA6C;AAC7C,OAAO,EACL,iBAAiB,EACjB,eAAe,EAGhB,MAAM,kBAAkB,CAAC;AAE1B,8CAA8C;AAC9C,OAAO,EACL,kBAAkB,EAClB,qBAAqB,EAGtB,MAAM,yBAAyB,CAAC;AAEjC,qCAAqC;AACrC,OAAO,EACL,iBAAiB,EAClB,MAAM,gBAAgB,CAAC;AAExB,wBAAwB;AACxB,OAAO,EACL,kBAAkB,EAClB,uBAAuB,EACxB,MAAM,qBAAqB,CAAC;AAE7B,4DAA4D;AAC5D,OAAO,EACL,eAAe,EACf,SAAS,EACT,iBAAiB,EACjB,gBAAgB,EAChB,gBAAgB,EAChB,cAAc,EACd,SAAS,EACT,gBAAgB,EAChB,WAAW,EACZ,MAAM,mBAAmB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,uDAAuD;AACvD,OAAO,EACL,cAAc,EACd,eAAe,EACf,qBAAqB,EACtB,MAAM,gBAAgB,CAAC;AAExB,6CAA6C;AAC7C,OAAO,EACL,iBAAiB,EACjB,eAAe,EAGhB,MAAM,kBAAkB,CAAC;AAE1B,8CAA8C;AAC9C,OAAO,EACL,kBAAkB,EAClB,qBAAqB,EAGtB,MAAM,yBAAyB,CAAC;AAEjC,qCAAqC;AACrC,OAAO,EACL,iBAAiB,EAClB,MAAM,gBAAgB,CAAC;AAExB,wBAAwB;AACxB,OAAO,EACL,kBAAkB,EAClB,uBAAuB,EACxB,MAAM,qBAAqB,CAAC;AAE7B,4DAA4D;AAC5D,OAAO,EACL,eAAe,EACf,SAAS,EACT,iBAAiB,EACjB,gBAAgB,EAChB,gBAAgB,EAChB,cAAc,EACd,SAAS,EACT,gBAAgB,EAChB,WAAW,EACZ,MAAM,mBAAmB,CAAC;AAE3B,+EAA+E;AAC/E,OAAO,EACL,iBAAiB,EACjB,cAAc,EACd,aAAa,EACb,cAAc,EACd,gBAAgB,EAChB,gBAAgB,EAGjB,MAAM,mBAAmB,CAAC;AAE3B,gDAAgD;AAChD,OAAO,EACL,OAAO,EACP,QAAQ,EACR,UAAU,EACV,SAAS,EACT,OAAO,EACP,aAAa,EACb,eAAe,EACf,cAAc,EACf,MAAM,gBAAgB,CAAC"}
|
package/package.json
CHANGED