@execufunction/mcp-server 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +182 -0
- package/dist/exfClient.d.ts +565 -0
- package/dist/exfClient.d.ts.map +1 -0
- package/dist/exfClient.js +595 -0
- package/dist/exfClient.js.map +1 -0
- package/dist/gitService.d.ts +121 -0
- package/dist/gitService.d.ts.map +1 -0
- package/dist/gitService.js +451 -0
- package/dist/gitService.js.map +1 -0
- package/dist/incrementalIndexer.d.ts +42 -0
- package/dist/incrementalIndexer.d.ts.map +1 -0
- package/dist/incrementalIndexer.js +445 -0
- package/dist/incrementalIndexer.js.map +1 -0
- package/dist/index.d.ts +29 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1868 -0
- package/dist/index.js.map +1 -0
- package/dist/localIndexer.d.ts +33 -0
- package/dist/localIndexer.d.ts.map +1 -0
- package/dist/localIndexer.js +323 -0
- package/dist/localIndexer.js.map +1 -0
- package/package.json +53 -0
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Git Service
|
|
3
|
+
*
|
|
4
|
+
* Wrapper around simple-git for local git operations.
|
|
5
|
+
* Used by the incremental indexer to detect changed files.
|
|
6
|
+
*
|
|
7
|
+
* Reference: docs/design/semantic-git-system-plan.md
|
|
8
|
+
*/
|
|
9
|
+
export interface FileChange {
|
|
10
|
+
path: string;
|
|
11
|
+
changeType: 'A' | 'M' | 'D' | 'R';
|
|
12
|
+
oldPath?: string;
|
|
13
|
+
linesAdded?: number;
|
|
14
|
+
linesDeleted?: number;
|
|
15
|
+
}
|
|
16
|
+
export interface CommitInfo {
|
|
17
|
+
sha: string;
|
|
18
|
+
parentShas: string[];
|
|
19
|
+
authorName: string;
|
|
20
|
+
authorEmail: string;
|
|
21
|
+
authorDate: Date;
|
|
22
|
+
committerName: string;
|
|
23
|
+
committerEmail: string;
|
|
24
|
+
committerDate: Date;
|
|
25
|
+
message: string;
|
|
26
|
+
}
|
|
27
|
+
export interface BlameEntry {
|
|
28
|
+
sha: string;
|
|
29
|
+
author: string;
|
|
30
|
+
authorEmail: string;
|
|
31
|
+
lineStart: number;
|
|
32
|
+
lineCount: number;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Git service for local repository operations.
|
|
36
|
+
* Uses native git commands via execSync for simplicity and reliability.
|
|
37
|
+
*/
|
|
38
|
+
export declare class GitService {
|
|
39
|
+
private repoPath;
|
|
40
|
+
constructor(repoPath: string);
|
|
41
|
+
/**
|
|
42
|
+
* Execute a git command in the repository directory
|
|
43
|
+
*/
|
|
44
|
+
private exec;
|
|
45
|
+
/**
|
|
46
|
+
* Check if the directory is a git repository
|
|
47
|
+
*/
|
|
48
|
+
isGitRepository(): Promise<boolean>;
|
|
49
|
+
/**
|
|
50
|
+
* Get the current HEAD commit SHA
|
|
51
|
+
*/
|
|
52
|
+
getCurrentCommit(): Promise<string>;
|
|
53
|
+
/**
|
|
54
|
+
* Get the current branch name
|
|
55
|
+
*/
|
|
56
|
+
getCurrentBranch(): Promise<string>;
|
|
57
|
+
/**
|
|
58
|
+
* Check whether ancestorSha is reachable from descendantSha.
|
|
59
|
+
* Returns false when the commit is missing (e.g., force-push/rebase).
|
|
60
|
+
*/
|
|
61
|
+
isCommitAncestor(ancestorSha: string, descendantSha?: string): Promise<boolean>;
|
|
62
|
+
/**
|
|
63
|
+
* Get files changed between two commits
|
|
64
|
+
* Uses git diff-tree for accurate change detection
|
|
65
|
+
*/
|
|
66
|
+
getChangedFiles(fromSha: string, toSha: string): Promise<FileChange[]>;
|
|
67
|
+
/**
|
|
68
|
+
* Get files changed since a specific commit (compared to HEAD)
|
|
69
|
+
*/
|
|
70
|
+
getChangedFilesSinceCommit(fromSha: string): Promise<FileChange[]>;
|
|
71
|
+
/**
|
|
72
|
+
* Get current working tree changes (staged + unstaged + untracked).
|
|
73
|
+
* Uses porcelain output to avoid locale-dependent parsing.
|
|
74
|
+
*/
|
|
75
|
+
getWorkingTreeChanges(): Promise<FileChange[]>;
|
|
76
|
+
/**
|
|
77
|
+
* Get all tracked files in the repository
|
|
78
|
+
* Used for initial full index
|
|
79
|
+
*/
|
|
80
|
+
getAllTrackedFiles(): Promise<string[]>;
|
|
81
|
+
/**
|
|
82
|
+
* Get detailed information about a specific commit
|
|
83
|
+
*/
|
|
84
|
+
getCommitInfo(sha: string): Promise<CommitInfo>;
|
|
85
|
+
/**
|
|
86
|
+
* Get commit info for HEAD
|
|
87
|
+
*/
|
|
88
|
+
getHeadCommitInfo(): Promise<CommitInfo>;
|
|
89
|
+
/**
|
|
90
|
+
* Get blame information for a file
|
|
91
|
+
*/
|
|
92
|
+
getFileBlame(filePath: string): Promise<BlameEntry[]>;
|
|
93
|
+
/**
|
|
94
|
+
* Parse git blame --line-porcelain output
|
|
95
|
+
*/
|
|
96
|
+
private parseBlameOutput;
|
|
97
|
+
/**
|
|
98
|
+
* Check if a file exists in the repository (is tracked)
|
|
99
|
+
*/
|
|
100
|
+
isFileTracked(filePath: string): Promise<boolean>;
|
|
101
|
+
/**
|
|
102
|
+
* Get the remote URL (if any)
|
|
103
|
+
*/
|
|
104
|
+
getRemoteUrl(): Promise<string | null>;
|
|
105
|
+
/**
|
|
106
|
+
* Get list of commit SHAs between two commits (exclusive fromSha, inclusive toSha)
|
|
107
|
+
* Returns commits in chronological order (oldest first)
|
|
108
|
+
*/
|
|
109
|
+
getCommitRange(fromSha: string, toSha?: string): Promise<string[]>;
|
|
110
|
+
/**
|
|
111
|
+
* Get file changes with line stats for a specific commit
|
|
112
|
+
* Returns changes with linesAdded/linesDeleted populated
|
|
113
|
+
*/
|
|
114
|
+
getCommitChangesWithStats(sha: string): Promise<FileChange[]>;
|
|
115
|
+
/**
|
|
116
|
+
* Extract task references from a commit message
|
|
117
|
+
* Matches: #123, fixes #123, closes #123, PROJ-123, EXF-456
|
|
118
|
+
*/
|
|
119
|
+
static extractTaskReferences(message: string): string[];
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=gitService.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gitService.d.ts","sourceRoot":"","sources":["../src/gitService.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;IAClC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,IAAI,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,IAAI,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAMD;;;GAGG;AACH,qBAAa,UAAU;IACrB,OAAO,CAAC,QAAQ,CAAS;gBAEb,QAAQ,EAAE,MAAM;IAI5B;;OAEG;IACH,OAAO,CAAC,IAAI;IAYZ;;OAEG;IACG,eAAe,IAAI,OAAO,CAAC,OAAO,CAAC;IASzC;;OAEG;IACG,gBAAgB,IAAI,OAAO,CAAC,MAAM,CAAC;IAIzC;;OAEG;IACG,gBAAgB,IAAI,OAAO,CAAC,MAAM,CAAC;IASzC;;;OAGG;IACG,gBAAgB,CAAC,WAAW,EAAE,MAAM,EAAE,aAAa,GAAE,MAAe,GAAG,OAAO,CAAC,OAAO,CAAC;IAS7F;;;OAGG;IACG,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAoC5E;;OAEG;IACG,0BAA0B,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAIxE;;;OAGG;IACG,qBAAqB,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;IAmEpD;;;OAGG;IACG,kBAAkB,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAK7C;;OAEG;IACG,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAuBrD;;OAEG;IACG,iBAAiB,IAAI,OAAO,CAAC,UAAU,CAAC;IAK9C;;OAEG;IACG,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAU3D;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAsCxB;;OAEG;IACG,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IASvD;;OAEG;IACG,YAAY,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAQ5C;;;OAGG;IACG,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,GAAE,MAAe,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAUhF;;;OAGG;IACG,yBAAyB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IA2EnE;;;OAGG;IACH,MAAM,CAAC,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE;CAwBxD"}
|
|
@@ -0,0 +1,451 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Git Service
|
|
4
|
+
*
|
|
5
|
+
* Wrapper around simple-git for local git operations.
|
|
6
|
+
* Used by the incremental indexer to detect changed files.
|
|
7
|
+
*
|
|
8
|
+
* Reference: docs/design/semantic-git-system-plan.md
|
|
9
|
+
*/
|
|
10
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
13
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
14
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
15
|
+
}
|
|
16
|
+
Object.defineProperty(o, k2, desc);
|
|
17
|
+
}) : (function(o, m, k, k2) {
|
|
18
|
+
if (k2 === undefined) k2 = k;
|
|
19
|
+
o[k2] = m[k];
|
|
20
|
+
}));
|
|
21
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
22
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
23
|
+
}) : function(o, v) {
|
|
24
|
+
o["default"] = v;
|
|
25
|
+
});
|
|
26
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
27
|
+
var ownKeys = function(o) {
|
|
28
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
29
|
+
var ar = [];
|
|
30
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
31
|
+
return ar;
|
|
32
|
+
};
|
|
33
|
+
return ownKeys(o);
|
|
34
|
+
};
|
|
35
|
+
return function (mod) {
|
|
36
|
+
if (mod && mod.__esModule) return mod;
|
|
37
|
+
var result = {};
|
|
38
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
39
|
+
__setModuleDefault(result, mod);
|
|
40
|
+
return result;
|
|
41
|
+
};
|
|
42
|
+
})();
|
|
43
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
44
|
+
exports.GitService = void 0;
|
|
45
|
+
const child_process_1 = require("child_process");
|
|
46
|
+
const path = __importStar(require("path"));
|
|
47
|
+
function normalizeStatusPath(rawPath) {
|
|
48
|
+
return rawPath.trim().replace(/^"+|"+$/g, '');
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Git service for local repository operations.
|
|
52
|
+
* Uses native git commands via execSync for simplicity and reliability.
|
|
53
|
+
*/
|
|
54
|
+
class GitService {
|
|
55
|
+
repoPath;
|
|
56
|
+
constructor(repoPath) {
|
|
57
|
+
this.repoPath = path.resolve(repoPath);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Execute a git command in the repository directory
|
|
61
|
+
*/
|
|
62
|
+
exec(args) {
|
|
63
|
+
try {
|
|
64
|
+
return (0, child_process_1.execSync)(`git ${args}`, {
|
|
65
|
+
cwd: this.repoPath,
|
|
66
|
+
encoding: 'utf-8',
|
|
67
|
+
maxBuffer: 50 * 1024 * 1024, // 50MB buffer for large outputs
|
|
68
|
+
}).trim();
|
|
69
|
+
}
|
|
70
|
+
catch (err) {
|
|
71
|
+
throw new Error(`Git command failed: git ${args}\n${err.stderr || err.message}`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Check if the directory is a git repository
|
|
76
|
+
*/
|
|
77
|
+
async isGitRepository() {
|
|
78
|
+
try {
|
|
79
|
+
this.exec('rev-parse --is-inside-work-tree');
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Get the current HEAD commit SHA
|
|
88
|
+
*/
|
|
89
|
+
async getCurrentCommit() {
|
|
90
|
+
return this.exec('rev-parse HEAD');
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Get the current branch name
|
|
94
|
+
*/
|
|
95
|
+
async getCurrentBranch() {
|
|
96
|
+
try {
|
|
97
|
+
return this.exec('branch --show-current');
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
// Detached HEAD state
|
|
101
|
+
return 'HEAD';
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Check whether ancestorSha is reachable from descendantSha.
|
|
106
|
+
* Returns false when the commit is missing (e.g., force-push/rebase).
|
|
107
|
+
*/
|
|
108
|
+
async isCommitAncestor(ancestorSha, descendantSha = 'HEAD') {
|
|
109
|
+
try {
|
|
110
|
+
this.exec(`merge-base --is-ancestor ${ancestorSha} ${descendantSha}`);
|
|
111
|
+
return true;
|
|
112
|
+
}
|
|
113
|
+
catch {
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Get files changed between two commits
|
|
119
|
+
* Uses git diff-tree for accurate change detection
|
|
120
|
+
*/
|
|
121
|
+
async getChangedFiles(fromSha, toSha) {
|
|
122
|
+
// git diff-tree -r --name-status --find-renames=50% fromSha toSha
|
|
123
|
+
const output = this.exec(`diff-tree -r --name-status --find-renames=50% ${fromSha} ${toSha}`);
|
|
124
|
+
if (!output) {
|
|
125
|
+
return [];
|
|
126
|
+
}
|
|
127
|
+
const changes = [];
|
|
128
|
+
const lines = output.split('\n').filter(line => line.trim());
|
|
129
|
+
for (const line of lines) {
|
|
130
|
+
const parts = line.split('\t');
|
|
131
|
+
if (parts.length < 2)
|
|
132
|
+
continue;
|
|
133
|
+
const status = parts[0];
|
|
134
|
+
if (status.startsWith('R')) {
|
|
135
|
+
// Rename: R100\toldpath\tnewpath
|
|
136
|
+
changes.push({
|
|
137
|
+
changeType: 'R',
|
|
138
|
+
oldPath: parts[1],
|
|
139
|
+
path: parts[2],
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
else if (status === 'A') {
|
|
143
|
+
changes.push({ changeType: 'A', path: parts[1] });
|
|
144
|
+
}
|
|
145
|
+
else if (status === 'M') {
|
|
146
|
+
changes.push({ changeType: 'M', path: parts[1] });
|
|
147
|
+
}
|
|
148
|
+
else if (status === 'D') {
|
|
149
|
+
changes.push({ changeType: 'D', path: parts[1] });
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
return changes;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Get files changed since a specific commit (compared to HEAD)
|
|
156
|
+
*/
|
|
157
|
+
async getChangedFilesSinceCommit(fromSha) {
|
|
158
|
+
return this.getChangedFiles(fromSha, 'HEAD');
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Get current working tree changes (staged + unstaged + untracked).
|
|
162
|
+
* Uses porcelain output to avoid locale-dependent parsing.
|
|
163
|
+
*/
|
|
164
|
+
async getWorkingTreeChanges() {
|
|
165
|
+
const output = this.exec('status --porcelain=1 --untracked-files=all');
|
|
166
|
+
if (!output) {
|
|
167
|
+
return [];
|
|
168
|
+
}
|
|
169
|
+
const changesByPath = new Map();
|
|
170
|
+
const lines = output.split('\n').filter(line => line.trim());
|
|
171
|
+
for (const line of lines) {
|
|
172
|
+
if (line.startsWith('!! ')) {
|
|
173
|
+
continue;
|
|
174
|
+
}
|
|
175
|
+
if (line.startsWith('?? ')) {
|
|
176
|
+
const filePath = normalizeStatusPath(line.slice(3));
|
|
177
|
+
changesByPath.set(filePath, { changeType: 'A', path: filePath });
|
|
178
|
+
continue;
|
|
179
|
+
}
|
|
180
|
+
const xy = line.slice(0, 2);
|
|
181
|
+
const indexStatus = xy[0];
|
|
182
|
+
const worktreeStatus = xy[1];
|
|
183
|
+
const statusChars = `${indexStatus}${worktreeStatus}`;
|
|
184
|
+
const payload = line.slice(3).trim();
|
|
185
|
+
if (!payload) {
|
|
186
|
+
continue;
|
|
187
|
+
}
|
|
188
|
+
if (statusChars.includes('R') && payload.includes(' -> ')) {
|
|
189
|
+
const [rawOldPath, rawNewPath] = payload.split(' -> ');
|
|
190
|
+
if (!rawOldPath || !rawNewPath) {
|
|
191
|
+
continue;
|
|
192
|
+
}
|
|
193
|
+
const oldPath = normalizeStatusPath(rawOldPath);
|
|
194
|
+
const newPath = normalizeStatusPath(rawNewPath);
|
|
195
|
+
changesByPath.set(newPath, {
|
|
196
|
+
changeType: 'R',
|
|
197
|
+
oldPath,
|
|
198
|
+
path: newPath,
|
|
199
|
+
});
|
|
200
|
+
continue;
|
|
201
|
+
}
|
|
202
|
+
const filePath = normalizeStatusPath(payload);
|
|
203
|
+
let changeType = 'M';
|
|
204
|
+
if (statusChars.includes('D')) {
|
|
205
|
+
changeType = 'D';
|
|
206
|
+
}
|
|
207
|
+
else if (statusChars.includes('A')) {
|
|
208
|
+
changeType = 'A';
|
|
209
|
+
}
|
|
210
|
+
else if (statusChars.includes('R')) {
|
|
211
|
+
changeType = 'R';
|
|
212
|
+
}
|
|
213
|
+
else {
|
|
214
|
+
changeType = 'M';
|
|
215
|
+
}
|
|
216
|
+
changesByPath.set(filePath, {
|
|
217
|
+
changeType,
|
|
218
|
+
path: filePath,
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
return Array.from(changesByPath.values());
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Get all tracked files in the repository
|
|
225
|
+
* Used for initial full index
|
|
226
|
+
*/
|
|
227
|
+
async getAllTrackedFiles() {
|
|
228
|
+
const output = this.exec('ls-files');
|
|
229
|
+
return output.split('\n').filter(f => f.trim());
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Get detailed information about a specific commit
|
|
233
|
+
*/
|
|
234
|
+
async getCommitInfo(sha) {
|
|
235
|
+
// Use format placeholders to get structured output
|
|
236
|
+
// %H = commit hash, %P = parent hashes, %an = author name, %ae = author email
|
|
237
|
+
// %ai = author date ISO, %cn = committer name, %ce = committer email
|
|
238
|
+
// %ci = committer date ISO, %B = raw body (message)
|
|
239
|
+
const format = '%H%n%P%n%an%n%ae%n%ai%n%cn%n%ce%n%ci%n%B';
|
|
240
|
+
const output = this.exec(`log -1 --format="${format}" ${sha}`);
|
|
241
|
+
const lines = output.split('\n');
|
|
242
|
+
return {
|
|
243
|
+
sha: lines[0],
|
|
244
|
+
parentShas: lines[1] ? lines[1].split(' ').filter(s => s) : [],
|
|
245
|
+
authorName: lines[2],
|
|
246
|
+
authorEmail: lines[3],
|
|
247
|
+
authorDate: new Date(lines[4]),
|
|
248
|
+
committerName: lines[5],
|
|
249
|
+
committerEmail: lines[6],
|
|
250
|
+
committerDate: new Date(lines[7]),
|
|
251
|
+
message: lines.slice(8).join('\n').trim(),
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Get commit info for HEAD
|
|
256
|
+
*/
|
|
257
|
+
async getHeadCommitInfo() {
|
|
258
|
+
const sha = await this.getCurrentCommit();
|
|
259
|
+
return this.getCommitInfo(sha);
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Get blame information for a file
|
|
263
|
+
*/
|
|
264
|
+
async getFileBlame(filePath) {
|
|
265
|
+
try {
|
|
266
|
+
const output = this.exec(`blame --line-porcelain "${filePath}"`);
|
|
267
|
+
return this.parseBlameOutput(output);
|
|
268
|
+
}
|
|
269
|
+
catch {
|
|
270
|
+
// File might not exist or not be tracked
|
|
271
|
+
return [];
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Parse git blame --line-porcelain output
|
|
276
|
+
*/
|
|
277
|
+
parseBlameOutput(output) {
|
|
278
|
+
const entries = [];
|
|
279
|
+
const lines = output.split('\n');
|
|
280
|
+
let currentEntry = null;
|
|
281
|
+
let lineCount = 0;
|
|
282
|
+
for (const line of lines) {
|
|
283
|
+
if (line.match(/^[0-9a-f]{40}/)) {
|
|
284
|
+
// New blame entry: sha original-line final-line [count]
|
|
285
|
+
if (currentEntry?.sha) {
|
|
286
|
+
currentEntry.lineCount = lineCount;
|
|
287
|
+
entries.push(currentEntry);
|
|
288
|
+
}
|
|
289
|
+
const parts = line.split(' ');
|
|
290
|
+
currentEntry = {
|
|
291
|
+
sha: parts[0],
|
|
292
|
+
lineStart: parseInt(parts[2], 10),
|
|
293
|
+
};
|
|
294
|
+
lineCount = parts[3] ? parseInt(parts[3], 10) : 1;
|
|
295
|
+
}
|
|
296
|
+
else if (line.startsWith('author ') && currentEntry) {
|
|
297
|
+
currentEntry.author = line.slice(7);
|
|
298
|
+
}
|
|
299
|
+
else if (line.startsWith('author-mail ') && currentEntry) {
|
|
300
|
+
// Remove angle brackets
|
|
301
|
+
currentEntry.authorEmail = line.slice(12).replace(/[<>]/g, '');
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
// Don't forget the last entry
|
|
305
|
+
if (currentEntry?.sha) {
|
|
306
|
+
currentEntry.lineCount = lineCount;
|
|
307
|
+
entries.push(currentEntry);
|
|
308
|
+
}
|
|
309
|
+
return entries;
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* Check if a file exists in the repository (is tracked)
|
|
313
|
+
*/
|
|
314
|
+
async isFileTracked(filePath) {
|
|
315
|
+
try {
|
|
316
|
+
this.exec(`ls-files --error-unmatch "${filePath}"`);
|
|
317
|
+
return true;
|
|
318
|
+
}
|
|
319
|
+
catch {
|
|
320
|
+
return false;
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* Get the remote URL (if any)
|
|
325
|
+
*/
|
|
326
|
+
async getRemoteUrl() {
|
|
327
|
+
try {
|
|
328
|
+
return this.exec('remote get-url origin');
|
|
329
|
+
}
|
|
330
|
+
catch {
|
|
331
|
+
return null;
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* Get list of commit SHAs between two commits (exclusive fromSha, inclusive toSha)
|
|
336
|
+
* Returns commits in chronological order (oldest first)
|
|
337
|
+
*/
|
|
338
|
+
async getCommitRange(fromSha, toSha = 'HEAD') {
|
|
339
|
+
try {
|
|
340
|
+
const output = this.exec(`rev-list --reverse ${fromSha}..${toSha}`);
|
|
341
|
+
if (!output)
|
|
342
|
+
return [];
|
|
343
|
+
return output.split('\n').filter(sha => sha.trim());
|
|
344
|
+
}
|
|
345
|
+
catch {
|
|
346
|
+
return [];
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
/**
|
|
350
|
+
* Get file changes with line stats for a specific commit
|
|
351
|
+
* Returns changes with linesAdded/linesDeleted populated
|
|
352
|
+
*/
|
|
353
|
+
async getCommitChangesWithStats(sha) {
|
|
354
|
+
// Get name-status for change types
|
|
355
|
+
const statusOutput = this.exec(`show --name-status --format= ${sha}`);
|
|
356
|
+
// Get numstat for line counts
|
|
357
|
+
const numstatOutput = this.exec(`show --numstat --format= ${sha}`);
|
|
358
|
+
const changes = [];
|
|
359
|
+
const lineStats = new Map();
|
|
360
|
+
// Parse numstat: "added\tdeleted\tpath" or "added\tdeleted\toldpath => newpath"
|
|
361
|
+
for (const line of numstatOutput.split('\n').filter(l => l.trim())) {
|
|
362
|
+
const parts = line.split('\t');
|
|
363
|
+
if (parts.length >= 3) {
|
|
364
|
+
const added = parts[0] === '-' ? 0 : parseInt(parts[0], 10) || 0;
|
|
365
|
+
const deleted = parts[1] === '-' ? 0 : parseInt(parts[1], 10) || 0;
|
|
366
|
+
// Handle rename format: "old => new" or just "path"
|
|
367
|
+
let path = parts.slice(2).join('\t');
|
|
368
|
+
if (path.includes(' => ')) {
|
|
369
|
+
path = path.split(' => ')[1].replace(/[{}]/g, '');
|
|
370
|
+
}
|
|
371
|
+
lineStats.set(path, { added, deleted });
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
// Parse name-status for change types
|
|
375
|
+
for (const line of statusOutput.split('\n').filter(l => l.trim())) {
|
|
376
|
+
const parts = line.split('\t');
|
|
377
|
+
if (parts.length < 2)
|
|
378
|
+
continue;
|
|
379
|
+
const status = parts[0];
|
|
380
|
+
if (status.startsWith('R')) {
|
|
381
|
+
const oldPath = parts[1];
|
|
382
|
+
const newPath = parts[2];
|
|
383
|
+
const stats = lineStats.get(newPath) || { added: 0, deleted: 0 };
|
|
384
|
+
changes.push({
|
|
385
|
+
changeType: 'R',
|
|
386
|
+
oldPath,
|
|
387
|
+
path: newPath,
|
|
388
|
+
linesAdded: stats.added,
|
|
389
|
+
linesDeleted: stats.deleted,
|
|
390
|
+
});
|
|
391
|
+
}
|
|
392
|
+
else if (status === 'A') {
|
|
393
|
+
const path = parts[1];
|
|
394
|
+
const stats = lineStats.get(path) || { added: 0, deleted: 0 };
|
|
395
|
+
changes.push({
|
|
396
|
+
changeType: 'A',
|
|
397
|
+
path,
|
|
398
|
+
linesAdded: stats.added,
|
|
399
|
+
linesDeleted: stats.deleted,
|
|
400
|
+
});
|
|
401
|
+
}
|
|
402
|
+
else if (status === 'M') {
|
|
403
|
+
const path = parts[1];
|
|
404
|
+
const stats = lineStats.get(path) || { added: 0, deleted: 0 };
|
|
405
|
+
changes.push({
|
|
406
|
+
changeType: 'M',
|
|
407
|
+
path,
|
|
408
|
+
linesAdded: stats.added,
|
|
409
|
+
linesDeleted: stats.deleted,
|
|
410
|
+
});
|
|
411
|
+
}
|
|
412
|
+
else if (status === 'D') {
|
|
413
|
+
const path = parts[1];
|
|
414
|
+
const stats = lineStats.get(path) || { added: 0, deleted: 0 };
|
|
415
|
+
changes.push({
|
|
416
|
+
changeType: 'D',
|
|
417
|
+
path,
|
|
418
|
+
linesAdded: stats.added,
|
|
419
|
+
linesDeleted: stats.deleted,
|
|
420
|
+
});
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
return changes;
|
|
424
|
+
}
|
|
425
|
+
/**
|
|
426
|
+
* Extract task references from a commit message
|
|
427
|
+
* Matches: #123, fixes #123, closes #123, PROJ-123, EXF-456
|
|
428
|
+
*/
|
|
429
|
+
static extractTaskReferences(message) {
|
|
430
|
+
const refs = [];
|
|
431
|
+
// GitHub style: #123, fixes #123, closes #123, resolves #123
|
|
432
|
+
for (const match of message.matchAll(/(fixes?|closes?|resolves?)?\s*#(\d+)/gi)) {
|
|
433
|
+
refs.push(match[2]);
|
|
434
|
+
}
|
|
435
|
+
// Jira/Linear style: PROJ-123, EXF-456 (2+ uppercase letters, dash, digits)
|
|
436
|
+
for (const match of message.matchAll(/([A-Z]{2,}-\d+)/g)) {
|
|
437
|
+
refs.push(match[1]);
|
|
438
|
+
}
|
|
439
|
+
// UUID prefix match (first 6-8 chars of UUID)
|
|
440
|
+
for (const match of message.matchAll(/\b([a-f0-9]{6,8})\b/gi)) {
|
|
441
|
+
// Only include if it looks like a task ref (not part of a longer hash)
|
|
442
|
+
const candidate = match[1].toLowerCase();
|
|
443
|
+
if (!message.includes(candidate + candidate[0])) { // Avoid matching partial SHAs
|
|
444
|
+
refs.push(candidate);
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
return [...new Set(refs)]; // Deduplicate
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
exports.GitService = GitService;
|
|
451
|
+
//# sourceMappingURL=gitService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gitService.js","sourceRoot":"","sources":["../src/gitService.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Incremental Indexer
|
|
3
|
+
*
|
|
4
|
+
* Git-aware indexing that only uploads changed files.
|
|
5
|
+
* Falls back to full index for non-git directories or first-time index.
|
|
6
|
+
*
|
|
7
|
+
* Reference: docs/design/semantic-git-system-plan.md § Phase 1
|
|
8
|
+
*/
|
|
9
|
+
import { ExfClient } from './exfClient.js';
|
|
10
|
+
import { IndexProgress, ProgressCallback } from './localIndexer.js';
|
|
11
|
+
export interface IncrementalIndexProgress extends IndexProgress {
|
|
12
|
+
isIncremental: boolean;
|
|
13
|
+
fromCommit?: string;
|
|
14
|
+
toCommit?: string;
|
|
15
|
+
changesDetected?: number;
|
|
16
|
+
chunksReused?: number;
|
|
17
|
+
workingTreeChanges?: number;
|
|
18
|
+
fallbackReason?: string;
|
|
19
|
+
usedRepositoryPatterns?: boolean;
|
|
20
|
+
}
|
|
21
|
+
export interface IncrementalIndexOptions {
|
|
22
|
+
includePatterns?: string[];
|
|
23
|
+
excludePatterns?: string[];
|
|
24
|
+
onProgress?: ProgressCallback;
|
|
25
|
+
includeWorkingTree?: boolean;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Incrementally index a codebase using git diff.
|
|
29
|
+
*
|
|
30
|
+
* Flow:
|
|
31
|
+
* 1. Check if git repository
|
|
32
|
+
* 2. Get last indexed commit from backend
|
|
33
|
+
* 3. If no last commit → full index
|
|
34
|
+
* 4. If same commit → no changes
|
|
35
|
+
* 5. Otherwise → get changed files via git diff, upload only those
|
|
36
|
+
*/
|
|
37
|
+
export declare function indexIncrementally(client: ExfClient, repositoryId: string, rootPath: string, options?: IncrementalIndexOptions): Promise<IncrementalIndexProgress>;
|
|
38
|
+
/**
|
|
39
|
+
* Format incremental index result for display
|
|
40
|
+
*/
|
|
41
|
+
export declare function formatIncrementalResult(result: IncrementalIndexProgress): string;
|
|
42
|
+
//# sourceMappingURL=incrementalIndexer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"incrementalIndexer.d.ts","sourceRoot":"","sources":["../src/incrementalIndexer.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C,OAAO,EAAqC,aAAa,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAEvG,MAAM,WAAW,wBAAyB,SAAQ,aAAa;IAC7D,aAAa,EAAE,OAAO,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,sBAAsB,CAAC,EAAE,OAAO,CAAC;CAClC;AAED,MAAM,WAAW,uBAAuB;IACtC,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AA2HD;;;;;;;;;GASG;AACH,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,SAAS,EACjB,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,uBAA4B,GACpC,OAAO,CAAC,wBAAwB,CAAC,CAqSnC;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,wBAAwB,GAAG,MAAM,CAkDhF"}
|