@azizbekdevuz/gitguard-cli 1.0.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 +88 -0
- package/dist/collectors/conflict-extractor.d.ts +7 -0
- package/dist/collectors/conflict-extractor.d.ts.map +1 -0
- package/dist/collectors/conflict-extractor.js +94 -0
- package/dist/collectors/conflict-extractor.js.map +1 -0
- package/dist/collectors/git-info.d.ts +18 -0
- package/dist/collectors/git-info.d.ts.map +1 -0
- package/dist/collectors/git-info.js +59 -0
- package/dist/collectors/git-info.js.map +1 -0
- package/dist/collectors/rebase-detector.d.ts +7 -0
- package/dist/collectors/rebase-detector.d.ts.map +1 -0
- package/dist/collectors/rebase-detector.js +57 -0
- package/dist/collectors/rebase-detector.js.map +1 -0
- package/dist/commands/send.d.ts +7 -0
- package/dist/commands/send.d.ts.map +1 -0
- package/dist/commands/send.js +169 -0
- package/dist/commands/send.js.map +1 -0
- package/dist/commands/snapshot.d.ts +7 -0
- package/dist/commands/snapshot.d.ts.map +1 -0
- package/dist/commands/snapshot.js +92 -0
- package/dist/commands/snapshot.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +22 -0
- package/dist/index.js.map +1 -0
- package/dist/parsers/branch-parser.d.ts +7 -0
- package/dist/parsers/branch-parser.d.ts.map +1 -0
- package/dist/parsers/branch-parser.js +20 -0
- package/dist/parsers/branch-parser.js.map +1 -0
- package/dist/parsers/diffstat-parser.d.ts +8 -0
- package/dist/parsers/diffstat-parser.d.ts.map +1 -0
- package/dist/parsers/diffstat-parser.js +42 -0
- package/dist/parsers/diffstat-parser.js.map +1 -0
- package/dist/parsers/log-parser.d.ts +8 -0
- package/dist/parsers/log-parser.d.ts.map +1 -0
- package/dist/parsers/log-parser.js +46 -0
- package/dist/parsers/log-parser.js.map +1 -0
- package/dist/parsers/reflog-parser.d.ts +8 -0
- package/dist/parsers/reflog-parser.d.ts.map +1 -0
- package/dist/parsers/reflog-parser.js +65 -0
- package/dist/parsers/reflog-parser.js.map +1 -0
- package/dist/parsers/status-parser.d.ts +27 -0
- package/dist/parsers/status-parser.d.ts.map +1 -0
- package/dist/parsers/status-parser.js +110 -0
- package/dist/parsers/status-parser.js.map +1 -0
- package/dist/utils/exec.d.ts +14 -0
- package/dist/utils/exec.d.ts.map +1 -0
- package/dist/utils/exec.js +54 -0
- package/dist/utils/exec.js.map +1 -0
- package/package.json +46 -0
package/README.md
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# GitGuard CLI
|
|
2
|
+
|
|
3
|
+
Command-line tool for capturing and analyzing Git repository state.
|
|
4
|
+
|
|
5
|
+
## Installation & Usage
|
|
6
|
+
|
|
7
|
+
Since this is a local package (not published to npm), use one of these methods:
|
|
8
|
+
|
|
9
|
+
### Method 1: Using pnpm (Recommended - Easiest)
|
|
10
|
+
|
|
11
|
+
From the **project root**:
|
|
12
|
+
```bash
|
|
13
|
+
# Build the CLI first (one time)
|
|
14
|
+
pnpm build:cli
|
|
15
|
+
|
|
16
|
+
# Then use via pnpm (use -- to pass arguments)
|
|
17
|
+
pnpm --filter @gitguard/cli -- snapshot --pretty > snapshot.json
|
|
18
|
+
# pnpm --filter @gitguard/cli -- send
|
|
19
|
+
# pnpm --filter @gitguard/cli -- send --open
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### Method 2: Direct Node Execution (After Building)
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
# Build first (one time)
|
|
26
|
+
pnpm build:cli
|
|
27
|
+
|
|
28
|
+
# Run directly from project root
|
|
29
|
+
node apps/cli/dist/index.js snapshot --pretty > snapshot.json
|
|
30
|
+
# node apps/cli/dist/index.js send
|
|
31
|
+
# node apps/cli/dist/index.js send --open
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Method 3: Global Link (For Development)
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
# From project root
|
|
38
|
+
pnpm build:cli
|
|
39
|
+
cd apps/cli
|
|
40
|
+
pnpm link --global
|
|
41
|
+
|
|
42
|
+
# Now you can use `gitguard` from anywhere on your system
|
|
43
|
+
gitguard snapshot --pretty > snapshot.json
|
|
44
|
+
gitguard send
|
|
45
|
+
gitguard send --open
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Method 4: Create an Alias (PowerShell)
|
|
49
|
+
|
|
50
|
+
Add to your PowerShell profile (`$PROFILE`):
|
|
51
|
+
```powershell
|
|
52
|
+
function gitguard { node D:\Workplace\Web\gitguardian\apps\cli\dist\index.js $args }
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Then use normally:
|
|
56
|
+
```bash
|
|
57
|
+
gitguard snapshot --pretty > snapshot.json
|
|
58
|
+
gitguard send
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Commands
|
|
62
|
+
|
|
63
|
+
### `gitguard snapshot`
|
|
64
|
+
|
|
65
|
+
Generate a read-only snapshot of your repository state.
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
gitguard snapshot # Output to stdout
|
|
69
|
+
gitguard snapshot -o snapshot.json # Save to file
|
|
70
|
+
gitguard snapshot --pretty # Pretty-print JSON
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### `gitguard send`
|
|
74
|
+
|
|
75
|
+
Capture repository state and send to GitGuard for AI analysis.
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
gitguard send # Send to default API (localhost:3000)
|
|
79
|
+
gitguard send -u https://api.example.com # Custom API URL
|
|
80
|
+
gitguard send --open # Open incident room in browser
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Requirements
|
|
84
|
+
|
|
85
|
+
- Node.js 18+
|
|
86
|
+
- Git repository with issues (conflicts, detached HEAD, rebase in progress)
|
|
87
|
+
- Build the CLI first: `pnpm build:cli` or `cd apps/cli && pnpm build`
|
|
88
|
+
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { UnmergedFile } from '@gitguard/schema';
|
|
2
|
+
/**
|
|
3
|
+
* Extract conflict blocks from unmerged files.
|
|
4
|
+
* Scans for <<<<<<<, =======, >>>>>>> markers.
|
|
5
|
+
*/
|
|
6
|
+
export declare function extractConflicts(repoRoot: string, unmergedPaths: string[]): Promise<UnmergedFile[]>;
|
|
7
|
+
//# sourceMappingURL=conflict-extractor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conflict-extractor.d.ts","sourceRoot":"","sources":["../../src/collectors/conflict-extractor.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAiB,MAAM,kBAAkB,CAAC;AAMpE;;;GAGG;AACH,wBAAsB,gBAAgB,CACpC,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,EAAE,GACtB,OAAO,CAAC,YAAY,EAAE,CAAC,CAkCzB"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { readFileSync, existsSync } from 'node:fs';
|
|
2
|
+
import { resolve } from 'node:path';
|
|
3
|
+
const MAX_BLOCKS_PER_FILE = 3;
|
|
4
|
+
const CONTEXT_LINES = 10;
|
|
5
|
+
const MAX_BLOCK_SIZE = 2000; // characters
|
|
6
|
+
/**
|
|
7
|
+
* Extract conflict blocks from unmerged files.
|
|
8
|
+
* Scans for <<<<<<<, =======, >>>>>>> markers.
|
|
9
|
+
*/
|
|
10
|
+
export async function extractConflicts(repoRoot, unmergedPaths) {
|
|
11
|
+
const results = [];
|
|
12
|
+
for (const filePath of unmergedPaths) {
|
|
13
|
+
const fullPath = resolve(repoRoot, filePath);
|
|
14
|
+
if (!existsSync(fullPath)) {
|
|
15
|
+
results.push({
|
|
16
|
+
path: filePath,
|
|
17
|
+
conflictBlocks: [],
|
|
18
|
+
});
|
|
19
|
+
continue;
|
|
20
|
+
}
|
|
21
|
+
try {
|
|
22
|
+
let content = readFileSync(fullPath, 'utf-8');
|
|
23
|
+
// Normalize line endings
|
|
24
|
+
content = content.replace(/\r\n/g, '\n');
|
|
25
|
+
const blocks = extractConflictBlocks(content);
|
|
26
|
+
results.push({
|
|
27
|
+
path: filePath,
|
|
28
|
+
conflictBlocks: blocks.slice(0, MAX_BLOCKS_PER_FILE),
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
results.push({
|
|
33
|
+
path: filePath,
|
|
34
|
+
conflictBlocks: [],
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return results;
|
|
39
|
+
}
|
|
40
|
+
function extractConflictBlocks(content) {
|
|
41
|
+
const lines = content.split('\n');
|
|
42
|
+
const blocks = [];
|
|
43
|
+
let i = 0;
|
|
44
|
+
while (i < lines.length && blocks.length < MAX_BLOCKS_PER_FILE) {
|
|
45
|
+
const line = lines[i];
|
|
46
|
+
// Look for conflict start marker
|
|
47
|
+
if (line.startsWith('<<<<<<<')) {
|
|
48
|
+
const startLine = i;
|
|
49
|
+
let separatorLine = -1;
|
|
50
|
+
let endLine = -1;
|
|
51
|
+
// Find separator and end
|
|
52
|
+
for (let j = i + 1; j < lines.length; j++) {
|
|
53
|
+
if (lines[j].startsWith('=======')) {
|
|
54
|
+
separatorLine = j;
|
|
55
|
+
}
|
|
56
|
+
else if (lines[j].startsWith('>>>>>>>') && separatorLine !== -1) {
|
|
57
|
+
endLine = j;
|
|
58
|
+
break;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
if (separatorLine !== -1 && endLine !== -1) {
|
|
62
|
+
// Extract ours (between <<<< and ====)
|
|
63
|
+
const oursLines = lines.slice(startLine + 1, separatorLine);
|
|
64
|
+
const oursContent = truncate(oursLines.join('\n'));
|
|
65
|
+
// Extract theirs (between ==== and >>>>)
|
|
66
|
+
const theirsLines = lines.slice(separatorLine + 1, endLine);
|
|
67
|
+
const theirsContent = truncate(theirsLines.join('\n'));
|
|
68
|
+
// Extract context (lines around the conflict)
|
|
69
|
+
const contextStart = Math.max(0, startLine - CONTEXT_LINES);
|
|
70
|
+
const contextEnd = Math.min(lines.length, endLine + CONTEXT_LINES + 1);
|
|
71
|
+
const contextLines = lines.slice(contextStart, contextEnd);
|
|
72
|
+
const context = truncate(contextLines.join('\n'));
|
|
73
|
+
blocks.push({
|
|
74
|
+
startLine: startLine + 1, // 1-indexed for display
|
|
75
|
+
endLine: endLine + 1,
|
|
76
|
+
oursContent,
|
|
77
|
+
theirsContent,
|
|
78
|
+
context,
|
|
79
|
+
});
|
|
80
|
+
i = endLine + 1;
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
i++;
|
|
85
|
+
}
|
|
86
|
+
return blocks;
|
|
87
|
+
}
|
|
88
|
+
function truncate(text) {
|
|
89
|
+
if (text.length <= MAX_BLOCK_SIZE) {
|
|
90
|
+
return text;
|
|
91
|
+
}
|
|
92
|
+
return text.slice(0, MAX_BLOCK_SIZE) + '\n... [truncated]';
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=conflict-extractor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conflict-extractor.js","sourceRoot":"","sources":["../../src/collectors/conflict-extractor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface GitInfo {
|
|
2
|
+
repoRoot: string;
|
|
3
|
+
gitDir: string;
|
|
4
|
+
status: string;
|
|
5
|
+
branches: string;
|
|
6
|
+
log: string;
|
|
7
|
+
reflog: string;
|
|
8
|
+
commitGraph: string;
|
|
9
|
+
diffStat: string;
|
|
10
|
+
mergeHead: string | null;
|
|
11
|
+
mergeMessage: string | null;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Collect all git information needed for snapshot.
|
|
15
|
+
* Uses only git commands - no direct file system access to .git
|
|
16
|
+
*/
|
|
17
|
+
export declare function collectGitInfo(): Promise<GitInfo>;
|
|
18
|
+
//# sourceMappingURL=git-info.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-info.d.ts","sourceRoot":"","sources":["../../src/collectors/git-info.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,OAAO;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED;;;GAGG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,OAAO,CAAC,CA8DvD"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { execGit } from '../utils/exec.js';
|
|
2
|
+
/**
|
|
3
|
+
* Collect all git information needed for snapshot.
|
|
4
|
+
* Uses only git commands - no direct file system access to .git
|
|
5
|
+
*/
|
|
6
|
+
export async function collectGitInfo() {
|
|
7
|
+
// Get repo root
|
|
8
|
+
const repoRootResult = execGit(['rev-parse', '--show-toplevel']);
|
|
9
|
+
if (!repoRootResult.success) {
|
|
10
|
+
throw new Error('Not a git repository (or any of the parent directories)');
|
|
11
|
+
}
|
|
12
|
+
const repoRoot = repoRootResult.stdout.trim();
|
|
13
|
+
// Get git directory (handles worktrees correctly)
|
|
14
|
+
const gitDirResult = execGit(['rev-parse', '--git-dir']);
|
|
15
|
+
if (!gitDirResult.success) {
|
|
16
|
+
throw new Error('Could not determine git directory');
|
|
17
|
+
}
|
|
18
|
+
const gitDir = gitDirResult.stdout.trim();
|
|
19
|
+
// Get status with porcelain v2 format
|
|
20
|
+
const statusResult = execGit(['status', '--porcelain=v2', '--branch']);
|
|
21
|
+
const status = statusResult.stdout;
|
|
22
|
+
// Get branches with verbose info
|
|
23
|
+
const branchesResult = execGit(['branch', '-vv']);
|
|
24
|
+
const branches = branchesResult.stdout;
|
|
25
|
+
// Get recent log
|
|
26
|
+
const logResult = execGit(['log', '--oneline', '--decorate', '-n', '30']);
|
|
27
|
+
const log = logResult.stdout;
|
|
28
|
+
// Get reflog
|
|
29
|
+
const reflogResult = execGit(['reflog', '-n', '30']);
|
|
30
|
+
const reflog = reflogResult.stdout;
|
|
31
|
+
// NEW: Get commit graph for visualization
|
|
32
|
+
const graphResult = execGit(['log', '--graph', '--oneline', '--decorate', '--all', '-n', '30']);
|
|
33
|
+
const commitGraph = graphResult.stdout;
|
|
34
|
+
// NEW: Get diff stat for file summary
|
|
35
|
+
const diffStatResult = execGit(['diff', '--stat', '--numstat']);
|
|
36
|
+
const diffStat = diffStatResult.stdout;
|
|
37
|
+
// NEW: Check for MERGE_HEAD (indicates we're in a merge)
|
|
38
|
+
const mergeHeadResult = execGit(['rev-parse', 'MERGE_HEAD']);
|
|
39
|
+
const mergeHead = mergeHeadResult.success ? mergeHeadResult.stdout.trim() : null;
|
|
40
|
+
// NEW: Get merge message if available
|
|
41
|
+
let mergeMessage = null;
|
|
42
|
+
if (mergeHead) {
|
|
43
|
+
const msgResult = execGit(['log', '-1', '--format=%B', 'MERGE_HEAD']);
|
|
44
|
+
mergeMessage = msgResult.success ? msgResult.stdout.trim() : null;
|
|
45
|
+
}
|
|
46
|
+
return {
|
|
47
|
+
repoRoot,
|
|
48
|
+
gitDir,
|
|
49
|
+
status,
|
|
50
|
+
branches,
|
|
51
|
+
log,
|
|
52
|
+
reflog,
|
|
53
|
+
commitGraph,
|
|
54
|
+
diffStat,
|
|
55
|
+
mergeHead,
|
|
56
|
+
mergeMessage,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=git-info.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-info.js","sourceRoot":"","sources":["../../src/collectors/git-info.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAe3C;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc;IAClC,gBAAgB;IAChB,MAAM,cAAc,GAAG,OAAO,CAAC,CAAC,WAAW,EAAE,iBAAiB,CAAC,CAAC,CAAC;IACjE,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CAAC,yDAAyD,CAAC,CAAC;IAC7E,CAAC;IACD,MAAM,QAAQ,GAAG,cAAc,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;IAE9C,kDAAkD;IAClD,MAAM,YAAY,GAAG,OAAO,CAAC,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC,CAAC;IACzD,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;IACvD,CAAC;IACD,MAAM,MAAM,GAAG,YAAY,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;IAE1C,sCAAsC;IACtC,MAAM,YAAY,GAAG,OAAO,CAAC,CAAC,QAAQ,EAAE,gBAAgB,EAAE,UAAU,CAAC,CAAC,CAAC;IACvE,MAAM,MAAM,GAAG,YAAY,CAAC,MAAM,CAAC;IAEnC,iCAAiC;IACjC,MAAM,cAAc,GAAG,OAAO,CAAC,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC;IAClD,MAAM,QAAQ,GAAG,cAAc,CAAC,MAAM,CAAC;IAEvC,iBAAiB;IACjB,MAAM,SAAS,GAAG,OAAO,CAAC,CAAC,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;IAC1E,MAAM,GAAG,GAAG,SAAS,CAAC,MAAM,CAAC;IAE7B,aAAa;IACb,MAAM,YAAY,GAAG,OAAO,CAAC,CAAC,QAAQ,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;IACrD,MAAM,MAAM,GAAG,YAAY,CAAC,MAAM,CAAC;IAEnC,0CAA0C;IAC1C,MAAM,WAAW,GAAG,OAAO,CAAC,CAAC,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,YAAY,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;IAChG,MAAM,WAAW,GAAG,WAAW,CAAC,MAAM,CAAC;IAEvC,sCAAsC;IACtC,MAAM,cAAc,GAAG,OAAO,CAAC,CAAC,MAAM,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAC,CAAC;IAChE,MAAM,QAAQ,GAAG,cAAc,CAAC,MAAM,CAAC;IAEvC,yDAAyD;IACzD,MAAM,eAAe,GAAG,OAAO,CAAC,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC,CAAC;IAC7D,MAAM,SAAS,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;IAEjF,sCAAsC;IACtC,IAAI,YAAY,GAAkB,IAAI,CAAC;IACvC,IAAI,SAAS,EAAE,CAAC;QACd,MAAM,SAAS,GAAG,OAAO,CAAC,CAAC,KAAK,EAAE,IAAI,EAAE,aAAa,EAAE,YAAY,CAAC,CAAC,CAAC;QACtE,YAAY,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;IACpE,CAAC;IAED,OAAO;QACL,QAAQ;QACR,MAAM;QACN,MAAM;QACN,QAAQ;QACR,GAAG;QACH,MAAM;QACN,WAAW;QACX,QAAQ;QACR,SAAS;QACT,YAAY;KACb,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { RebaseState } from '@gitguard/schema';
|
|
2
|
+
/**
|
|
3
|
+
* Detect if a rebase is in progress and gather state info.
|
|
4
|
+
* Uses git rev-parse --git-path to locate rebase directories cross-platform.
|
|
5
|
+
*/
|
|
6
|
+
export declare function detectRebaseState(gitDir: string): Promise<RebaseState>;
|
|
7
|
+
//# sourceMappingURL=rebase-detector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rebase-detector.d.ts","sourceRoot":"","sources":["../../src/collectors/rebase-detector.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAGpD;;;GAGG;AACH,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAuB5E"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
2
|
+
import { resolve } from 'node:path';
|
|
3
|
+
import { execGit } from '../utils/exec.js';
|
|
4
|
+
/**
|
|
5
|
+
* Detect if a rebase is in progress and gather state info.
|
|
6
|
+
* Uses git rev-parse --git-path to locate rebase directories cross-platform.
|
|
7
|
+
*/
|
|
8
|
+
export async function detectRebaseState(gitDir) {
|
|
9
|
+
// Check for rebase-merge (interactive rebase)
|
|
10
|
+
const rebaseMergeResult = execGit(['rev-parse', '--git-path', 'rebase-merge']);
|
|
11
|
+
const rebaseMergePath = rebaseMergeResult.stdout.trim();
|
|
12
|
+
const resolvedMergePath = resolve(process.cwd(), rebaseMergePath);
|
|
13
|
+
if (existsSync(resolvedMergePath)) {
|
|
14
|
+
return parseRebaseState(resolvedMergePath, 'merge');
|
|
15
|
+
}
|
|
16
|
+
// Check for rebase-apply (regular rebase, am, etc.)
|
|
17
|
+
const rebaseApplyResult = execGit(['rev-parse', '--git-path', 'rebase-apply']);
|
|
18
|
+
const rebaseApplyPath = rebaseApplyResult.stdout.trim();
|
|
19
|
+
const resolvedApplyPath = resolve(process.cwd(), rebaseApplyPath);
|
|
20
|
+
if (existsSync(resolvedApplyPath)) {
|
|
21
|
+
return parseRebaseState(resolvedApplyPath, 'apply');
|
|
22
|
+
}
|
|
23
|
+
return {
|
|
24
|
+
inProgress: false,
|
|
25
|
+
type: 'none',
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
function parseRebaseState(rebasePath, type) {
|
|
29
|
+
const state = {
|
|
30
|
+
inProgress: true,
|
|
31
|
+
type,
|
|
32
|
+
};
|
|
33
|
+
// Try to read head-name (original branch)
|
|
34
|
+
const headNamePath = resolve(rebasePath, 'head-name');
|
|
35
|
+
if (existsSync(headNamePath)) {
|
|
36
|
+
const headName = readFileSync(headNamePath, 'utf-8').trim();
|
|
37
|
+
// Remove refs/heads/ prefix
|
|
38
|
+
state.headName = headName.replace(/^refs\/heads\//, '');
|
|
39
|
+
}
|
|
40
|
+
// Try to read onto (target commit)
|
|
41
|
+
const ontoPath = resolve(rebasePath, 'onto');
|
|
42
|
+
if (existsSync(ontoPath)) {
|
|
43
|
+
state.onto = readFileSync(ontoPath, 'utf-8').trim();
|
|
44
|
+
}
|
|
45
|
+
// Try to read msgnum (current step)
|
|
46
|
+
const msgnumPath = resolve(rebasePath, 'msgnum');
|
|
47
|
+
if (existsSync(msgnumPath)) {
|
|
48
|
+
state.currentStep = parseInt(readFileSync(msgnumPath, 'utf-8').trim(), 10);
|
|
49
|
+
}
|
|
50
|
+
// Try to read end (total steps)
|
|
51
|
+
const endPath = resolve(rebasePath, 'end');
|
|
52
|
+
if (existsSync(endPath)) {
|
|
53
|
+
state.totalSteps = parseInt(readFileSync(endPath, 'utf-8').trim(), 10);
|
|
54
|
+
}
|
|
55
|
+
return state;
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=rebase-detector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rebase-detector.js","sourceRoot":"","sources":["../../src/collectors/rebase-detector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAE3C;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,MAAc;IACpD,8CAA8C;IAC9C,MAAM,iBAAiB,GAAG,OAAO,CAAC,CAAC,WAAW,EAAE,YAAY,EAAE,cAAc,CAAC,CAAC,CAAC;IAC/E,MAAM,eAAe,GAAG,iBAAiB,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;IACxD,MAAM,iBAAiB,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,eAAe,CAAC,CAAC;IAElE,IAAI,UAAU,CAAC,iBAAiB,CAAC,EAAE,CAAC;QAClC,OAAO,gBAAgB,CAAC,iBAAiB,EAAE,OAAO,CAAC,CAAC;IACtD,CAAC;IAED,oDAAoD;IACpD,MAAM,iBAAiB,GAAG,OAAO,CAAC,CAAC,WAAW,EAAE,YAAY,EAAE,cAAc,CAAC,CAAC,CAAC;IAC/E,MAAM,eAAe,GAAG,iBAAiB,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;IACxD,MAAM,iBAAiB,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,eAAe,CAAC,CAAC;IAElE,IAAI,UAAU,CAAC,iBAAiB,CAAC,EAAE,CAAC;QAClC,OAAO,gBAAgB,CAAC,iBAAiB,EAAE,OAAO,CAAC,CAAC;IACtD,CAAC;IAED,OAAO;QACL,UAAU,EAAE,KAAK;QACjB,IAAI,EAAE,MAAM;KACb,CAAC;AACJ,CAAC;AAED,SAAS,gBAAgB,CAAC,UAAkB,EAAE,IAAuB;IACnE,MAAM,KAAK,GAAgB;QACzB,UAAU,EAAE,IAAI;QAChB,IAAI;KACL,CAAC;IAEF,0CAA0C;IAC1C,MAAM,YAAY,GAAG,OAAO,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;IACtD,IAAI,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QAC7B,MAAM,QAAQ,GAAG,YAAY,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;QAC5D,4BAA4B;QAC5B,KAAK,CAAC,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC,gBAAgB,EAAE,EAAE,CAAC,CAAC;IAC1D,CAAC;IAED,mCAAmC;IACnC,MAAM,QAAQ,GAAG,OAAO,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IAC7C,IAAI,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QACzB,KAAK,CAAC,IAAI,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;IACtD,CAAC;IAED,oCAAoC;IACpC,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;IACjD,IAAI,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC3B,KAAK,CAAC,WAAW,GAAG,QAAQ,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;IAC7E,CAAC;IAED,gCAAgC;IAChC,MAAM,OAAO,GAAG,OAAO,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;IAC3C,IAAI,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QACxB,KAAK,CAAC,UAAU,GAAG,QAAQ,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;IACzE,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"send.d.ts","sourceRoot":"","sources":["../../src/commands/send.ts"],"names":[],"mappings":"AAYA,UAAU,WAAW;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAWD,wBAAsB,WAAW,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAuKrE"}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { SnapshotV1Schema } from '@gitguard/schema';
|
|
2
|
+
import { collectGitInfo } from '../collectors/git-info.js';
|
|
3
|
+
import { parseStatus } from '../parsers/status-parser.js';
|
|
4
|
+
import { parseBranches } from '../parsers/branch-parser.js';
|
|
5
|
+
import { parseLog } from '../parsers/log-parser.js';
|
|
6
|
+
import { parseReflog } from '../parsers/reflog-parser.js';
|
|
7
|
+
import { parseDiffStat } from '../parsers/diffstat-parser.js';
|
|
8
|
+
import { detectRebaseState } from '../collectors/rebase-detector.js';
|
|
9
|
+
import { extractConflicts } from '../collectors/conflict-extractor.js';
|
|
10
|
+
const DEFAULT_API_URL = 'http://localhost:3000';
|
|
11
|
+
export async function sendCommand(options) {
|
|
12
|
+
const apiUrl = options.apiUrl || process.env.GITGUARD_API_URL || DEFAULT_API_URL;
|
|
13
|
+
const requestId = `cli-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;
|
|
14
|
+
console.error(`[CLI:SEND:${requestId}] ========================================`);
|
|
15
|
+
console.error(`[CLI:SEND:${requestId}] 🚀 Starting GitGuard snapshot collection`);
|
|
16
|
+
console.error(`[CLI:SEND:${requestId}] API URL: ${apiUrl}`);
|
|
17
|
+
console.error(`[CLI:SEND:${requestId}] Timestamp: ${new Date().toISOString()}`);
|
|
18
|
+
try {
|
|
19
|
+
console.error(`[CLI:SEND:${requestId}] 📥 Collecting Git repository information...`);
|
|
20
|
+
// Collect git information
|
|
21
|
+
const gitInfo = await collectGitInfo();
|
|
22
|
+
console.error(`[CLI:SEND:${requestId}] ✅ Git info collected`);
|
|
23
|
+
console.error(`[CLI:SEND:${requestId}] Repo root: ${gitInfo.repoRoot}`);
|
|
24
|
+
console.error(`[CLI:SEND:${requestId}] Git dir: ${gitInfo.gitDir}`);
|
|
25
|
+
console.error(`[CLI:SEND:${requestId}] 🔍 Parsing Git status...`);
|
|
26
|
+
// Parse status
|
|
27
|
+
const statusInfo = parseStatus(gitInfo.status);
|
|
28
|
+
console.error(`[CLI:SEND:${requestId}] ✅ Status parsed`);
|
|
29
|
+
console.error(`[CLI:SEND:${requestId}] Branch: ${statusInfo.branch}`);
|
|
30
|
+
console.error(`[CLI:SEND:${requestId}] Unmerged files: ${statusInfo.unmergedPaths.length}`);
|
|
31
|
+
console.error(`[CLI:SEND:${requestId}] Staged: ${statusInfo.stagedFiles.length}, Modified: ${statusInfo.modifiedFiles.length}`);
|
|
32
|
+
console.error(`[CLI:SEND:${requestId}] 🔍 Parsing branches...`);
|
|
33
|
+
// Parse branches
|
|
34
|
+
const branchInfo = parseBranches(gitInfo.branches, statusInfo.branch);
|
|
35
|
+
console.error(`[CLI:SEND:${requestId}] ✅ Branches parsed: ${branchInfo.head}`);
|
|
36
|
+
console.error(`[CLI:SEND:${requestId}] 🔍 Parsing commit logs...`);
|
|
37
|
+
// Parse logs
|
|
38
|
+
const logEntries = parseLog(gitInfo.log);
|
|
39
|
+
const reflogEntries = parseReflog(gitInfo.reflog);
|
|
40
|
+
console.error(`[CLI:SEND:${requestId}] ✅ Logs parsed: ${logEntries.length} commits, ${reflogEntries.length} reflog entries`);
|
|
41
|
+
console.error(`[CLI:SEND:${requestId}] 🔍 Parsing diff stats...`);
|
|
42
|
+
// Parse diff stats
|
|
43
|
+
const diffStats = parseDiffStat(gitInfo.diffStat);
|
|
44
|
+
console.error(`[CLI:SEND:${requestId}] ✅ Diff stats parsed: ${diffStats.length} files`);
|
|
45
|
+
console.error(`[CLI:SEND:${requestId}] 🔍 Detecting rebase state...`);
|
|
46
|
+
// Detect rebase state
|
|
47
|
+
const rebaseState = await detectRebaseState(gitInfo.gitDir);
|
|
48
|
+
console.error(`[CLI:SEND:${requestId}] ✅ Rebase state: ${rebaseState.inProgress ? 'IN PROGRESS' : 'none'}`);
|
|
49
|
+
console.error(`[CLI:SEND:${requestId}] 🔍 Extracting conflict details...`);
|
|
50
|
+
// Extract conflict details
|
|
51
|
+
const unmergedFiles = await extractConflicts(gitInfo.repoRoot, statusInfo.unmergedPaths.slice(0, 10) // Extract up to 10 conflict files
|
|
52
|
+
);
|
|
53
|
+
console.error(`[CLI:SEND:${requestId}] ✅ Conflicts extracted: ${unmergedFiles.length} files with conflicts`);
|
|
54
|
+
// Build snapshot
|
|
55
|
+
const snapshot = {
|
|
56
|
+
version: 1,
|
|
57
|
+
timestamp: new Date().toISOString(),
|
|
58
|
+
platform: process.platform,
|
|
59
|
+
repoRoot: gitInfo.repoRoot,
|
|
60
|
+
gitDir: gitInfo.gitDir,
|
|
61
|
+
branch: branchInfo,
|
|
62
|
+
isDetachedHead: statusInfo.isDetachedHead,
|
|
63
|
+
rebaseState,
|
|
64
|
+
unmergedFiles,
|
|
65
|
+
stagedFiles: statusInfo.stagedFiles,
|
|
66
|
+
modifiedFiles: statusInfo.modifiedFiles,
|
|
67
|
+
untrackedFiles: statusInfo.untrackedFiles,
|
|
68
|
+
recentLog: logEntries,
|
|
69
|
+
recentReflog: reflogEntries,
|
|
70
|
+
commitGraph: gitInfo.commitGraph || undefined,
|
|
71
|
+
diffStats: diffStats.length > 0 ? diffStats : undefined,
|
|
72
|
+
mergeHead: gitInfo.mergeHead || undefined,
|
|
73
|
+
mergeMessage: gitInfo.mergeMessage || undefined,
|
|
74
|
+
rawStatus: gitInfo.status,
|
|
75
|
+
rawBranches: gitInfo.branches,
|
|
76
|
+
};
|
|
77
|
+
console.error(`[CLI:SEND:${requestId}] ✅ Validating snapshot with schema...`);
|
|
78
|
+
// Validate with Zod
|
|
79
|
+
const validated = SnapshotV1Schema.parse(snapshot);
|
|
80
|
+
console.error(`[CLI:SEND:${requestId}] ✅ Snapshot validated`);
|
|
81
|
+
console.error(`[CLI:SEND:${requestId}] Snapshot size: ${JSON.stringify(validated).length} bytes`);
|
|
82
|
+
console.error(`[CLI:SEND:${requestId}] 📤 Uploading snapshot to GitGuard API...`);
|
|
83
|
+
console.error(`[CLI:SEND:${requestId}] Endpoint: ${apiUrl}/api/snapshots/ingest`);
|
|
84
|
+
const uploadStart = Date.now();
|
|
85
|
+
// Send to API
|
|
86
|
+
const response = await fetch(`${apiUrl}/api/snapshots/ingest`, {
|
|
87
|
+
method: 'POST',
|
|
88
|
+
headers: {
|
|
89
|
+
'Content-Type': 'application/json',
|
|
90
|
+
},
|
|
91
|
+
body: JSON.stringify({ snapshot: validated }),
|
|
92
|
+
});
|
|
93
|
+
const uploadDuration = Date.now() - uploadStart;
|
|
94
|
+
console.error(`[CLI:SEND:${requestId}] Upload duration: ${uploadDuration}ms`);
|
|
95
|
+
console.error(`[CLI:SEND:${requestId}] Response status: ${response.status}`);
|
|
96
|
+
if (!response.ok) {
|
|
97
|
+
let errorMessage = `Server returned ${response.status}`;
|
|
98
|
+
try {
|
|
99
|
+
const errorData = await response.json();
|
|
100
|
+
if (errorData.error) {
|
|
101
|
+
errorMessage = errorData.error;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
// Ignore JSON parse errors
|
|
106
|
+
}
|
|
107
|
+
console.error(`[CLI:SEND:${requestId}] ❌ Upload failed: ${errorMessage}`);
|
|
108
|
+
throw new Error(errorMessage);
|
|
109
|
+
}
|
|
110
|
+
const result = await response.json();
|
|
111
|
+
console.error(`[CLI:SEND:${requestId}] ✅ Upload successful`);
|
|
112
|
+
console.error(`[CLI:SEND:${requestId}] Session ID: ${result.sessionId}`);
|
|
113
|
+
console.error(`[CLI:SEND:${requestId}] Issue type: ${result.analysis.issueType}`);
|
|
114
|
+
// Display results
|
|
115
|
+
console.log('');
|
|
116
|
+
console.log('='.repeat(60));
|
|
117
|
+
console.log('');
|
|
118
|
+
console.log(` Issue Type: ${result.analysis.issueType.replace('_', ' ').toUpperCase()}`);
|
|
119
|
+
console.log(` Summary: ${result.analysis.summary}`);
|
|
120
|
+
console.log('');
|
|
121
|
+
console.log(` Incident Room: ${result.url}`);
|
|
122
|
+
console.log('');
|
|
123
|
+
console.log('='.repeat(60));
|
|
124
|
+
console.log('');
|
|
125
|
+
// Try to open in browser if requested
|
|
126
|
+
if (options.open) {
|
|
127
|
+
try {
|
|
128
|
+
const open = await getOpenCommand();
|
|
129
|
+
if (open) {
|
|
130
|
+
const { exec } = await import('node:child_process');
|
|
131
|
+
exec(`${open} "${result.url}"`);
|
|
132
|
+
console.error(`[CLI:SEND:${requestId}] 🌐 Opening incident room in browser...`);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
catch {
|
|
136
|
+
// Silently fail if we can't open the browser
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
console.error(`[CLI:SEND:${requestId}] ✅ Command completed successfully`);
|
|
140
|
+
console.error(`[CLI:SEND:${requestId}] ========================================`);
|
|
141
|
+
}
|
|
142
|
+
catch (error) {
|
|
143
|
+
console.error(`[CLI:SEND:${requestId}] ❌ Command failed`);
|
|
144
|
+
if (error instanceof Error) {
|
|
145
|
+
console.error(`[CLI:SEND:${requestId}] Error: ${error.message}`);
|
|
146
|
+
if (error.message.includes('not a git repository')) {
|
|
147
|
+
console.error('Please run this command from within a git repository.');
|
|
148
|
+
}
|
|
149
|
+
else if (error.message.includes('fetch')) {
|
|
150
|
+
console.error(`Could not connect to ${apiUrl}. Is the server running?`);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
console.error(`[CLI:SEND:${requestId}] ========================================`);
|
|
154
|
+
process.exit(1);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
async function getOpenCommand() {
|
|
158
|
+
switch (process.platform) {
|
|
159
|
+
case 'darwin':
|
|
160
|
+
return 'open';
|
|
161
|
+
case 'win32':
|
|
162
|
+
return 'start';
|
|
163
|
+
case 'linux':
|
|
164
|
+
return 'xdg-open';
|
|
165
|
+
default:
|
|
166
|
+
return null;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
//# sourceMappingURL=send.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"send.js","sourceRoot":"","sources":["../../src/commands/send.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snapshot.d.ts","sourceRoot":"","sources":["../../src/commands/snapshot.ts"],"names":[],"mappings":"AAWA,UAAU,eAAe;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,wBAAsB,eAAe,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAqG7E"}
|