@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.
Files changed (50) hide show
  1. package/README.md +88 -0
  2. package/dist/collectors/conflict-extractor.d.ts +7 -0
  3. package/dist/collectors/conflict-extractor.d.ts.map +1 -0
  4. package/dist/collectors/conflict-extractor.js +94 -0
  5. package/dist/collectors/conflict-extractor.js.map +1 -0
  6. package/dist/collectors/git-info.d.ts +18 -0
  7. package/dist/collectors/git-info.d.ts.map +1 -0
  8. package/dist/collectors/git-info.js +59 -0
  9. package/dist/collectors/git-info.js.map +1 -0
  10. package/dist/collectors/rebase-detector.d.ts +7 -0
  11. package/dist/collectors/rebase-detector.d.ts.map +1 -0
  12. package/dist/collectors/rebase-detector.js +57 -0
  13. package/dist/collectors/rebase-detector.js.map +1 -0
  14. package/dist/commands/send.d.ts +7 -0
  15. package/dist/commands/send.d.ts.map +1 -0
  16. package/dist/commands/send.js +169 -0
  17. package/dist/commands/send.js.map +1 -0
  18. package/dist/commands/snapshot.d.ts +7 -0
  19. package/dist/commands/snapshot.d.ts.map +1 -0
  20. package/dist/commands/snapshot.js +92 -0
  21. package/dist/commands/snapshot.js.map +1 -0
  22. package/dist/index.d.ts +3 -0
  23. package/dist/index.d.ts.map +1 -0
  24. package/dist/index.js +22 -0
  25. package/dist/index.js.map +1 -0
  26. package/dist/parsers/branch-parser.d.ts +7 -0
  27. package/dist/parsers/branch-parser.d.ts.map +1 -0
  28. package/dist/parsers/branch-parser.js +20 -0
  29. package/dist/parsers/branch-parser.js.map +1 -0
  30. package/dist/parsers/diffstat-parser.d.ts +8 -0
  31. package/dist/parsers/diffstat-parser.d.ts.map +1 -0
  32. package/dist/parsers/diffstat-parser.js +42 -0
  33. package/dist/parsers/diffstat-parser.js.map +1 -0
  34. package/dist/parsers/log-parser.d.ts +8 -0
  35. package/dist/parsers/log-parser.d.ts.map +1 -0
  36. package/dist/parsers/log-parser.js +46 -0
  37. package/dist/parsers/log-parser.js.map +1 -0
  38. package/dist/parsers/reflog-parser.d.ts +8 -0
  39. package/dist/parsers/reflog-parser.d.ts.map +1 -0
  40. package/dist/parsers/reflog-parser.js +65 -0
  41. package/dist/parsers/reflog-parser.js.map +1 -0
  42. package/dist/parsers/status-parser.d.ts +27 -0
  43. package/dist/parsers/status-parser.d.ts.map +1 -0
  44. package/dist/parsers/status-parser.js +110 -0
  45. package/dist/parsers/status-parser.js.map +1 -0
  46. package/dist/utils/exec.d.ts +14 -0
  47. package/dist/utils/exec.d.ts.map +1 -0
  48. package/dist/utils/exec.js +54 -0
  49. package/dist/utils/exec.js.map +1 -0
  50. package/package.json +46 -0
