@generacy-ai/agency-plugin-git 0.0.0-preview-20260302182740
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/LICENSE +191 -0
- package/dist/config.d.ts +25 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +22 -0
- package/dist/config.js.map +1 -0
- package/dist/errors/auth-error.d.ts +23 -0
- package/dist/errors/auth-error.d.ts.map +1 -0
- package/dist/errors/auth-error.js +33 -0
- package/dist/errors/auth-error.js.map +1 -0
- package/dist/errors/conflict-error.d.ts +31 -0
- package/dist/errors/conflict-error.d.ts.map +1 -0
- package/dist/errors/conflict-error.js +49 -0
- package/dist/errors/conflict-error.js.map +1 -0
- package/dist/errors/detached-head-error.d.ts +26 -0
- package/dist/errors/detached-head-error.d.ts.map +1 -0
- package/dist/errors/detached-head-error.js +32 -0
- package/dist/errors/detached-head-error.js.map +1 -0
- package/dist/errors/git-error.d.ts +25 -0
- package/dist/errors/git-error.d.ts.map +1 -0
- package/dist/errors/git-error.js +33 -0
- package/dist/errors/git-error.js.map +1 -0
- package/dist/errors/index.d.ts +9 -0
- package/dist/errors/index.d.ts.map +1 -0
- package/dist/errors/index.js +9 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/errors/network-error.d.ts +30 -0
- package/dist/errors/network-error.d.ts.map +1 -0
- package/dist/errors/network-error.js +67 -0
- package/dist/errors/network-error.js.map +1 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +29 -0
- package/dist/index.js.map +1 -0
- package/dist/plugin.d.ts +28 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +79 -0
- package/dist/plugin.js.map +1 -0
- package/dist/tools/blame.d.ts +9 -0
- package/dist/tools/blame.d.ts.map +1 -0
- package/dist/tools/blame.js +67 -0
- package/dist/tools/blame.js.map +1 -0
- package/dist/tools/branch.d.ts +9 -0
- package/dist/tools/branch.d.ts.map +1 -0
- package/dist/tools/branch.js +141 -0
- package/dist/tools/branch.js.map +1 -0
- package/dist/tools/checkout.d.ts +9 -0
- package/dist/tools/checkout.d.ts.map +1 -0
- package/dist/tools/checkout.js +94 -0
- package/dist/tools/checkout.js.map +1 -0
- package/dist/tools/commit.d.ts +9 -0
- package/dist/tools/commit.d.ts.map +1 -0
- package/dist/tools/commit.js +90 -0
- package/dist/tools/commit.js.map +1 -0
- package/dist/tools/diff.d.ts +9 -0
- package/dist/tools/diff.d.ts.map +1 -0
- package/dist/tools/diff.js +97 -0
- package/dist/tools/diff.js.map +1 -0
- package/dist/tools/index.d.ts +26 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +55 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/log.d.ts +9 -0
- package/dist/tools/log.d.ts.map +1 -0
- package/dist/tools/log.js +91 -0
- package/dist/tools/log.js.map +1 -0
- package/dist/tools/merge.d.ts +9 -0
- package/dist/tools/merge.d.ts.map +1 -0
- package/dist/tools/merge.js +119 -0
- package/dist/tools/merge.js.map +1 -0
- package/dist/tools/pull.d.ts +9 -0
- package/dist/tools/pull.d.ts.map +1 -0
- package/dist/tools/pull.js +113 -0
- package/dist/tools/pull.js.map +1 -0
- package/dist/tools/push.d.ts +9 -0
- package/dist/tools/push.d.ts.map +1 -0
- package/dist/tools/push.js +116 -0
- package/dist/tools/push.js.map +1 -0
- package/dist/tools/rebase.d.ts +9 -0
- package/dist/tools/rebase.d.ts.map +1 -0
- package/dist/tools/rebase.js +147 -0
- package/dist/tools/rebase.js.map +1 -0
- package/dist/tools/stash.d.ts +9 -0
- package/dist/tools/stash.d.ts.map +1 -0
- package/dist/tools/stash.js +151 -0
- package/dist/tools/stash.js.map +1 -0
- package/dist/tools/status.d.ts +9 -0
- package/dist/tools/status.d.ts.map +1 -0
- package/dist/tools/status.js +76 -0
- package/dist/tools/status.js.map +1 -0
- package/dist/types.d.ts +297 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +7 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/conflict-parser.d.ts +38 -0
- package/dist/utils/conflict-parser.d.ts.map +1 -0
- package/dist/utils/conflict-parser.js +158 -0
- package/dist/utils/conflict-parser.js.map +1 -0
- package/dist/utils/exec-git.d.ts +45 -0
- package/dist/utils/exec-git.d.ts.map +1 -0
- package/dist/utils/exec-git.js +180 -0
- package/dist/utils/exec-git.js.map +1 -0
- package/dist/utils/parse-blame.d.ts +29 -0
- package/dist/utils/parse-blame.d.ts.map +1 -0
- package/dist/utils/parse-blame.js +97 -0
- package/dist/utils/parse-blame.js.map +1 -0
- package/dist/utils/parse-diff.d.ts +25 -0
- package/dist/utils/parse-diff.d.ts.map +1 -0
- package/dist/utils/parse-diff.js +105 -0
- package/dist/utils/parse-diff.js.map +1 -0
- package/dist/utils/parse-log.d.ts +33 -0
- package/dist/utils/parse-log.d.ts.map +1 -0
- package/dist/utils/parse-log.js +90 -0
- package/dist/utils/parse-log.js.map +1 -0
- package/dist/utils/parse-status.d.ts +22 -0
- package/dist/utils/parse-status.d.ts.map +1 -0
- package/dist/utils/parse-status.js +173 -0
- package/dist/utils/parse-status.js.map +1 -0
- package/package.json +82 -0
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Git command execution wrapper
|
|
3
|
+
*
|
|
4
|
+
* Provides:
|
|
5
|
+
* - Spawn-based execution with timeout
|
|
6
|
+
* - Error classification
|
|
7
|
+
* - Raw output capture for parsing
|
|
8
|
+
*/
|
|
9
|
+
import { spawn } from 'node:child_process';
|
|
10
|
+
import { GitError, AuthError, NetworkError, ConflictError, DetachedHeadError, isAuthError, isNetworkError, isConflictError, isDetachedHeadError, extractRemote, } from '../errors/index.js';
|
|
11
|
+
const DEFAULT_TIMEOUT = 30000; // 30 seconds
|
|
12
|
+
/**
|
|
13
|
+
* Execute a git command and return the result
|
|
14
|
+
*
|
|
15
|
+
* @param args - Git command arguments (e.g., ['status', '--porcelain'])
|
|
16
|
+
* @param options - Execution options
|
|
17
|
+
* @returns ExecGitResult with exitCode, stdout, stderr
|
|
18
|
+
*/
|
|
19
|
+
export async function execGit(args, options = {}) {
|
|
20
|
+
const { cwd = process.cwd(), timeout = DEFAULT_TIMEOUT, env = {}, } = options;
|
|
21
|
+
const command = `git ${args.join(' ')}`;
|
|
22
|
+
return new Promise((resolve, reject) => {
|
|
23
|
+
const gitProcess = spawn('git', args, {
|
|
24
|
+
cwd,
|
|
25
|
+
env: { ...process.env, ...env },
|
|
26
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
27
|
+
});
|
|
28
|
+
let stdout = '';
|
|
29
|
+
let stderr = '';
|
|
30
|
+
gitProcess.stdout.on('data', (data) => {
|
|
31
|
+
stdout += data.toString();
|
|
32
|
+
});
|
|
33
|
+
gitProcess.stderr.on('data', (data) => {
|
|
34
|
+
stderr += data.toString();
|
|
35
|
+
});
|
|
36
|
+
const timeoutId = setTimeout(() => {
|
|
37
|
+
gitProcess.kill('SIGTERM');
|
|
38
|
+
reject(new GitError(`Git command timed out after ${timeout}ms`, {
|
|
39
|
+
command,
|
|
40
|
+
exitCode: -1,
|
|
41
|
+
stderr: 'Command timed out',
|
|
42
|
+
cwd,
|
|
43
|
+
}));
|
|
44
|
+
}, timeout);
|
|
45
|
+
gitProcess.on('error', (error) => {
|
|
46
|
+
clearTimeout(timeoutId);
|
|
47
|
+
reject(new GitError(`Failed to spawn git: ${error.message}`, {
|
|
48
|
+
command,
|
|
49
|
+
exitCode: -1,
|
|
50
|
+
stderr: error.message,
|
|
51
|
+
cwd,
|
|
52
|
+
}));
|
|
53
|
+
});
|
|
54
|
+
gitProcess.on('close', (code) => {
|
|
55
|
+
clearTimeout(timeoutId);
|
|
56
|
+
resolve({
|
|
57
|
+
exitCode: code ?? 0,
|
|
58
|
+
stdout: stdout.trim(),
|
|
59
|
+
stderr: stderr.trim(),
|
|
60
|
+
command,
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Execute a git command and throw a classified error on failure
|
|
67
|
+
*
|
|
68
|
+
* @param args - Git command arguments
|
|
69
|
+
* @param options - Execution options
|
|
70
|
+
* @returns ExecGitResult on success
|
|
71
|
+
* @throws GitError (or subclass) on failure
|
|
72
|
+
*/
|
|
73
|
+
export async function execGitOrThrow(args, options = {}) {
|
|
74
|
+
const result = await execGit(args, options);
|
|
75
|
+
if (result.exitCode !== 0) {
|
|
76
|
+
throw classifyError(result, options.cwd ?? process.cwd());
|
|
77
|
+
}
|
|
78
|
+
return result;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Classify a git error based on exit code and stderr
|
|
82
|
+
*/
|
|
83
|
+
export function classifyError(result, cwd, conflicts = []) {
|
|
84
|
+
const { exitCode, stderr, stdout, command } = result;
|
|
85
|
+
// Check error patterns in order of specificity
|
|
86
|
+
// Auth errors (exit code 128 typically)
|
|
87
|
+
if (isAuthError(stderr)) {
|
|
88
|
+
return new AuthError('Authentication failed', {
|
|
89
|
+
command,
|
|
90
|
+
exitCode,
|
|
91
|
+
stderr,
|
|
92
|
+
cwd,
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
// Network errors
|
|
96
|
+
if (isNetworkError(stderr)) {
|
|
97
|
+
return new NetworkError('Network error', {
|
|
98
|
+
command,
|
|
99
|
+
exitCode,
|
|
100
|
+
stderr,
|
|
101
|
+
cwd,
|
|
102
|
+
remote: extractRemote(stderr),
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
// Conflict errors (exit code 1 with conflict message)
|
|
106
|
+
if (isConflictError(stderr, stdout)) {
|
|
107
|
+
return new ConflictError('Merge conflict', {
|
|
108
|
+
command,
|
|
109
|
+
exitCode,
|
|
110
|
+
stderr,
|
|
111
|
+
cwd,
|
|
112
|
+
conflicts,
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
// Detached HEAD errors
|
|
116
|
+
if (isDetachedHeadError(stderr)) {
|
|
117
|
+
return new DetachedHeadError('HEAD is detached', {
|
|
118
|
+
command,
|
|
119
|
+
exitCode,
|
|
120
|
+
stderr,
|
|
121
|
+
cwd,
|
|
122
|
+
headCommit: extractHeadCommit(stderr) ?? 'unknown',
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
// Generic git error
|
|
126
|
+
return new GitError(stderr || `Command exited with code ${exitCode}`, {
|
|
127
|
+
command,
|
|
128
|
+
exitCode,
|
|
129
|
+
stderr,
|
|
130
|
+
cwd,
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Extract HEAD commit from error message
|
|
135
|
+
*/
|
|
136
|
+
function extractHeadCommit(stderr) {
|
|
137
|
+
const match = stderr.match(/head detached (?:at|from) ([a-f0-9]+)/i);
|
|
138
|
+
return match?.[1];
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Check if git is available
|
|
142
|
+
*/
|
|
143
|
+
export async function isGitAvailable() {
|
|
144
|
+
try {
|
|
145
|
+
const result = await execGit(['--version']);
|
|
146
|
+
return result.exitCode === 0;
|
|
147
|
+
}
|
|
148
|
+
catch {
|
|
149
|
+
return false;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Get the current git version
|
|
154
|
+
*/
|
|
155
|
+
export async function getGitVersion() {
|
|
156
|
+
try {
|
|
157
|
+
const result = await execGit(['--version']);
|
|
158
|
+
if (result.exitCode === 0) {
|
|
159
|
+
const match = result.stdout.match(/git version (\d+\.\d+\.\d+)/);
|
|
160
|
+
return match?.[1] ?? null;
|
|
161
|
+
}
|
|
162
|
+
return null;
|
|
163
|
+
}
|
|
164
|
+
catch {
|
|
165
|
+
return null;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Check if the current directory is a git repository
|
|
170
|
+
*/
|
|
171
|
+
export async function isGitRepository(cwd) {
|
|
172
|
+
try {
|
|
173
|
+
const result = await execGit(['rev-parse', '--git-dir'], { cwd });
|
|
174
|
+
return result.exitCode === 0;
|
|
175
|
+
}
|
|
176
|
+
catch {
|
|
177
|
+
return false;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
//# sourceMappingURL=exec-git.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exec-git.js","sourceRoot":"","sources":["../../src/utils/exec-git.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parse git blame --porcelain output
|
|
3
|
+
*/
|
|
4
|
+
import type { BlameResult } from '../types.js';
|
|
5
|
+
/**
|
|
6
|
+
* Parse git blame --porcelain output into BlameResult
|
|
7
|
+
*
|
|
8
|
+
* Porcelain format for each line:
|
|
9
|
+
* <sha1> <orig-line> <final-line> [<num-lines>]
|
|
10
|
+
* author <author-name>
|
|
11
|
+
* author-mail <author-email>
|
|
12
|
+
* author-time <timestamp>
|
|
13
|
+
* author-tz <timezone>
|
|
14
|
+
* committer <committer-name>
|
|
15
|
+
* committer-mail <committer-email>
|
|
16
|
+
* committer-time <timestamp>
|
|
17
|
+
* committer-tz <timezone>
|
|
18
|
+
* summary <commit-summary>
|
|
19
|
+
* [previous <sha1> <filename>]
|
|
20
|
+
* [boundary]
|
|
21
|
+
* filename <filename>
|
|
22
|
+
* <tab><content>
|
|
23
|
+
*/
|
|
24
|
+
export declare function parseBlame(output: string): BlameResult;
|
|
25
|
+
/**
|
|
26
|
+
* Format blame result for display
|
|
27
|
+
*/
|
|
28
|
+
export declare function formatBlame(result: BlameResult, showContent?: boolean): string;
|
|
29
|
+
//# sourceMappingURL=parse-blame.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse-blame.d.ts","sourceRoot":"","sources":["../../src/utils/parse-blame.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,WAAW,CAkEtD;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,WAAW,EAAE,WAAW,GAAE,OAAc,GAAG,MAAM,CAapF"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parse git blame --porcelain output
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Parse git blame --porcelain output into BlameResult
|
|
6
|
+
*
|
|
7
|
+
* Porcelain format for each line:
|
|
8
|
+
* <sha1> <orig-line> <final-line> [<num-lines>]
|
|
9
|
+
* author <author-name>
|
|
10
|
+
* author-mail <author-email>
|
|
11
|
+
* author-time <timestamp>
|
|
12
|
+
* author-tz <timezone>
|
|
13
|
+
* committer <committer-name>
|
|
14
|
+
* committer-mail <committer-email>
|
|
15
|
+
* committer-time <timestamp>
|
|
16
|
+
* committer-tz <timezone>
|
|
17
|
+
* summary <commit-summary>
|
|
18
|
+
* [previous <sha1> <filename>]
|
|
19
|
+
* [boundary]
|
|
20
|
+
* filename <filename>
|
|
21
|
+
* <tab><content>
|
|
22
|
+
*/
|
|
23
|
+
export function parseBlame(output) {
|
|
24
|
+
const lines = output.split('\n');
|
|
25
|
+
const result = { lines: [] };
|
|
26
|
+
let currentHash = '';
|
|
27
|
+
let currentAuthor = '';
|
|
28
|
+
let currentDate = '';
|
|
29
|
+
let currentLineNumber = 0;
|
|
30
|
+
const hashInfoCache = {};
|
|
31
|
+
for (let i = 0; i < lines.length; i++) {
|
|
32
|
+
const line = lines[i];
|
|
33
|
+
if (!line)
|
|
34
|
+
continue;
|
|
35
|
+
// SHA line: <sha1> <orig-line> <final-line> [<num-lines>]
|
|
36
|
+
const shaMatch = line.match(/^([a-f0-9]{40}) (\d+) (\d+)/);
|
|
37
|
+
if (shaMatch) {
|
|
38
|
+
currentHash = shaMatch[1] ?? '';
|
|
39
|
+
currentLineNumber = parseInt(shaMatch[3] ?? '0', 10);
|
|
40
|
+
// Check cache for hash info
|
|
41
|
+
const cached = hashInfoCache[currentHash];
|
|
42
|
+
if (cached) {
|
|
43
|
+
currentAuthor = cached.author;
|
|
44
|
+
currentDate = cached.date;
|
|
45
|
+
}
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
// Author line
|
|
49
|
+
if (line.startsWith('author ')) {
|
|
50
|
+
currentAuthor = line.slice(7);
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
// Author time (Unix timestamp)
|
|
54
|
+
if (line.startsWith('author-time ')) {
|
|
55
|
+
const timestamp = parseInt(line.slice(12), 10);
|
|
56
|
+
currentDate = new Date(timestamp * 1000).toISOString();
|
|
57
|
+
// Cache the hash info
|
|
58
|
+
if (currentHash) {
|
|
59
|
+
hashInfoCache[currentHash] = {
|
|
60
|
+
author: currentAuthor,
|
|
61
|
+
date: currentDate,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
// Content line (starts with tab)
|
|
67
|
+
if (line.startsWith('\t')) {
|
|
68
|
+
const content = line.slice(1);
|
|
69
|
+
result.lines.push({
|
|
70
|
+
lineNumber: currentLineNumber,
|
|
71
|
+
hash: currentHash,
|
|
72
|
+
author: currentAuthor,
|
|
73
|
+
date: currentDate,
|
|
74
|
+
content,
|
|
75
|
+
});
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return result;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Format blame result for display
|
|
83
|
+
*/
|
|
84
|
+
export function formatBlame(result, showContent = true) {
|
|
85
|
+
return result.lines
|
|
86
|
+
.map((line) => {
|
|
87
|
+
const hash = line.hash.slice(0, 7);
|
|
88
|
+
const author = line.author.slice(0, 20).padEnd(20);
|
|
89
|
+
const lineNum = line.lineNumber.toString().padStart(4);
|
|
90
|
+
if (showContent) {
|
|
91
|
+
return `${hash} ${author} ${lineNum}: ${line.content}`;
|
|
92
|
+
}
|
|
93
|
+
return `${hash} ${author} ${lineNum}`;
|
|
94
|
+
})
|
|
95
|
+
.join('\n');
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=parse-blame.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse-blame.js","sourceRoot":"","sources":["../../src/utils/parse-blame.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,UAAU,CAAC,MAAc;IACvC,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACjC,MAAM,MAAM,GAAgB,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;IAE1C,IAAI,WAAW,GAAG,EAAE,CAAC;IACrB,IAAI,aAAa,GAAG,EAAE,CAAC;IACvB,IAAI,WAAW,GAAG,EAAE,CAAC;IACrB,IAAI,iBAAiB,GAAG,CAAC,CAAC;IAC1B,MAAM,aAAa,GAAqD,EAAE,CAAC;IAE3E,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACtB,IAAI,CAAC,IAAI;YAAE,SAAS;QAEpB,0DAA0D;QAC1D,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAC;QAC3D,IAAI,QAAQ,EAAE,CAAC;YACb,WAAW,GAAG,QAAQ,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;YAChC,iBAAiB,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,GAAG,EAAE,EAAE,CAAC,CAAC;YAErD,4BAA4B;YAC5B,MAAM,MAAM,GAAG,aAAa,CAAC,WAAW,CAAC,CAAC;YAC1C,IAAI,MAAM,EAAE,CAAC;gBACX,aAAa,GAAG,MAAM,CAAC,MAAM,CAAC;gBAC9B,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC;YAC5B,CAAC;YACD,SAAS;QACX,CAAC;QAED,cAAc;QACd,IAAI,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YAC/B,aAAa,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YAC9B,SAAS;QACX,CAAC;QAED,+BAA+B;QAC/B,IAAI,IAAI,CAAC,UAAU,CAAC,cAAc,CAAC,EAAE,CAAC;YACpC,MAAM,SAAS,GAAG,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;YAC/C,WAAW,GAAG,IAAI,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;YAEvD,sBAAsB;YACtB,IAAI,WAAW,EAAE,CAAC;gBAChB,aAAa,CAAC,WAAW,CAAC,GAAG;oBAC3B,MAAM,EAAE,aAAa;oBACrB,IAAI,EAAE,WAAW;iBAClB,CAAC;YACJ,CAAC;YACD,SAAS;QACX,CAAC;QAED,iCAAiC;QACjC,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YAC1B,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YAE9B,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC;gBAChB,UAAU,EAAE,iBAAiB;gBAC7B,IAAI,EAAE,WAAW;gBACjB,MAAM,EAAE,aAAa;gBACrB,IAAI,EAAE,WAAW;gBACjB,OAAO;aACR,CAAC,CAAC;YACH,SAAS;QACX,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,MAAmB,EAAE,cAAuB,IAAI;IAC1E,OAAO,MAAM,CAAC,KAAK;SAChB,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QACZ,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACnC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACnD,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;QAEvD,IAAI,WAAW,EAAE,CAAC;YAChB,OAAO,GAAG,IAAI,IAAI,MAAM,IAAI,OAAO,KAAK,IAAI,CAAC,OAAO,EAAE,CAAC;QACzD,CAAC;QACD,OAAO,GAAG,IAAI,IAAI,MAAM,IAAI,OAAO,EAAE,CAAC;IACxC,CAAC,CAAC;SACD,IAAI,CAAC,IAAI,CAAC,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parse git diff output
|
|
3
|
+
*/
|
|
4
|
+
import type { DiffResult } from '../types.js';
|
|
5
|
+
/**
|
|
6
|
+
* Parse git diff --numstat output into DiffResult
|
|
7
|
+
*
|
|
8
|
+
* numstat format: <insertions><tab><deletions><tab><path>
|
|
9
|
+
* Binary files show as: -<tab>-<tab><path>
|
|
10
|
+
*/
|
|
11
|
+
export declare function parseDiffNumstat(output: string): DiffResult;
|
|
12
|
+
/**
|
|
13
|
+
* Parse git diff --stat output into DiffResult
|
|
14
|
+
*
|
|
15
|
+
* stat format:
|
|
16
|
+
* <path> | <count> <bar>
|
|
17
|
+
* ...
|
|
18
|
+
* <n> files changed, <m> insertions(+), <p> deletions(-)
|
|
19
|
+
*/
|
|
20
|
+
export declare function parseDiffStat(output: string): DiffResult;
|
|
21
|
+
/**
|
|
22
|
+
* Create a summary string from DiffResult
|
|
23
|
+
*/
|
|
24
|
+
export declare function formatDiffSummary(result: DiffResult): string;
|
|
25
|
+
//# sourceMappingURL=parse-diff.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse-diff.d.ts","sourceRoot":"","sources":["../../src/utils/parse-diff.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,CAkC3D;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,CAiDxD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAkB5D"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parse git diff output
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Parse git diff --numstat output into DiffResult
|
|
6
|
+
*
|
|
7
|
+
* numstat format: <insertions><tab><deletions><tab><path>
|
|
8
|
+
* Binary files show as: -<tab>-<tab><path>
|
|
9
|
+
*/
|
|
10
|
+
export function parseDiffNumstat(output) {
|
|
11
|
+
const lines = output.split('\n').filter(Boolean);
|
|
12
|
+
const result = {
|
|
13
|
+
filesChanged: 0,
|
|
14
|
+
insertions: 0,
|
|
15
|
+
deletions: 0,
|
|
16
|
+
files: [],
|
|
17
|
+
};
|
|
18
|
+
for (const line of lines) {
|
|
19
|
+
const parts = line.split('\t');
|
|
20
|
+
if (parts.length < 3)
|
|
21
|
+
continue;
|
|
22
|
+
const insertionsStr = parts[0];
|
|
23
|
+
const deletionsStr = parts[1];
|
|
24
|
+
const path = parts.slice(2).join('\t'); // Handle paths with tabs
|
|
25
|
+
const binary = insertionsStr === '-' && deletionsStr === '-';
|
|
26
|
+
const insertions = binary ? 0 : parseInt(insertionsStr ?? '0', 10) || 0;
|
|
27
|
+
const deletions = binary ? 0 : parseInt(deletionsStr ?? '0', 10) || 0;
|
|
28
|
+
result.filesChanged++;
|
|
29
|
+
result.insertions += insertions;
|
|
30
|
+
result.deletions += deletions;
|
|
31
|
+
result.files?.push({
|
|
32
|
+
path,
|
|
33
|
+
insertions,
|
|
34
|
+
deletions,
|
|
35
|
+
binary: binary ? true : undefined,
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
return result;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Parse git diff --stat output into DiffResult
|
|
42
|
+
*
|
|
43
|
+
* stat format:
|
|
44
|
+
* <path> | <count> <bar>
|
|
45
|
+
* ...
|
|
46
|
+
* <n> files changed, <m> insertions(+), <p> deletions(-)
|
|
47
|
+
*/
|
|
48
|
+
export function parseDiffStat(output) {
|
|
49
|
+
const lines = output.split('\n').filter(Boolean);
|
|
50
|
+
const result = {
|
|
51
|
+
filesChanged: 0,
|
|
52
|
+
insertions: 0,
|
|
53
|
+
deletions: 0,
|
|
54
|
+
files: [],
|
|
55
|
+
};
|
|
56
|
+
for (const line of lines) {
|
|
57
|
+
// Summary line at the end
|
|
58
|
+
const summaryMatch = line.match(/(\d+) files? changed(?:, (\d+) insertions?\(\+\))?(?:, (\d+) deletions?\(-\))?/);
|
|
59
|
+
if (summaryMatch) {
|
|
60
|
+
result.filesChanged = parseInt(summaryMatch[1] ?? '0', 10) || 0;
|
|
61
|
+
result.insertions = parseInt(summaryMatch[2] ?? '0', 10) || 0;
|
|
62
|
+
result.deletions = parseInt(summaryMatch[3] ?? '0', 10) || 0;
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
// File stat line
|
|
66
|
+
const fileMatch = line.match(/^\s*(.+?)\s*\|\s*(\d+|Bin)/);
|
|
67
|
+
if (fileMatch && fileMatch[1]) {
|
|
68
|
+
const path = fileMatch[1].trim();
|
|
69
|
+
const binary = fileMatch[2] === 'Bin';
|
|
70
|
+
// Count + and - characters in the visual bar
|
|
71
|
+
const barMatch = line.match(/\|[^|]*$/);
|
|
72
|
+
let insertions = 0;
|
|
73
|
+
let deletions = 0;
|
|
74
|
+
if (barMatch && !binary) {
|
|
75
|
+
const bar = barMatch[0];
|
|
76
|
+
insertions = (bar.match(/\+/g) || []).length;
|
|
77
|
+
deletions = (bar.match(/-/g) || []).length;
|
|
78
|
+
}
|
|
79
|
+
result.files?.push({
|
|
80
|
+
path,
|
|
81
|
+
insertions,
|
|
82
|
+
deletions,
|
|
83
|
+
binary: binary ? true : undefined,
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return result;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Create a summary string from DiffResult
|
|
91
|
+
*/
|
|
92
|
+
export function formatDiffSummary(result) {
|
|
93
|
+
const parts = [];
|
|
94
|
+
if (result.filesChanged > 0) {
|
|
95
|
+
parts.push(`${result.filesChanged} file${result.filesChanged !== 1 ? 's' : ''} changed`);
|
|
96
|
+
}
|
|
97
|
+
if (result.insertions > 0) {
|
|
98
|
+
parts.push(`${result.insertions} insertion${result.insertions !== 1 ? 's' : ''}(+)`);
|
|
99
|
+
}
|
|
100
|
+
if (result.deletions > 0) {
|
|
101
|
+
parts.push(`${result.deletions} deletion${result.deletions !== 1 ? 's' : ''}(-)`);
|
|
102
|
+
}
|
|
103
|
+
return parts.join(', ') || 'No changes';
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=parse-diff.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse-diff.js","sourceRoot":"","sources":["../../src/utils/parse-diff.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAAc;IAC7C,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAEjD,MAAM,MAAM,GAAe;QACzB,YAAY,EAAE,CAAC;QACf,UAAU,EAAE,CAAC;QACb,SAAS,EAAE,CAAC;QACZ,KAAK,EAAE,EAAE;KACV,CAAC;IAEF,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC/B,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;YAAE,SAAS;QAE/B,MAAM,aAAa,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QAC/B,MAAM,YAAY,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QAC9B,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,yBAAyB;QAEjE,MAAM,MAAM,GAAG,aAAa,KAAK,GAAG,IAAI,YAAY,KAAK,GAAG,CAAC;QAC7D,MAAM,UAAU,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,aAAa,IAAI,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC;QACxE,MAAM,SAAS,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,YAAY,IAAI,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC;QAEtE,MAAM,CAAC,YAAY,EAAE,CAAC;QACtB,MAAM,CAAC,UAAU,IAAI,UAAU,CAAC;QAChC,MAAM,CAAC,SAAS,IAAI,SAAS,CAAC;QAC9B,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC;YACjB,IAAI;YACJ,UAAU;YACV,SAAS;YACT,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS;SAClC,CAAC,CAAC;IACL,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,aAAa,CAAC,MAAc;IAC1C,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAEjD,MAAM,MAAM,GAAe;QACzB,YAAY,EAAE,CAAC;QACf,UAAU,EAAE,CAAC;QACb,SAAS,EAAE,CAAC;QACZ,KAAK,EAAE,EAAE;KACV,CAAC;IAEF,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,0BAA0B;QAC1B,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAC7B,gFAAgF,CACjF,CAAC;QACF,IAAI,YAAY,EAAE,CAAC;YACjB,MAAM,CAAC,YAAY,GAAG,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC;YAChE,MAAM,CAAC,UAAU,GAAG,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC;YAC9D,MAAM,CAAC,SAAS,GAAG,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC;YAC7D,SAAS;QACX,CAAC;QAED,iBAAiB;QACjB,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,4BAA4B,CAAC,CAAC;QAC3D,IAAI,SAAS,IAAI,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC;YAC9B,MAAM,IAAI,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;YACjC,MAAM,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC;YAEtC,6CAA6C;YAC7C,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;YACxC,IAAI,UAAU,GAAG,CAAC,CAAC;YACnB,IAAI,SAAS,GAAG,CAAC,CAAC;YAElB,IAAI,QAAQ,IAAI,CAAC,MAAM,EAAE,CAAC;gBACxB,MAAM,GAAG,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;gBACxB,UAAU,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC;gBAC7C,SAAS,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC;YAC7C,CAAC;YAED,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC;gBACjB,IAAI;gBACJ,UAAU;gBACV,SAAS;gBACT,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS;aAClC,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,MAAkB;IAClD,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,IAAI,MAAM,CAAC,YAAY,GAAG,CAAC,EAAE,CAAC;QAC5B,KAAK,CAAC,IAAI,CACR,GAAG,MAAM,CAAC,YAAY,QAAQ,MAAM,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,UAAU,CAC7E,CAAC;IACJ,CAAC;IAED,IAAI,MAAM,CAAC,UAAU,GAAG,CAAC,EAAE,CAAC;QAC1B,KAAK,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,UAAU,aAAa,MAAM,CAAC,UAAU,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IACvF,CAAC;IAED,IAAI,MAAM,CAAC,SAAS,GAAG,CAAC,EAAE,CAAC;QACzB,KAAK,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,SAAS,YAAY,MAAM,CAAC,SAAS,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IACpF,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,YAAY,CAAC;AAC1C,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parse git log output
|
|
3
|
+
*/
|
|
4
|
+
import type { LogResult, CommitInfo } from '../types.js';
|
|
5
|
+
/**
|
|
6
|
+
* Git log format string for structured parsing
|
|
7
|
+
* Fields: hash, shortHash, authorName, authorEmail, date, parents, subject, body
|
|
8
|
+
*/
|
|
9
|
+
export declare const LOG_FORMAT: string;
|
|
10
|
+
/**
|
|
11
|
+
* Parse git log output with custom format into LogResult
|
|
12
|
+
*
|
|
13
|
+
* @param output - Raw git log output using LOG_FORMAT
|
|
14
|
+
* @param limit - The limit that was used (to determine hasMore)
|
|
15
|
+
*/
|
|
16
|
+
export declare function parseLog(output: string, limit?: number): LogResult;
|
|
17
|
+
/**
|
|
18
|
+
* Parse a simplified log format (one commit per line)
|
|
19
|
+
* Format: <hash> <subject>
|
|
20
|
+
*/
|
|
21
|
+
export declare function parseSimpleLog(output: string): Array<{
|
|
22
|
+
hash: string;
|
|
23
|
+
subject: string;
|
|
24
|
+
}>;
|
|
25
|
+
/**
|
|
26
|
+
* Format commit info for display
|
|
27
|
+
*/
|
|
28
|
+
export declare function formatCommit(commit: CommitInfo): string;
|
|
29
|
+
/**
|
|
30
|
+
* Format log result as a simple list
|
|
31
|
+
*/
|
|
32
|
+
export declare function formatLogList(result: LogResult): string;
|
|
33
|
+
//# sourceMappingURL=parse-log.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse-log.d.ts","sourceRoot":"","sources":["../../src/utils/parse-log.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAQzD;;;GAGG;AACH,eAAO,MAAM,UAAU,QASmB,CAAC;AAE3C;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,GAAE,MAAW,GAAG,SAAS,CAgCtE;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAavF;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAEvD;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM,CAMvD"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parse git log output
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Delimiter for log format fields (unlikely to appear in commit messages)
|
|
6
|
+
*/
|
|
7
|
+
const FIELD_DELIMITER = '\x1f'; // ASCII Unit Separator
|
|
8
|
+
const RECORD_DELIMITER = '\x1e'; // ASCII Record Separator
|
|
9
|
+
/**
|
|
10
|
+
* Git log format string for structured parsing
|
|
11
|
+
* Fields: hash, shortHash, authorName, authorEmail, date, parents, subject, body
|
|
12
|
+
*/
|
|
13
|
+
export const LOG_FORMAT = [
|
|
14
|
+
'%H', // hash
|
|
15
|
+
'%h', // shortHash
|
|
16
|
+
'%an', // authorName
|
|
17
|
+
'%ae', // authorEmail
|
|
18
|
+
'%aI', // date (ISO 8601)
|
|
19
|
+
'%P', // parents (space-separated)
|
|
20
|
+
'%s', // subject
|
|
21
|
+
'%b', // body
|
|
22
|
+
].join(FIELD_DELIMITER) + RECORD_DELIMITER;
|
|
23
|
+
/**
|
|
24
|
+
* Parse git log output with custom format into LogResult
|
|
25
|
+
*
|
|
26
|
+
* @param output - Raw git log output using LOG_FORMAT
|
|
27
|
+
* @param limit - The limit that was used (to determine hasMore)
|
|
28
|
+
*/
|
|
29
|
+
export function parseLog(output, limit = 10) {
|
|
30
|
+
const records = output.split(RECORD_DELIMITER).filter(Boolean);
|
|
31
|
+
const commits = [];
|
|
32
|
+
for (const record of records) {
|
|
33
|
+
const fields = record.trim().split(FIELD_DELIMITER);
|
|
34
|
+
if (fields.length < 6)
|
|
35
|
+
continue;
|
|
36
|
+
const [hash, shortHash, authorName, authorEmail, date, parentsStr, subject, ...bodyParts] = fields;
|
|
37
|
+
if (!hash || !shortHash)
|
|
38
|
+
continue;
|
|
39
|
+
const parents = parentsStr ? parentsStr.split(' ').filter(Boolean) : [];
|
|
40
|
+
const body = bodyParts.join(FIELD_DELIMITER).trim() || undefined;
|
|
41
|
+
commits.push({
|
|
42
|
+
hash,
|
|
43
|
+
shortHash,
|
|
44
|
+
authorName: authorName ?? '',
|
|
45
|
+
authorEmail: authorEmail ?? '',
|
|
46
|
+
date: date ?? '',
|
|
47
|
+
parents,
|
|
48
|
+
subject: subject ?? '',
|
|
49
|
+
body,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
return {
|
|
53
|
+
commits,
|
|
54
|
+
hasMore: commits.length >= limit,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Parse a simplified log format (one commit per line)
|
|
59
|
+
* Format: <hash> <subject>
|
|
60
|
+
*/
|
|
61
|
+
export function parseSimpleLog(output) {
|
|
62
|
+
const lines = output.split('\n').filter(Boolean);
|
|
63
|
+
return lines.map((line) => {
|
|
64
|
+
const spaceIndex = line.indexOf(' ');
|
|
65
|
+
if (spaceIndex === -1) {
|
|
66
|
+
return { hash: line, subject: '' };
|
|
67
|
+
}
|
|
68
|
+
return {
|
|
69
|
+
hash: line.slice(0, spaceIndex),
|
|
70
|
+
subject: line.slice(spaceIndex + 1),
|
|
71
|
+
};
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Format commit info for display
|
|
76
|
+
*/
|
|
77
|
+
export function formatCommit(commit) {
|
|
78
|
+
return `${commit.shortHash} ${commit.subject}`;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Format log result as a simple list
|
|
82
|
+
*/
|
|
83
|
+
export function formatLogList(result) {
|
|
84
|
+
const lines = result.commits.map(formatCommit);
|
|
85
|
+
if (result.hasMore) {
|
|
86
|
+
lines.push('...');
|
|
87
|
+
}
|
|
88
|
+
return lines.join('\n');
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=parse-log.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse-log.js","sourceRoot":"","sources":["../../src/utils/parse-log.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parse git status --porcelain=v2 output
|
|
3
|
+
*/
|
|
4
|
+
import type { StatusResult } from '../types.js';
|
|
5
|
+
/**
|
|
6
|
+
* Parse git status --porcelain=v2 output into structured StatusResult
|
|
7
|
+
*
|
|
8
|
+
* Porcelain v2 format:
|
|
9
|
+
* - Header lines start with #
|
|
10
|
+
* - # branch.oid <commit>
|
|
11
|
+
* - # branch.head <branch>
|
|
12
|
+
* - # branch.upstream <upstream>
|
|
13
|
+
* - # branch.ab +<ahead> -<behind>
|
|
14
|
+
* - Changed entries:
|
|
15
|
+
* - 1 <XY> <sub> <mH> <mI> <mW> <hH> <hI> <path>
|
|
16
|
+
* - 2 <XY> <sub> <mH> <mI> <mW> <hH> <hI> <X><score> <path><tab><origPath>
|
|
17
|
+
* - Untracked: ? <path>
|
|
18
|
+
* - Ignored: ! <path>
|
|
19
|
+
* - Unmerged: u <XY> <sub> <m1> <m2> <m3> <mW> <h1> <h2> <h3> <path>
|
|
20
|
+
*/
|
|
21
|
+
export declare function parseStatus(output: string): StatusResult;
|
|
22
|
+
//# sourceMappingURL=parse-status.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse-status.d.ts","sourceRoot":"","sources":["../../src/utils/parse-status.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAc,MAAM,aAAa,CAAC;AAE5D;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,CAmDxD"}
|