ghagga 2.1.0 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +41 -8
- package/dist/commands/hooks/index.d.ts +9 -0
- package/dist/commands/hooks/index.d.ts.map +1 -0
- package/dist/commands/hooks/index.js +16 -0
- package/dist/commands/hooks/index.js.map +1 -0
- package/dist/commands/hooks/install.d.ts +13 -0
- package/dist/commands/hooks/install.d.ts.map +1 -0
- package/dist/commands/hooks/install.js +64 -0
- package/dist/commands/hooks/install.js.map +1 -0
- package/dist/commands/hooks/install.test.d.ts +11 -0
- package/dist/commands/hooks/install.test.d.ts.map +1 -0
- package/dist/commands/hooks/install.test.js +157 -0
- package/dist/commands/hooks/install.test.js.map +1 -0
- package/dist/commands/hooks/status.d.ts +12 -0
- package/dist/commands/hooks/status.d.ts.map +1 -0
- package/dist/commands/hooks/status.js +38 -0
- package/dist/commands/hooks/status.js.map +1 -0
- package/dist/commands/hooks/status.test.d.ts +11 -0
- package/dist/commands/hooks/status.test.d.ts.map +1 -0
- package/dist/commands/hooks/status.test.js +123 -0
- package/dist/commands/hooks/status.test.js.map +1 -0
- package/dist/commands/hooks/uninstall.d.ts +12 -0
- package/dist/commands/hooks/uninstall.d.ts.map +1 -0
- package/dist/commands/hooks/uninstall.js +44 -0
- package/dist/commands/hooks/uninstall.js.map +1 -0
- package/dist/commands/hooks/uninstall.test.d.ts +10 -0
- package/dist/commands/hooks/uninstall.test.d.ts.map +1 -0
- package/dist/commands/hooks/uninstall.test.js +120 -0
- package/dist/commands/hooks/uninstall.test.js.map +1 -0
- package/dist/commands/review-commit-msg.d.ts +28 -0
- package/dist/commands/review-commit-msg.d.ts.map +1 -0
- package/dist/commands/review-commit-msg.js +126 -0
- package/dist/commands/review-commit-msg.js.map +1 -0
- package/dist/commands/review-commit-msg.test.d.ts +11 -0
- package/dist/commands/review-commit-msg.test.d.ts.map +1 -0
- package/dist/commands/review-commit-msg.test.js +126 -0
- package/dist/commands/review-commit-msg.test.js.map +1 -0
- package/dist/commands/review.d.ts +6 -0
- package/dist/commands/review.d.ts.map +1 -1
- package/dist/commands/review.js +105 -10
- package/dist/commands/review.js.map +1 -1
- package/dist/index.d.ts +5 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +21 -7
- package/dist/index.js.map +1 -1
- package/dist/lib/git-hooks.d.ts +19 -0
- package/dist/lib/git-hooks.d.ts.map +1 -0
- package/dist/lib/git-hooks.js +129 -0
- package/dist/lib/git-hooks.js.map +1 -0
- package/dist/lib/git-hooks.test.d.ts +11 -0
- package/dist/lib/git-hooks.test.d.ts.map +1 -0
- package/dist/lib/git-hooks.test.js +178 -0
- package/dist/lib/git-hooks.test.js.map +1 -0
- package/dist/lib/git.d.ts +10 -0
- package/dist/lib/git.d.ts.map +1 -1
- package/dist/lib/git.js +32 -0
- package/dist/lib/git.js.map +1 -1
- package/dist/lib/hook-templates.d.ts +12 -0
- package/dist/lib/hook-templates.d.ts.map +1 -0
- package/dist/lib/hook-templates.js +52 -0
- package/dist/lib/hook-templates.js.map +1 -0
- package/dist/lib/hook-templates.test.d.ts +11 -0
- package/dist/lib/hook-templates.test.d.ts.map +1 -0
- package/dist/lib/hook-templates.test.js +76 -0
- package/dist/lib/hook-templates.test.js.map +1 -0
- package/dist/lib/hooks-types.d.ts +30 -0
- package/dist/lib/hooks-types.d.ts.map +1 -0
- package/dist/lib/hooks-types.js +9 -0
- package/dist/lib/hooks-types.js.map +1 -0
- package/package.json +2 -2
package/dist/commands/review.js
CHANGED
|
@@ -8,9 +8,10 @@
|
|
|
8
8
|
import { execSync } from 'node:child_process';
|
|
9
9
|
import { readFileSync, existsSync } from 'node:fs';
|
|
10
10
|
import { resolve, join } from 'node:path';
|
|
11
|
-
import { reviewPipeline, DEFAULT_SETTINGS, SqliteMemoryStorage, } from 'ghagga-core';
|
|
12
|
-
import { resolveProjectId } from '../lib/git.js';
|
|
11
|
+
import { reviewPipeline, DEFAULT_SETTINGS, SqliteMemoryStorage, EngramMemoryStorage, } from 'ghagga-core';
|
|
12
|
+
import { resolveProjectId, getStagedDiff } from '../lib/git.js';
|
|
13
13
|
import { getConfigDir } from '../lib/config.js';
|
|
14
|
+
import { reviewCommitMessage } from './review-commit-msg.js';
|
|
14
15
|
import * as tui from '../ui/tui.js';
|
|
15
16
|
import { formatMarkdownResult } from '../ui/format.js';
|
|
16
17
|
import { resolveStepIcon } from '../ui/theme.js';
|
|
@@ -19,10 +20,52 @@ export async function reviewCommand(targetPath, options) {
|
|
|
19
20
|
const repoPath = resolve(targetPath);
|
|
20
21
|
let memoryStorage;
|
|
21
22
|
try {
|
|
22
|
-
//
|
|
23
|
-
|
|
23
|
+
// ── Mutual exclusivity check: --staged and --commit-msg ──
|
|
24
|
+
if (options.staged && options.commitMsg) {
|
|
25
|
+
tui.log.error('❌ --staged and --commit-msg are mutually exclusive. Use one or the other.');
|
|
26
|
+
process.exit(1);
|
|
27
|
+
}
|
|
28
|
+
// ── Commit message review path (bypasses file-based pipeline) ──
|
|
29
|
+
if (options.commitMsg) {
|
|
30
|
+
const commitMsgFile = resolve(options.commitMsg);
|
|
31
|
+
if (!existsSync(commitMsgFile)) {
|
|
32
|
+
tui.log.error(`❌ Commit message file not found: ${commitMsgFile}`);
|
|
33
|
+
process.exit(1);
|
|
34
|
+
}
|
|
35
|
+
const message = readFileSync(commitMsgFile, 'utf-8');
|
|
36
|
+
if (options.format !== 'json') {
|
|
37
|
+
tui.intro('🤖 GHAGGA Commit Message Review');
|
|
38
|
+
}
|
|
39
|
+
const result = await reviewCommitMessage({
|
|
40
|
+
message,
|
|
41
|
+
provider: options.provider,
|
|
42
|
+
model: options.model,
|
|
43
|
+
apiKey: options.apiKey,
|
|
44
|
+
quick: options.quick,
|
|
45
|
+
});
|
|
46
|
+
// Output the result
|
|
47
|
+
if (options.format === 'json') {
|
|
48
|
+
console.log(JSON.stringify(result, null, 2));
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
tui.log.message(formatMarkdownResult(result));
|
|
52
|
+
}
|
|
53
|
+
// Exit code: --exit-on-issues overrides default behavior
|
|
54
|
+
const exitCode = resolveExitCode(result, options.exitOnIssues ?? false);
|
|
55
|
+
if (options.format !== 'json') {
|
|
56
|
+
tui.outro('Commit message review complete');
|
|
57
|
+
}
|
|
58
|
+
process.exit(exitCode);
|
|
59
|
+
}
|
|
60
|
+
// ── Step 1: Get the git diff ─────────────────────────────
|
|
61
|
+
const diff = options.staged
|
|
62
|
+
? getStagedDiff(repoPath)
|
|
63
|
+
: getGitDiff(repoPath);
|
|
24
64
|
if (!diff || diff.trim().length === 0) {
|
|
25
|
-
|
|
65
|
+
const msg = options.staged
|
|
66
|
+
? 'ℹ️ No staged changes found. Stage files with `git add` first.'
|
|
67
|
+
: 'ℹ️ No changes detected. Stage some changes or make commits to review.';
|
|
68
|
+
tui.log.info(msg);
|
|
26
69
|
process.exit(0);
|
|
27
70
|
}
|
|
28
71
|
// Step 2: Load optional config file
|
|
@@ -33,14 +76,49 @@ export async function reviewCommand(targetPath, options) {
|
|
|
33
76
|
if (options.format !== 'json') {
|
|
34
77
|
tui.intro('🤖 GHAGGA Code Review');
|
|
35
78
|
tui.log.message(` Mode: ${options.mode} | Provider: ${options.provider} | Model: ${options.model}`);
|
|
36
|
-
|
|
79
|
+
if (options.staged) {
|
|
80
|
+
tui.log.step(' Reviewing staged changes...\n');
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
tui.log.step(' Analyzing...\n');
|
|
84
|
+
}
|
|
37
85
|
}
|
|
38
|
-
// Step 4.5: Initialize memory storage
|
|
86
|
+
// Step 4.5: Initialize memory storage
|
|
39
87
|
const repoFullName = resolveProjectId(repoPath);
|
|
40
88
|
if (options.memory) {
|
|
89
|
+
// Determine backend: CLI flag > env var > default ('sqlite')
|
|
90
|
+
const memoryBackend = options.memoryBackend
|
|
91
|
+
?? process.env['GHAGGA_MEMORY_BACKEND']
|
|
92
|
+
?? 'sqlite';
|
|
93
|
+
// Validate backend value
|
|
94
|
+
const validBackends = ['sqlite', 'engram'];
|
|
95
|
+
if (!validBackends.includes(memoryBackend)) {
|
|
96
|
+
tui.log.error(`❌ Invalid memory backend "${memoryBackend}". Choose from: ${validBackends.join(', ')}`);
|
|
97
|
+
process.exit(1);
|
|
98
|
+
}
|
|
41
99
|
try {
|
|
42
100
|
const dbPath = join(getConfigDir(), 'memory.db');
|
|
43
|
-
|
|
101
|
+
if (memoryBackend === 'engram') {
|
|
102
|
+
// Try Engram; fall back to SQLite if unavailable
|
|
103
|
+
const engramHost = process.env['GHAGGA_ENGRAM_HOST'] ?? 'http://localhost:7437';
|
|
104
|
+
const engramTimeout = process.env['GHAGGA_ENGRAM_TIMEOUT']
|
|
105
|
+
? Number(process.env['GHAGGA_ENGRAM_TIMEOUT']) * 1000
|
|
106
|
+
: undefined;
|
|
107
|
+
const engramStorage = await EngramMemoryStorage.create({
|
|
108
|
+
host: engramHost,
|
|
109
|
+
...(engramTimeout != null ? { timeout: engramTimeout } : {}),
|
|
110
|
+
});
|
|
111
|
+
if (engramStorage) {
|
|
112
|
+
memoryStorage = engramStorage;
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
tui.log.warn('⚠️ Engram not available, falling back to SQLite memory');
|
|
116
|
+
memoryStorage = await SqliteMemoryStorage.create(dbPath);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
memoryStorage = await SqliteMemoryStorage.create(dbPath);
|
|
121
|
+
}
|
|
44
122
|
}
|
|
45
123
|
catch (error) {
|
|
46
124
|
const msg = error instanceof Error ? error.message : String(error);
|
|
@@ -67,6 +145,8 @@ export async function reviewCommand(targetPath, options) {
|
|
|
67
145
|
},
|
|
68
146
|
memoryStorage,
|
|
69
147
|
onProgress,
|
|
148
|
+
// --quick: disable AI review, use static analysis only
|
|
149
|
+
...(options.quick ? { aiReviewEnabled: false } : {}),
|
|
70
150
|
});
|
|
71
151
|
// Step 5.5: Persist memory to disk
|
|
72
152
|
await memoryStorage?.close();
|
|
@@ -77,8 +157,8 @@ export async function reviewCommand(targetPath, options) {
|
|
|
77
157
|
else {
|
|
78
158
|
tui.log.message(formatMarkdownResult(result));
|
|
79
159
|
}
|
|
80
|
-
// Step 7: Exit code
|
|
81
|
-
const exitCode =
|
|
160
|
+
// Step 7: Exit code — --exit-on-issues overrides default behavior
|
|
161
|
+
const exitCode = resolveExitCode(result, options.exitOnIssues ?? false);
|
|
82
162
|
if (options.format !== 'json') {
|
|
83
163
|
tui.outro('Review complete');
|
|
84
164
|
}
|
|
@@ -187,6 +267,21 @@ function createProgressHandler() {
|
|
|
187
267
|
};
|
|
188
268
|
}
|
|
189
269
|
// ─── Exit Code ──────────────────────────────────────────────────
|
|
270
|
+
/**
|
|
271
|
+
* Resolve the exit code for the review process.
|
|
272
|
+
*
|
|
273
|
+
* When `exitOnIssues` is true (hook mode), checks findings for
|
|
274
|
+
* critical/high severity — returns 1 if any found, 0 otherwise.
|
|
275
|
+
* When false, delegates to the default status-based exit code.
|
|
276
|
+
*/
|
|
277
|
+
function resolveExitCode(result, exitOnIssues) {
|
|
278
|
+
if (exitOnIssues) {
|
|
279
|
+
const hasBlockingIssues = result.findings.some((f) => f.severity === 'critical' || f.severity === 'high');
|
|
280
|
+
return hasBlockingIssues ? 1 : 0;
|
|
281
|
+
}
|
|
282
|
+
// Default behavior: use status-based exit code
|
|
283
|
+
return getExitCode(result.status);
|
|
284
|
+
}
|
|
190
285
|
/**
|
|
191
286
|
* Map review status to process exit code.
|
|
192
287
|
* PASSED and SKIPPED = 0, everything else = 1.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"review.js","sourceRoot":"","sources":["../../src/commands/review.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EACL,cAAc,EACd,gBAAgB,EAChB,mBAAmB,GACpB,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"review.js","sourceRoot":"","sources":["../../src/commands/review.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -12,10 +12,11 @@
|
|
|
12
12
|
* You can override with --provider, --model, --api-key for other providers.
|
|
13
13
|
*
|
|
14
14
|
* Environment variables (override stored config):
|
|
15
|
-
* GHAGGA_API_KEY
|
|
16
|
-
* GHAGGA_PROVIDER
|
|
17
|
-
* GHAGGA_MODEL
|
|
18
|
-
* GITHUB_TOKEN
|
|
15
|
+
* GHAGGA_API_KEY API key for the LLM provider
|
|
16
|
+
* GHAGGA_PROVIDER LLM provider: anthropic, openai, google, github, ollama, qwen
|
|
17
|
+
* GHAGGA_MODEL Model identifier
|
|
18
|
+
* GITHUB_TOKEN GitHub token (fallback for github provider)
|
|
19
|
+
* GHAGGA_MEMORY_BACKEND Memory backend: sqlite (default) or engram
|
|
19
20
|
*/
|
|
20
21
|
import 'dotenv/config';
|
|
21
22
|
//# 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":";AAEA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,eAAe,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -12,10 +12,11 @@
|
|
|
12
12
|
* You can override with --provider, --model, --api-key for other providers.
|
|
13
13
|
*
|
|
14
14
|
* Environment variables (override stored config):
|
|
15
|
-
* GHAGGA_API_KEY
|
|
16
|
-
* GHAGGA_PROVIDER
|
|
17
|
-
* GHAGGA_MODEL
|
|
18
|
-
* GITHUB_TOKEN
|
|
15
|
+
* GHAGGA_API_KEY API key for the LLM provider
|
|
16
|
+
* GHAGGA_PROVIDER LLM provider: anthropic, openai, google, github, ollama, qwen
|
|
17
|
+
* GHAGGA_MODEL Model identifier
|
|
18
|
+
* GITHUB_TOKEN GitHub token (fallback for github provider)
|
|
19
|
+
* GHAGGA_MEMORY_BACKEND Memory backend: sqlite (default) or engram
|
|
19
20
|
*/
|
|
20
21
|
import 'dotenv/config';
|
|
21
22
|
import { readFileSync } from 'node:fs';
|
|
@@ -29,6 +30,7 @@ import { loginCommand } from './commands/login.js';
|
|
|
29
30
|
import { logoutCommand } from './commands/logout.js';
|
|
30
31
|
import { statusCommand } from './commands/status.js';
|
|
31
32
|
import { memoryCommand } from './commands/memory/index.js';
|
|
33
|
+
import { hooksCommand } from './commands/hooks/index.js';
|
|
32
34
|
import * as tui from './ui/tui.js';
|
|
33
35
|
// Read version from package.json at runtime (no hardcoded strings)
|
|
34
36
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
@@ -81,6 +83,11 @@ program
|
|
|
81
83
|
.option('--no-memory', 'Disable review memory')
|
|
82
84
|
.option('-c, --config <path>', 'Path to .ghagga.json config file')
|
|
83
85
|
.option('-v, --verbose', 'Show detailed progress during review')
|
|
86
|
+
.option('--staged', 'Review only staged changes (for pre-commit hooks)')
|
|
87
|
+
.option('--commit-msg <file>', 'Validate commit message from file path')
|
|
88
|
+
.option('--exit-on-issues', 'Exit with code 1 if critical/high issues found')
|
|
89
|
+
.option('--quick', 'Static analysis only — skip LLM review')
|
|
90
|
+
.option('--memory-backend <type>', 'Memory backend: sqlite (default) or engram (env: GHAGGA_MEMORY_BACKEND)', 'sqlite')
|
|
84
91
|
.action(async (path, options) => {
|
|
85
92
|
// ── Auto-resolve auth from stored config ──────────────────
|
|
86
93
|
const config = loadConfig();
|
|
@@ -116,8 +123,8 @@ program
|
|
|
116
123
|
tui.log.error(`❌ Invalid format "${options.format}". Choose from: ${validFormats.join(', ')}`);
|
|
117
124
|
process.exit(1);
|
|
118
125
|
}
|
|
119
|
-
// ── Validate API key (not required for ollama)
|
|
120
|
-
if (!options.apiKey && options.provider !== 'ollama') {
|
|
126
|
+
// ── Validate API key (not required for ollama or --quick mode) ──
|
|
127
|
+
if (!options.apiKey && options.provider !== 'ollama' && !options.quick) {
|
|
121
128
|
tui.log.error('❌ No API key available.\n');
|
|
122
129
|
tui.log.error(' Quick fix: run "ghagga login" to authenticate with GitHub (free!)');
|
|
123
130
|
tui.log.error(' Or pass --api-key <key> or set GHAGGA_API_KEY.');
|
|
@@ -135,17 +142,24 @@ program
|
|
|
135
142
|
mode: options.mode,
|
|
136
143
|
provider,
|
|
137
144
|
model,
|
|
138
|
-
apiKey: options.apiKey,
|
|
145
|
+
apiKey: options.apiKey ?? '',
|
|
139
146
|
format: options.format,
|
|
140
147
|
semgrep: options.semgrep,
|
|
141
148
|
trivy: options.trivy,
|
|
142
149
|
cpd: options.cpd,
|
|
143
150
|
memory: options.memory,
|
|
151
|
+
memoryBackend: options.memoryBackend,
|
|
144
152
|
config: options.config,
|
|
145
153
|
verbose: options.verbose ?? false,
|
|
154
|
+
staged: options.staged ?? false,
|
|
155
|
+
commitMsg: options.commitMsg,
|
|
156
|
+
exitOnIssues: options.exitOnIssues ?? false,
|
|
157
|
+
quick: options.quick ?? false,
|
|
146
158
|
});
|
|
147
159
|
});
|
|
148
160
|
// ─── Memory ─────────────────────────────────────────────────────
|
|
149
161
|
program.addCommand(memoryCommand);
|
|
162
|
+
// ─── Hooks ──────────────────────────────────────────────────────
|
|
163
|
+
program.addCommand(hooksCommand);
|
|
150
164
|
program.parse();
|
|
151
165
|
//# 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":";AAEA
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,eAAe,CAAC;AAEvB,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7C,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAC7D,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,KAAK,GAAG,MAAM,aAAa,CAAC;AAEnC,mEAAmE;AACnE,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC1D,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,EAAE,cAAc,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;AAExF,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,QAAQ,CAAC;KACd,WAAW,CAAC,4BAA4B,CAAC;KACzC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC;KACpB,MAAM,CAAC,SAAS,EAAE,gCAAgC,CAAC,CAAC;AAEvD,2DAA2D;AAC3D,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,WAAW,EAAE,EAAE;IACxC,MAAM,IAAI,GAAG,WAAW,CAAC,eAAe,EAAyB,CAAC;IAClE,GAAG,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;AAClC,CAAC,CAAC,CAAC;AAEH,mEAAmE;AAEnE,OAAO;KACJ,OAAO,CAAC,OAAO,CAAC;KAChB,WAAW,CAAC,gDAAgD,CAAC;KAC7D,MAAM,CAAC,KAAK,IAAI,EAAE;IACjB,MAAM,YAAY,EAAE,CAAC;AACvB,CAAC,CAAC,CAAC;AAEL,mEAAmE;AAEnE,OAAO;KACJ,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,iCAAiC,CAAC;KAC9C,MAAM,CAAC,GAAG,EAAE;IACX,aAAa,EAAE,CAAC;AAClB,CAAC,CAAC,CAAC;AAEL,mEAAmE;AAEnE,OAAO;KACJ,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,+CAA+C,CAAC;KAC5D,MAAM,CAAC,KAAK,IAAI,EAAE;IACjB,MAAM,aAAa,EAAE,CAAC;AACxB,CAAC,CAAC,CAAC;AAEL,mEAAmE;AAEnE,OAAO;KACJ,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,oCAAoC,CAAC;KACjD,QAAQ,CAAC,QAAQ,EAAE,wBAAwB,EAAE,GAAG,CAAC;KACjD,MAAM,CACL,mBAAmB,EACnB,aAAa,EACb,QAAQ,CACT;KACA,MAAM,CACL,2BAA2B,EAC3B,yCAAyC,EACzC,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAC/B;KACA,MAAM,CACL,iBAAiB,EACjB,sBAAsB,EACtB,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAC5B;KACA,MAAM,CACL,iBAAiB,EACjB,sBAAsB,EACtB,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAC9B;KACA,MAAM,CACL,uBAAuB,EACvB,eAAe,EACf,UAAU,CACX;KACA,MAAM,CAAC,cAAc,EAAE,iCAAiC,CAAC;KACzD,MAAM,CAAC,YAAY,EAAE,sCAAsC,CAAC;KAC5D,MAAM,CAAC,UAAU,EAAE,iCAAiC,CAAC;KACrD,MAAM,CAAC,aAAa,EAAE,uBAAuB,CAAC;KAC9C,MAAM,CAAC,qBAAqB,EAAE,kCAAkC,CAAC;KACjE,MAAM,CAAC,eAAe,EAAE,sCAAsC,CAAC;KAC/D,MAAM,CAAC,UAAU,EAAE,mDAAmD,CAAC;KACvE,MAAM,CAAC,qBAAqB,EAAE,wCAAwC,CAAC;KACvE,MAAM,CAAC,kBAAkB,EAAE,gDAAgD,CAAC;KAC5E,MAAM,CAAC,SAAS,EAAE,wCAAwC,CAAC;KAC3D,MAAM,CAAC,yBAAyB,EAAE,yEAAyE,EAAE,QAAQ,CAAC;KACtH,MAAM,CAAC,KAAK,EAAE,IAAY,EAAE,OAA6B,EAAE,EAAE;IAC5D,6DAA6D;IAC7D,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,MAAM,WAAW,GAAG,cAAc,EAAE,CAAC;IAErC,+CAA+C;IAC/C,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;QACtB,OAAO,CAAC,QAAQ,GAAG,MAAM,CAAC,eAAe,IAAI,QAAQ,CAAC;IACxD,CAAC;IAED,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QACnB,OAAO,CAAC,KAAK,GAAG,MAAM,CAAC,YAAY,IAAI,SAAS,CAAC;IACnD,CAAC;IAED,yEAAyE;IACzE,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;QACpB,IAAI,OAAO,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;YAClC,OAAO,CAAC,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,WAAW,IAAI,SAAS,CAAC;QAC3E,CAAC;IACH,CAAC;IAED,6DAA6D;IAC7D,MAAM,UAAU,GAAiB,CAAC,QAAQ,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC;IACrE,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAkB,CAAC,EAAE,CAAC;QACrD,GAAG,CAAC,GAAG,CAAC,KAAK,CACX,mBAAmB,OAAO,CAAC,IAAI,mBAAmB,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAC1E,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,6DAA6D;IAC7D,MAAM,cAAc,GAAkB,CAAC,WAAW,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;IACpG,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,OAAO,CAAC,QAAuB,CAAC,EAAE,CAAC;QAC9D,GAAG,CAAC,GAAG,CAAC,KAAK,CACX,uBAAuB,OAAO,CAAC,QAAQ,mBAAmB,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACtF,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,6DAA6D;IAC7D,MAAM,YAAY,GAAG,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IAC1C,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAC3C,GAAG,CAAC,GAAG,CAAC,KAAK,CACX,qBAAqB,OAAO,CAAC,MAAM,mBAAmB,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAChF,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,mEAAmE;IACnE,IAAI,CAAC,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,QAAQ,KAAK,QAAQ,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QACvE,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAC;QAC3C,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,sEAAsE,CAAC,CAAC;QACtF,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,mDAAmD,CAAC,CAAC;QACnE,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,iEAAiE,CAAC,CAAC;QACjF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,qDAAqD;IACrD,IAAI,OAAO,CAAC,QAAQ,KAAK,QAAQ,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;QACrD,OAAO,CAAC,MAAM,GAAG,QAAQ,CAAC;IAC5B,CAAC;IAED,6DAA6D;IAC7D,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAuB,CAAC;IACjD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,cAAc,CAAC,QAAQ,CAAC,CAAC;IAExD,MAAM,aAAa,CAAC,IAAI,EAAE;QACxB,IAAI,EAAE,OAAO,CAAC,IAAkB;QAChC,QAAQ;QACR,KAAK;QACL,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,EAAE;QAC5B,MAAM,EAAE,OAAO,CAAC,MAA6B;QAC7C,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,GAAG,EAAE,OAAO,CAAC,GAAG;QAChB,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,aAAa,EAAE,OAAO,CAAC,aAAgD;QACvE,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,KAAK;QACjC,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,KAAK;QAC/B,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,YAAY,EAAE,OAAO,CAAC,YAAY,IAAI,KAAK;QAC3C,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,KAAK;KAC9B,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEL,mEAAmE;AAEnE,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;AAElC,mEAAmE;AAEnE,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;AAEjC,OAAO,CAAC,KAAK,EAAE,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Git hook utilities for install, uninstall, and status operations.
|
|
3
|
+
*
|
|
4
|
+
* Handles detection of the hooks directory (respects core.hooksPath),
|
|
5
|
+
* GHAGGA marker detection, hook installation with backup, and
|
|
6
|
+
* clean uninstallation with backup restoration.
|
|
7
|
+
*/
|
|
8
|
+
import { type HookType, type HookStatus, type HookOperationResult } from './hooks-types.js';
|
|
9
|
+
/** Get the git hooks directory (respects core.hooksPath config) */
|
|
10
|
+
export declare function getHooksDir(): string;
|
|
11
|
+
/** Check if we're in a git repository */
|
|
12
|
+
export declare function isGitRepo(): boolean;
|
|
13
|
+
/** Get the status of a specific hook */
|
|
14
|
+
export declare function getHookStatus(hooksDir: string, hookType: HookType): HookStatus;
|
|
15
|
+
/** Install a hook script */
|
|
16
|
+
export declare function installHook(hooksDir: string, hookType: HookType, content: string, force: boolean): HookOperationResult;
|
|
17
|
+
/** Uninstall a hook if it's managed by GHAGGA */
|
|
18
|
+
export declare function uninstallHook(hooksDir: string, hookType: HookType): HookOperationResult;
|
|
19
|
+
//# sourceMappingURL=git-hooks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-hooks.d.ts","sourceRoot":"","sources":["../../src/lib/git-hooks.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,OAAO,EAAe,KAAK,QAAQ,EAAE,KAAK,UAAU,EAAE,KAAK,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAEzG,mEAAmE;AACnE,wBAAgB,WAAW,IAAI,MAAM,CAYpC;AAED,yCAAyC;AACzC,wBAAgB,SAAS,IAAI,OAAO,CAOnC;AAED,wCAAwC;AACxC,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,GAAG,UAAU,CAoB9E;AAED,4BAA4B;AAC5B,wBAAgB,WAAW,CACzB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,OAAO,GACb,mBAAmB,CAmCrB;AAED,iDAAiD;AACjD,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,GAAG,mBAAmB,CAsCvF"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Git hook utilities for install, uninstall, and status operations.
|
|
3
|
+
*
|
|
4
|
+
* Handles detection of the hooks directory (respects core.hooksPath),
|
|
5
|
+
* GHAGGA marker detection, hook installation with backup, and
|
|
6
|
+
* clean uninstallation with backup restoration.
|
|
7
|
+
*/
|
|
8
|
+
import { existsSync, readFileSync, writeFileSync, unlinkSync, renameSync, chmodSync } from 'node:fs';
|
|
9
|
+
import { join } from 'node:path';
|
|
10
|
+
import { execSync } from 'node:child_process';
|
|
11
|
+
import { HOOK_MARKER } from './hooks-types.js';
|
|
12
|
+
/** Get the git hooks directory (respects core.hooksPath config) */
|
|
13
|
+
export function getHooksDir() {
|
|
14
|
+
// Try core.hooksPath first
|
|
15
|
+
try {
|
|
16
|
+
const hooksPath = execSync('git config core.hooksPath', { encoding: 'utf-8' }).trim();
|
|
17
|
+
if (hooksPath)
|
|
18
|
+
return hooksPath;
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
// Not set, use default
|
|
22
|
+
}
|
|
23
|
+
// Default: .git/hooks
|
|
24
|
+
const gitDir = execSync('git rev-parse --git-dir', { encoding: 'utf-8' }).trim();
|
|
25
|
+
return join(gitDir, 'hooks');
|
|
26
|
+
}
|
|
27
|
+
/** Check if we're in a git repository */
|
|
28
|
+
export function isGitRepo() {
|
|
29
|
+
try {
|
|
30
|
+
execSync('git rev-parse --git-dir', { stdio: 'pipe' });
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/** Get the status of a specific hook */
|
|
38
|
+
export function getHookStatus(hooksDir, hookType) {
|
|
39
|
+
const hookPath = join(hooksDir, hookType);
|
|
40
|
+
const exists = existsSync(hookPath);
|
|
41
|
+
let managedByGhagga = false;
|
|
42
|
+
if (exists) {
|
|
43
|
+
try {
|
|
44
|
+
const content = readFileSync(hookPath, 'utf-8');
|
|
45
|
+
managedByGhagga = content.includes(HOOK_MARKER);
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
// Can't read, not managed
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return {
|
|
52
|
+
type: hookType,
|
|
53
|
+
installed: exists,
|
|
54
|
+
managedByGhagga,
|
|
55
|
+
path: hookPath,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
/** Install a hook script */
|
|
59
|
+
export function installHook(hooksDir, hookType, content, force) {
|
|
60
|
+
const hookPath = join(hooksDir, hookType);
|
|
61
|
+
const exists = existsSync(hookPath);
|
|
62
|
+
let backedUp = false;
|
|
63
|
+
if (exists) {
|
|
64
|
+
const existing = readFileSync(hookPath, 'utf-8');
|
|
65
|
+
if (existing.includes(HOOK_MARKER)) {
|
|
66
|
+
// Already GHAGGA-managed, overwrite
|
|
67
|
+
}
|
|
68
|
+
else if (!force) {
|
|
69
|
+
return {
|
|
70
|
+
type: hookType,
|
|
71
|
+
success: false,
|
|
72
|
+
message: `Hook ${hookType} already exists (not managed by GHAGGA). Use --force to overwrite.`,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
// Backup existing hook
|
|
77
|
+
const backupPath = `${hookPath}.ghagga-backup`;
|
|
78
|
+
renameSync(hookPath, backupPath);
|
|
79
|
+
backedUp = true;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
writeFileSync(hookPath, content, { mode: 0o755 });
|
|
83
|
+
// Also chmod explicitly for systems where writeFileSync mode doesn't work
|
|
84
|
+
chmodSync(hookPath, 0o755);
|
|
85
|
+
return {
|
|
86
|
+
type: hookType,
|
|
87
|
+
success: true,
|
|
88
|
+
message: backedUp
|
|
89
|
+
? `Installed ${hookType} hook (existing hook backed up to ${hookType}.ghagga-backup)`
|
|
90
|
+
: `Installed ${hookType} hook`,
|
|
91
|
+
backedUp,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
/** Uninstall a hook if it's managed by GHAGGA */
|
|
95
|
+
export function uninstallHook(hooksDir, hookType) {
|
|
96
|
+
const hookPath = join(hooksDir, hookType);
|
|
97
|
+
if (!existsSync(hookPath)) {
|
|
98
|
+
return {
|
|
99
|
+
type: hookType,
|
|
100
|
+
success: true,
|
|
101
|
+
message: `Hook ${hookType} not installed, nothing to remove`,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
const content = readFileSync(hookPath, 'utf-8');
|
|
105
|
+
if (!content.includes(HOOK_MARKER)) {
|
|
106
|
+
return {
|
|
107
|
+
type: hookType,
|
|
108
|
+
success: false,
|
|
109
|
+
message: `Hook ${hookType} exists but is not managed by GHAGGA. Skipping.`,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
unlinkSync(hookPath);
|
|
113
|
+
// Restore backup if exists
|
|
114
|
+
const backupPath = `${hookPath}.ghagga-backup`;
|
|
115
|
+
if (existsSync(backupPath)) {
|
|
116
|
+
renameSync(backupPath, hookPath);
|
|
117
|
+
return {
|
|
118
|
+
type: hookType,
|
|
119
|
+
success: true,
|
|
120
|
+
message: `Removed ${hookType} hook (restored previous hook from backup)`,
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
return {
|
|
124
|
+
type: hookType,
|
|
125
|
+
success: true,
|
|
126
|
+
message: `Removed ${hookType} hook`,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=git-hooks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-hooks.js","sourceRoot":"","sources":["../../src/lib/git-hooks.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for git hook utilities (install, uninstall, status).
|
|
3
|
+
*
|
|
4
|
+
* Mocks node:fs, node:child_process, and node:path to test
|
|
5
|
+
* isGitRepo, getHooksDir, getHookStatus, installHook, and uninstallHook
|
|
6
|
+
* without touching the real filesystem or git.
|
|
7
|
+
*
|
|
8
|
+
* @see Phase 4, Test 2
|
|
9
|
+
*/
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=git-hooks.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-hooks.test.d.ts","sourceRoot":"","sources":["../../src/lib/git-hooks.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG"}
|