@@ -0,0 +1,92 @@
1
+ import { writeFileSync } from 'node:fs';
2
+ import { SnapshotV1Schema } from '@gitguard/schema';
3
+ import { collectGitInfo } from '../collectors/git-info.js';
4
+ import { parseStatus } from '../parsers/status-parser.js';
5
+ import { parseBranches } from '../parsers/branch-parser.js';
6
+ import { parseLog } from '../parsers/log-parser.js';
7
+ import { parseReflog } from '../parsers/reflog-parser.js';
8
+ import { parseDiffStat } from '../parsers/diffstat-parser.js';
9
+ import { detectRebaseState } from '../collectors/rebase-detector.js';
10
+ import { extractConflicts } from '../collectors/conflict-extractor.js';
11
+ export async function snapshotCommand(options) {
12
+ const requestId = `snapshot-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;
13
+ console.error(`[CLI:SNAPSHOT:${requestId}] ========================================`);
14
+ console.error(`[CLI:SNAPSHOT:${requestId}] 📸 Starting snapshot generation`);
15
+ console.error(`[CLI:SNAPSHOT:${requestId}] Output: ${options.output || 'stdout'}`);
16
+ console.error(`[CLI:SNAPSHOT:${requestId}] Pretty: ${options.pretty || false}`);
17
+ try {
18
+ console.error(`[CLI:SNAPSHOT:${requestId}] 📥 Collecting Git repository information...`);
19
+ // Collect git information
20
+ const gitInfo = await collectGitInfo();
21
+ console.error(`[CLI:SNAPSHOT:${requestId}] ✅ Git info collected`);
22
+ // Parse status
23
+ const statusInfo = parseStatus(gitInfo.status);
24
+ // Parse branches
25
+ const branchInfo = parseBranches(gitInfo.branches, statusInfo.branch);
26
+ // Parse logs
27
+ const logEntries = parseLog(gitInfo.log);
28
+ const reflogEntries = parseReflog(gitInfo.reflog);
29
+ // Parse diff stats
30
+ const diffStats = parseDiffStat(gitInfo.diffStat);
31
+ // Detect rebase state
32
+ const rebaseState = await detectRebaseState(gitInfo.gitDir);
33
+ // Extract conflict details for up to 5 unmerged files (increased for better conflict exploration)
34
+ const unmergedFiles = await extractConflicts(gitInfo.repoRoot, statusInfo.unmergedPaths.slice(0, 5));
35
+ // Build snapshot
36
+ const snapshot = {
37
+ version: 1,
38
+ timestamp: new Date().toISOString(),
39
+ platform: process.platform,
40
+ repoRoot: gitInfo.repoRoot,
41
+ gitDir: gitInfo.gitDir,
42
+ branch: branchInfo,
43
+ isDetachedHead: statusInfo.isDetachedHead,
44
+ rebaseState,
45
+ unmergedFiles,
46
+ stagedFiles: statusInfo.stagedFiles,
47
+ modifiedFiles: statusInfo.modifiedFiles,
48
+ untrackedFiles: statusInfo.untrackedFiles,
49
+ recentLog: logEntries,
50
+ recentReflog: reflogEntries,
51
+ // NEW: Commit graph for history visualization
52
+ commitGraph: gitInfo.commitGraph || undefined,
53
+ // NEW: Diff stats for file summary
54
+ diffStats: diffStats.length > 0 ? diffStats : undefined,
55
+ // NEW: Merge metadata
56
+ mergeHead: gitInfo.mergeHead || undefined,
57
+ mergeMessage: gitInfo.mergeMessage || undefined,
58
+ rawStatus: gitInfo.status,
59
+ rawBranches: gitInfo.branches,
60
+ };
61
+ console.error(`[CLI:SNAPSHOT:${requestId}] ✅ Validating snapshot with schema...`);
62
+ // Validate with Zod
63
+ const validated = SnapshotV1Schema.parse(snapshot);
64
+ console.error(`[CLI:SNAPSHOT:${requestId}] ✅ Snapshot validated`);
65
+ console.error(`[CLI:SNAPSHOT:${requestId}] Snapshot size: ${JSON.stringify(validated).length} bytes`);
66
+ // Output
67
+ const jsonOutput = options.pretty
68
+ ? JSON.stringify(validated, null, 2)
69
+ : JSON.stringify(validated);
70
+ if (options.output) {
71
+ writeFileSync(options.output, jsonOutput, 'utf-8');
72
+ console.error(`[CLI:SNAPSHOT:${requestId}] ✅ Snapshot written to: ${options.output}`);
73
+ }
74
+ else {
75
+ console.log(jsonOutput);
76
+ console.error(`[CLI:SNAPSHOT:${requestId}] ✅ Snapshot output to stdout`);
77
+ }
78
+ console.error(`[CLI:SNAPSHOT:${requestId}] ========================================`);
79
+ }
80
+ catch (error) {
81
+ console.error(`[CLI:SNAPSHOT:${requestId}] ❌ Snapshot generation failed`);
82
+ if (error instanceof Error) {
83
+ console.error(`[CLI:SNAPSHOT:${requestId}] Error: ${error.message}`);
84
+ if (error.message.includes('not a git repository')) {
85
+ console.error('Please run this command from within a git repository.');
86
+ }
87
+ }
88
+ console.error(`[CLI:SNAPSHOT:${requestId}] ========================================`);
89
+ process.exit(1);
90
+ }
91
+ }
92
+ //# sourceMappingURL=snapshot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snapshot.js","sourceRoot":"","sources":["../../src/commands/snapshot.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env node
2
+ import { program } from 'commander';
3
+ import { snapshotCommand } from './commands/snapshot.js';
4
+ import { sendCommand } from './commands/send.js';
5
+ program
6
+ .name('gitguard')
7
+ .description('GitGuard Agent - Safe git recovery helper')
8
+ .version('1.0.0');
9
+ program
10
+ .command('snapshot')
11
+ .description('Generate a read-only snapshot of the current git repository state')
12
+ .option('-o, --output <file>', 'Write snapshot to file instead of stdout')
13
+ .option('--pretty', 'Pretty-print JSON output')
14
+ .action(snapshotCommand);
15
+ program
16
+ .command('send')
17
+ .description('Capture and send repository state to GitGuard for analysis')
18
+ .option('-u, --api-url <url>', 'GitGuard API URL (default: http://localhost:3000)')
19
+ .option('-o, --open', 'Open the incident room in browser after upload')
20
+ .action(sendCommand);
21
+ program.parse();
22
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEjD,OAAO;KACJ,IAAI,CAAC,UAAU,CAAC;KAChB,WAAW,CAAC,2CAA2C,CAAC;KACxD,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,OAAO;KACJ,OAAO,CAAC,UAAU,CAAC;KACnB,WAAW,CAAC,mEAAmE,CAAC;KAChF,MAAM,CAAC,qBAAqB,EAAE,0CAA0C,CAAC;KACzE,MAAM,CAAC,UAAU,EAAE,0BAA0B,CAAC;KAC9C,MAAM,CAAC,eAAe,CAAC,CAAC;AAE3B,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,4DAA4D,CAAC;KACzE,MAAM,CAAC,qBAAqB,EAAE,mDAAmD,CAAC;KAClF,MAAM,CAAC,YAAY,EAAE,gDAAgD,CAAC;KACtE,MAAM,CAAC,WAAW,CAAC,CAAC;AAEvB,OAAO,CAAC,KAAK,EAAE,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { BranchInfo } from '@gitguard/schema';
2
+ import type { StatusInfo } from './status-parser.js';
3
+ /**
4
+ * Parse branch information from git branch -vv and status info.
5
+ */
6
+ export declare function parseBranches(branchOutput: string, statusBranch: StatusInfo['branch']): BranchInfo;
7
+ //# sourceMappingURL=branch-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"branch-parser.d.ts","sourceRoot":"","sources":["../../src/parsers/branch-parser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAErD;;GAEG;AACH,wBAAgB,aAAa,CAC3B,YAAY,EAAE,MAAM,EACpB,YAAY,EAAE,UAAU,CAAC,QAAQ,CAAC,GACjC,UAAU,CAkBZ"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Parse branch information from git branch -vv and status info.
3
+ */
4
+ export function parseBranches(branchOutput, statusBranch) {
5
+ const result = {
6
+ head: statusBranch.head,
7
+ oid: statusBranch.oid,
8
+ };
9
+ if (statusBranch.upstream) {
10
+ result.upstream = statusBranch.upstream;
11
+ }
12
+ if (statusBranch.ahead !== undefined && statusBranch.behind !== undefined) {
13
+ result.aheadBehind = {
14
+ ahead: statusBranch.ahead,
15
+ behind: statusBranch.behind,
16
+ };
17
+ }
18
+ return result;
19
+ }
20
+ //# sourceMappingURL=branch-parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"branch-parser.js","sourceRoot":"","sources":["../../src/parsers/branch-parser.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,MAAM,UAAU,aAAa,CAC3B,YAAoB,EACpB,YAAkC;IAElC,MAAM,MAAM,GAAe;QACzB,IAAI,EAAE,YAAY,CAAC,IAAI;QACvB,GAAG,EAAE,YAAY,CAAC,GAAG;KACtB,CAAC;IAEF,IAAI,YAAY,CAAC,QAAQ,EAAE,CAAC;QAC1B,MAAM,CAAC,QAAQ,GAAG,YAAY,CAAC,QAAQ,CAAC;IAC1C,CAAC;IAED,IAAI,YAAY,CAAC,KAAK,KAAK,SAAS,IAAI,YAAY,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAC1E,MAAM,CAAC,WAAW,GAAG;YACnB,KAAK,EAAE,YAAY,CAAC,KAAK;YACzB,MAAM,EAAE,YAAY,CAAC,MAAM;SAC5B,CAAC;IACJ,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { DiffStat } from '@gitguard/schema';
2
+ /**
3
+ * Parse git diff --numstat output into structured diff stats.
4
+ * Format: additions<TAB>deletions<TAB>path
5
+ * For binary files: -<TAB>-<TAB>path
6
+ */
7
+ export declare function parseDiffStat(rawOutput: string): DiffStat[];
8
+ //# sourceMappingURL=diffstat-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diffstat-parser.d.ts","sourceRoot":"","sources":["../../src/parsers/diffstat-parser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEjD;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,QAAQ,EAAE,CAuC3D"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Parse git diff --numstat output into structured diff stats.
3
+ * Format: additions<TAB>deletions<TAB>path
4
+ * For binary files: -<TAB>-<TAB>path
5
+ */
6
+ export function parseDiffStat(rawOutput) {
7
+ if (!rawOutput.trim()) {
8
+ return [];
9
+ }
10
+ const stats = [];
11
+ const lines = rawOutput.split('\n').filter(Boolean);
12
+ for (const line of lines) {
13
+ // Skip the summary line (e.g., "3 files changed, 10 insertions(+)")
14
+ if (line.includes('files changed') || line.includes('file changed')) {
15
+ continue;
16
+ }
17
+ // Parse numstat format: additions<TAB>deletions<TAB>path
18
+ const parts = line.split('\t');
19
+ if (parts.length >= 3) {
20
+ const [addStr, delStr, ...pathParts] = parts;
21
+ const path = pathParts.join('\t'); // Handle paths with tabs
22
+ if (addStr === '-' && delStr === '-') {
23
+ // Binary file
24
+ stats.push({
25
+ path,
26
+ additions: 0,
27
+ deletions: 0,
28
+ binary: true,
29
+ });
30
+ }
31
+ else {
32
+ stats.push({
33
+ path,
34
+ additions: parseInt(addStr, 10) || 0,
35
+ deletions: parseInt(delStr, 10) || 0,
36
+ });
37
+ }
38
+ }
39
+ }
40
+ return stats;
41
+ }
42
+ //# sourceMappingURL=diffstat-parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diffstat-parser.js","sourceRoot":"","sources":["../../src/parsers/diffstat-parser.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,SAAiB;IAC7C,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,EAAE,CAAC;QACtB,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,KAAK,GAAe,EAAE,CAAC;IAC7B,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAEpD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,oEAAoE;QACpE,IAAI,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC;YACpE,SAAS;QACX,CAAC;QAED,yDAAyD;QACzD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC/B,IAAI,KAAK,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;YACtB,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC,GAAG,KAAK,CAAC;YAC7C,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,yBAAyB;YAE5D,IAAI,MAAM,KAAK,GAAG,IAAI,MAAM,KAAK,GAAG,EAAE,CAAC;gBACrC,cAAc;gBACd,KAAK,CAAC,IAAI,CAAC;oBACT,IAAI;oBACJ,SAAS,EAAE,CAAC;oBACZ,SAAS,EAAE,CAAC;oBACZ,MAAM,EAAE,IAAI;iBACb,CAAC,CAAC;YACL,CAAC;iBAAM,CAAC;gBACN,KAAK,CAAC,IAAI,CAAC;oBACT,IAAI;oBACJ,SAAS,EAAE,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC;oBACpC,SAAS,EAAE,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC;iBACrC,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { LogEntry } from '@gitguard/schema';
2
+ /**
3
+ * Parse git log --oneline --decorate output.
4
+ * Format: <hash> (<decorations>) <message>
5
+ * Or: <hash> <message> (if no decorations)
6
+ */
7
+ export declare function parseLog(logOutput: string): LogEntry[];
8
+ //# sourceMappingURL=log-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log-parser.d.ts","sourceRoot":"","sources":["../../src/parsers/log-parser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEjD;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,QAAQ,EAAE,CAYtD"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Parse git log --oneline --decorate output.
3
+ * Format: <hash> (<decorations>) <message>
4
+ * Or: <hash> <message> (if no decorations)
5
+ */
6
+ export function parseLog(logOutput) {
7
+ const lines = logOutput.split('\n').filter(line => line.length > 0);
8
+ const entries = [];
9
+ for (const line of lines) {
10
+ const entry = parseLogLine(line);
11
+ if (entry) {
12
+ entries.push(entry);
13
+ }
14
+ }
15
+ return entries;
16
+ }
17
+ function parseLogLine(line) {
18
+ // Match: <hash> (optional decorations) <message>
19
+ const match = line.match(/^([a-f0-9]+)\s+(?:\(([^)]+)\)\s+)?(.*)$/);
20
+ if (!match) {
21
+ return null;
22
+ }
23
+ const [, hash, decorations, message] = match;
24
+ const refs = [];
25
+ if (decorations) {
26
+ // Parse decorations like "HEAD -> main, origin/main, tag: v1.0"
27
+ const parts = decorations.split(',').map(p => p.trim());
28
+ for (const part of parts) {
29
+ // Handle "HEAD -> branch"
30
+ if (part.includes('->')) {
31
+ const [head, branch] = part.split('->').map(s => s.trim());
32
+ refs.push(head);
33
+ refs.push(branch);
34
+ }
35
+ else {
36
+ refs.push(part);
37
+ }
38
+ }
39
+ }
40
+ return {
41
+ hash,
42
+ refs,
43
+ message: message.trim(),
44
+ };
45
+ }
46
+ //# sourceMappingURL=log-parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log-parser.js","sourceRoot":"","sources":["../../src/parsers/log-parser.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,MAAM,UAAU,QAAQ,CAAC,SAAiB;IACxC,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACpE,MAAM,OAAO,GAAe,EAAE,CAAC;IAE/B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,KAAK,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;QACjC,IAAI,KAAK,EAAE,CAAC;YACV,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,YAAY,CAAC,IAAY;IAChC,iDAAiD;IACjD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,yCAAyC,CAAC,CAAC;IAEpE,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,CAAC,GAAG,KAAK,CAAC;IAE7C,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,IAAI,WAAW,EAAE,CAAC;QAChB,gEAAgE;QAChE,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QACxD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,0BAA0B;YAC1B,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;gBACxB,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;gBAC3D,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAChB,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACpB,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAClB,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO;QACL,IAAI;QACJ,IAAI;QACJ,OAAO,EAAE,OAAO,CAAC,IAAI,EAAE;KACxB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { ReflogEntry } from '@gitguard/schema';
2
+ /**
3
+ * Parse git reflog output.
4
+ * Format: <hash> <selector> <action>: <message>
5
+ * Example: abc1234 HEAD@{0} commit: Fix bug
6
+ */
7
+ export declare function parseReflog(reflogOutput: string): ReflogEntry[];
8
+ //# sourceMappingURL=reflog-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reflog-parser.d.ts","sourceRoot":"","sources":["../../src/parsers/reflog-parser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEpD;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,YAAY,EAAE,MAAM,GAAG,WAAW,EAAE,CAY/D"}
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Parse git reflog output.
3
+ * Format: <hash> <selector> <action>: <message>
4
+ * Example: abc1234 HEAD@{0} commit: Fix bug
5
+ */
6
+ export function parseReflog(reflogOutput) {
7
+ const lines = reflogOutput.split('\n').filter(line => line.length > 0);
8
+ const entries = [];
9
+ for (const line of lines) {
10
+ const entry = parseReflogLine(line);
11
+ if (entry) {
12
+ entries.push(entry);
13
+ }
14
+ }
15
+ return entries;
16
+ }
17
+ function parseReflogLine(line) {
18
+ // Match: <hash> <selector> <action>: <message>
19
+ // Example: 57c3040 HEAD@{0}: commit: Add validation to functions
20
+ // Note: action can contain sub-parts like "commit (initial)"
21
+ const match = line.match(/^([a-f0-9]+)\s+(HEAD@\{\d+\}):\s+([^:]+):\s*(.*)$/);
22
+ if (match) {
23
+ const [, hash, selector, action, message] = match;
24
+ return {
25
+ hash,
26
+ selector,
27
+ action: action.trim(),
28
+ message: message.trim(),
29
+ };
30
+ }
31
+ // Try format with parentheses in action: "commit (initial): message"
32
+ const parenMatch = line.match(/^([a-f0-9]+)\s+(HEAD@\{\d+\}):\s+([^:]+\([^)]+\)):\s*(.*)$/);
33
+ if (parenMatch) {
34
+ const [, hash, selector, action, message] = parenMatch;
35
+ return {
36
+ hash,
37
+ selector,
38
+ action: action.trim(),
39
+ message: message.trim(),
40
+ };
41
+ }
42
+ // Fallback: simpler format
43
+ const simpleMatch = line.match(/^([a-f0-9]+)\s+(HEAD@\{\d+\}):\s+(.*)$/);
44
+ if (simpleMatch) {
45
+ const [, hash, selector, rest] = simpleMatch;
46
+ // Try to split on first colon for action
47
+ const colonIdx = rest.indexOf(':');
48
+ if (colonIdx > 0) {
49
+ return {
50
+ hash,
51
+ selector,
52
+ action: rest.slice(0, colonIdx).trim(),
53
+ message: rest.slice(colonIdx + 1).trim(),
54
+ };
55
+ }
56
+ return {
57
+ hash,
58
+ selector,
59
+ action: 'unknown',
60
+ message: rest.trim(),
61
+ };
62
+ }
63
+ return null;
64
+ }
65
+ //# sourceMappingURL=reflog-parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reflog-parser.js","sourceRoot":"","sources":["../../src/parsers/reflog-parser.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,MAAM,UAAU,WAAW,CAAC,YAAoB;IAC9C,MAAM,KAAK,GAAG,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACvE,MAAM,OAAO,GAAkB,EAAE,CAAC;IAElC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,KAAK,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;QACpC,IAAI,KAAK,EAAE,CAAC;YACV,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,eAAe,CAAC,IAAY;IACnC,+CAA+C;IAC/C,iEAAiE;IACjE,6DAA6D;IAC7D,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,mDAAmD,CAAC,CAAC;IAE9E,IAAI,KAAK,EAAE,CAAC;QACV,MAAM,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,GAAG,KAAK,CAAC;QAClD,OAAO;YACL,IAAI;YACJ,QAAQ;YACR,MAAM,EAAE,MAAM,CAAC,IAAI,EAAE;YACrB,OAAO,EAAE,OAAO,CAAC,IAAI,EAAE;SACxB,CAAC;IACJ,CAAC;IAED,qEAAqE;IACrE,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,4DAA4D,CAAC,CAAC;IAC5F,IAAI,UAAU,EAAE,CAAC;QACf,MAAM,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,GAAG,UAAU,CAAC;QACvD,OAAO;YACL,IAAI;YACJ,QAAQ;YACR,MAAM,EAAE,MAAM,CAAC,IAAI,EAAE;YACrB,OAAO,EAAE,OAAO,CAAC,IAAI,EAAE;SACxB,CAAC;IACJ,CAAC;IAED,2BAA2B;IAC3B,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,wCAAwC,CAAC,CAAC;IACzE,IAAI,WAAW,EAAE,CAAC;QAChB,MAAM,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,CAAC,GAAG,WAAW,CAAC;QAC7C,yCAAyC;QACzC,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACnC,IAAI,QAAQ,GAAG,CAAC,EAAE,CAAC;YACjB,OAAO;gBACL,IAAI;gBACJ,QAAQ;gBACR,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,IAAI,EAAE;gBACtC,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE;aACzC,CAAC;QACJ,CAAC;QACD,OAAO;YACL,IAAI;YACJ,QAAQ;YACR,MAAM,EAAE,SAAS;YACjB,OAAO,EAAE,IAAI,CAAC,IAAI,EAAE;SACrB,CAAC;IACJ,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Parse git status --porcelain=v2 --branch output.
3
+ *
4
+ * Format reference:
5
+ * - Branch headers: # branch.oid, # branch.head, # branch.upstream, # branch.ab
6
+ * - Ordinary changed entries: 1 <XY> <sub> <mH> <mI> <mW> <hH> <hI> <path>
7
+ * - Renamed/copied entries: 2 <XY> <sub> <mH> <mI> <mW> <hH> <hI> <X><score> <path><tab><origPath>
8
+ * - Unmerged entries: u <XY> <sub> <m1> <m2> <m3> <mW> <h1> <h2> <h3> <path>
9
+ * - Untracked entries: ? <path>
10
+ * - Ignored entries: ! <path>
11
+ */
12
+ export interface StatusInfo {
13
+ branch: {
14
+ oid: string;
15
+ head: string;
16
+ upstream?: string;
17
+ ahead?: number;
18
+ behind?: number;
19
+ };
20
+ isDetachedHead: boolean;
21
+ unmergedPaths: string[];
22
+ stagedFiles: string[];
23
+ modifiedFiles: string[];
24
+ untrackedFiles: string[];
25
+ }
26
+ export declare function parseStatus(status: string): StatusInfo;
27
+ //# sourceMappingURL=status-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status-parser.d.ts","sourceRoot":"","sources":["../../src/parsers/status-parser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE;QACN,GAAG,EAAE,MAAM,CAAC;QACZ,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC;IACF,cAAc,EAAE,OAAO,CAAC;IACxB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,cAAc,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,CAgEtD"}
@@ -0,0 +1,110 @@
1
+ /**
2
+ * Parse git status --porcelain=v2 --branch output.
3
+ *
4
+ * Format reference:
5
+ * - Branch headers: # branch.oid, # branch.head, # branch.upstream, # branch.ab
6
+ * - Ordinary changed entries: 1 <XY> <sub> <mH> <mI> <mW> <hH> <hI> <path>
7
+ * - Renamed/copied entries: 2 <XY> <sub> <mH> <mI> <mW> <hH> <hI> <X><score> <path><tab><origPath>
8
+ * - Unmerged entries: u <XY> <sub> <m1> <m2> <m3> <mW> <h1> <h2> <h3> <path>
9
+ * - Untracked entries: ? <path>
10
+ * - Ignored entries: ! <path>
11
+ */
12
+ export function parseStatus(status) {
13
+ const lines = status.split('\n').filter(line => line.length > 0);
14
+ const result = {
15
+ branch: {
16
+ oid: '',
17
+ head: '',
18
+ },
19
+ isDetachedHead: false,
20
+ unmergedPaths: [],
21
+ stagedFiles: [],
22
+ modifiedFiles: [],
23
+ untrackedFiles: [],
24
+ };
25
+ for (const line of lines) {
26
+ // Branch headers
27
+ if (line.startsWith('# branch.oid ')) {
28
+ result.branch.oid = line.slice('# branch.oid '.length);
29
+ }
30
+ else if (line.startsWith('# branch.head ')) {
31
+ result.branch.head = line.slice('# branch.head '.length);
32
+ result.isDetachedHead = result.branch.head === '(detached)';
33
+ }
34
+ else if (line.startsWith('# branch.upstream ')) {
35
+ result.branch.upstream = line.slice('# branch.upstream '.length);
36
+ }
37
+ else if (line.startsWith('# branch.ab ')) {
38
+ const match = line.match(/# branch\.ab \+(\d+) -(\d+)/);
39
+ if (match) {
40
+ result.branch.ahead = parseInt(match[1], 10);
41
+ result.branch.behind = parseInt(match[2], 10);
42
+ }
43
+ }
44
+ // Unmerged entries (conflicts)
45
+ else if (line.startsWith('u ')) {
46
+ const path = parseUnmergedLine(line);
47
+ if (path) {
48
+ result.unmergedPaths.push(path);
49
+ }
50
+ }
51
+ // Ordinary changed entries
52
+ else if (line.startsWith('1 ')) {
53
+ const parsed = parseOrdinaryLine(line);
54
+ if (parsed) {
55
+ if (parsed.staged) {
56
+ result.stagedFiles.push(parsed.path);
57
+ }
58
+ if (parsed.modified) {
59
+ result.modifiedFiles.push(parsed.path);
60
+ }
61
+ }
62
+ }
63
+ // Renamed/copied entries
64
+ else if (line.startsWith('2 ')) {
65
+ const parsed = parseRenamedLine(line);
66
+ if (parsed) {
67
+ result.stagedFiles.push(parsed.path);
68
+ }
69
+ }
70
+ // Untracked entries
71
+ else if (line.startsWith('? ')) {
72
+ result.untrackedFiles.push(line.slice(2));
73
+ }
74
+ }
75
+ return result;
76
+ }
77
+ function parseUnmergedLine(line) {
78
+ // u <XY> <sub> <m1> <m2> <m3> <mW> <h1> <h2> <h3> <path>
79
+ const parts = line.split(' ');
80
+ if (parts.length >= 11) {
81
+ // Path is everything after the 10th space-separated element
82
+ return parts.slice(10).join(' ');
83
+ }
84
+ return null;
85
+ }
86
+ function parseOrdinaryLine(line) {
87
+ // 1 <XY> <sub> <mH> <mI> <mW> <hH> <hI> <path>
88
+ const parts = line.split(' ');
89
+ if (parts.length >= 9) {
90
+ const xy = parts[1];
91
+ const path = parts.slice(8).join(' ');
92
+ // X is index status (staged), Y is worktree status (modified)
93
+ const staged = xy[0] !== '.';
94
+ const modified = xy[1] !== '.';
95
+ return { path, staged, modified };
96
+ }
97
+ return null;
98
+ }
99
+ function parseRenamedLine(line) {
100
+ // 2 <XY> <sub> <mH> <mI> <mW> <hH> <hI> <X><score> <path><tab><origPath>
101
+ const tabIndex = line.indexOf('\t');
102
+ if (tabIndex !== -1) {
103
+ const beforeTab = line.slice(0, tabIndex).split(' ');
104
+ const origPath = line.slice(tabIndex + 1);
105
+ const path = beforeTab[beforeTab.length - 1];
106
+ return { path, origPath };
107
+ }
108
+ return null;
109
+ }
110
+ //# sourceMappingURL=status-parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status-parser.js","sourceRoot":"","sources":["../../src/parsers/status-parser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ export interface ExecResult {
2
+ stdout: string;
3
+ success: boolean;
4
+ }
5
+ /**
6
+ * Execute a git command and return the output.
7
+ * Normalizes line endings to LF for cross-platform compatibility.
8
+ */
9
+ export declare function execGit(args: string[], cwd?: string): ExecResult;
10
+ /**
11
+ * Check if a path exists using git rev-parse --git-path
12
+ */
13
+ export declare function gitPathExists(gitDir: string, subpath: string): Promise<boolean>;
14
+ //# sourceMappingURL=exec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exec.d.ts","sourceRoot":"","sources":["../../src/utils/exec.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;;GAGG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,UAAU,CA0BhE;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAmBrF"}
@@ -0,0 +1,54 @@
1
+ import { execSync } from 'node:child_process';
2
+ /**
3
+ * Execute a git command and return the output.
4
+ * Normalizes line endings to LF for cross-platform compatibility.
5
+ */
6
+ export function execGit(args, cwd) {
7
+ try {
8
+ const result = execSync(`git ${args.join(' ')}`, {
9
+ cwd,
10
+ encoding: 'utf-8',
11
+ stdio: ['pipe', 'pipe', 'pipe'],
12
+ maxBuffer: 10 * 1024 * 1024, // 10MB
13
+ });
14
+ // Normalize CRLF to LF
15
+ const normalized = result.replace(/\r\n/g, '\n');
16
+ return {
17
+ stdout: normalized,
18
+ success: true,
19
+ };
20
+ }
21
+ catch (error) {
22
+ if (error instanceof Error && 'stdout' in error) {
23
+ const stdout = error.stdout || '';
24
+ return {
25
+ stdout: stdout.replace(/\r\n/g, '\n'),
26
+ success: false,
27
+ };
28
+ }
29
+ throw error;
30
+ }
31
+ }
32
+ /**
33
+ * Check if a path exists using git rev-parse --git-path
34
+ */
35
+ export async function gitPathExists(gitDir, subpath) {
36
+ try {
37
+ const result = execGit(['rev-parse', '--git-path', subpath]);
38
+ if (!result.success)
39
+ return false;
40
+ const fullPath = result.stdout.trim();
41
+ // Use git to check if the path exists by trying to list it
42
+ const { existsSync } = await import('node:fs');
43
+ const { resolve } = await import('node:path');
44
+ // If the path is relative, resolve it against gitDir's parent
45
+ const resolvedPath = fullPath.startsWith('/') || /^[A-Za-z]:/.test(fullPath)
46
+ ? fullPath
47
+ : resolve(process.cwd(), fullPath);
48
+ return existsSync(resolvedPath);
49
+ }
50
+ catch {
51
+ return false;
52
+ }
53
+ }
54
+ //# sourceMappingURL=exec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exec.js","sourceRoot":"","sources":["../../src/utils/exec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAO9C;;;GAGG;AACH,MAAM,UAAU,OAAO,CAAC,IAAc,EAAE,GAAY;IAClD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE;YAC/C,GAAG;YACH,QAAQ,EAAE,OAAO;YACjB,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;YAC/B,SAAS,EAAE,EAAE,GAAG,IAAI,GAAG,IAAI,EAAE,OAAO;SACrC,CAAC,CAAC;QAEH,uBAAuB;QACvB,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QAEjD,OAAO;YACL,MAAM,EAAE,UAAU;YAClB,OAAO,EAAE,IAAI;SACd,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,KAAK,IAAI,QAAQ,IAAI,KAAK,EAAE,CAAC;YAChD,MAAM,MAAM,GAAI,KAA4B,CAAC,MAAM,IAAI,EAAE,CAAC;YAC1D,OAAO;gBACL,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC;gBACrC,OAAO,EAAE,KAAK;aACf,CAAC;QACJ,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,MAAc,EAAE,OAAe;IACjE,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,WAAW,EAAE,YAAY,EAAE,OAAO,CAAC,CAAC,CAAC;QAC7D,IAAI,CAAC,MAAM,CAAC,OAAO;YAAE,OAAO,KAAK,CAAC;QAElC,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QACtC,2DAA2D;QAC3D,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,CAAC;QAC/C,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,CAAC;QAE9C,8DAA8D;QAC9D,MAAM,YAAY,GAAG,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC;YAC1E,CAAC,CAAC,QAAQ;YACV,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,QAAQ,CAAC,CAAC;QAErC,OAAO,UAAU,CAAC,YAAY,CAAC,CAAC;IAClC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}