gitlab-auto-reviewers 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +1878 -0
- package/dist/api/gitlab-api.d.ts +136 -0
- package/dist/api/gitlab-api.d.ts.map +1 -0
- package/dist/api/gitlab-api.js +334 -0
- package/dist/api/gitlab-api.js.map +1 -0
- package/dist/bin/cli.d.ts +10 -0
- package/dist/bin/cli.d.ts.map +1 -0
- package/dist/bin/cli.js +186 -0
- package/dist/bin/cli.js.map +1 -0
- package/dist/bin/deprecated-mcp.d.ts +12 -0
- package/dist/bin/deprecated-mcp.d.ts.map +1 -0
- package/dist/bin/deprecated-mcp.js +73 -0
- package/dist/bin/deprecated-mcp.js.map +1 -0
- package/dist/bin/index.d.ts +18 -0
- package/dist/bin/index.d.ts.map +1 -0
- package/dist/bin/index.js +78 -0
- package/dist/bin/index.js.map +1 -0
- package/dist/bin/mcp.d.ts +11 -0
- package/dist/bin/mcp.d.ts.map +1 -0
- package/dist/bin/mcp.js +43 -0
- package/dist/bin/mcp.js.map +1 -0
- package/dist/cache/cache.service.d.ts +113 -0
- package/dist/cache/cache.service.d.ts.map +1 -0
- package/dist/cache/cache.service.js +213 -0
- package/dist/cache/cache.service.js.map +1 -0
- package/dist/cli/commands.d.ts +40 -0
- package/dist/cli/commands.d.ts.map +1 -0
- package/dist/cli/commands.js +142 -0
- package/dist/cli/commands.js.map +1 -0
- package/dist/cli/output.d.ts +24 -0
- package/dist/cli/output.d.ts.map +1 -0
- package/dist/cli/output.js +143 -0
- package/dist/cli/output.js.map +1 -0
- package/dist/config/config.service.d.ts +89 -0
- package/dist/config/config.service.d.ts.map +1 -0
- package/dist/config/config.service.js +169 -0
- package/dist/config/config.service.js.map +1 -0
- package/dist/datasources/git-data-source.interface.d.ts +140 -0
- package/dist/datasources/git-data-source.interface.d.ts.map +1 -0
- package/dist/datasources/git-data-source.interface.js +2 -0
- package/dist/datasources/git-data-source.interface.js.map +1 -0
- package/dist/datasources/gitlab-api-data-source.d.ts +127 -0
- package/dist/datasources/gitlab-api-data-source.d.ts.map +1 -0
- package/dist/datasources/gitlab-api-data-source.js +248 -0
- package/dist/datasources/gitlab-api-data-source.js.map +1 -0
- package/dist/datasources/local-git-data-source.d.ts +124 -0
- package/dist/datasources/local-git-data-source.d.ts.map +1 -0
- package/dist/datasources/local-git-data-source.js +580 -0
- package/dist/datasources/local-git-data-source.js.map +1 -0
- package/dist/errors/error-handler.d.ts +113 -0
- package/dist/errors/error-handler.d.ts.map +1 -0
- package/dist/errors/error-handler.js +230 -0
- package/dist/errors/error-handler.js.map +1 -0
- package/dist/index.d.ts +139 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +139 -0
- package/dist/index.js.map +1 -0
- package/dist/logging/example.d.ts +15 -0
- package/dist/logging/example.d.ts.map +1 -0
- package/dist/logging/example.js +79 -0
- package/dist/logging/example.js.map +1 -0
- package/dist/logging/index.d.ts +7 -0
- package/dist/logging/index.d.ts.map +1 -0
- package/dist/logging/index.js +7 -0
- package/dist/logging/index.js.map +1 -0
- package/dist/logging/logger.service.d.ts +98 -0
- package/dist/logging/logger.service.d.ts.map +1 -0
- package/dist/logging/logger.service.js +160 -0
- package/dist/logging/logger.service.js.map +1 -0
- package/dist/mcp/server.d.ts +67 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +213 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/tools.d.ts +22 -0
- package/dist/mcp/tools.d.ts.map +1 -0
- package/dist/mcp/tools.js +176 -0
- package/dist/mcp/tools.js.map +1 -0
- package/dist/services/blacklist.service.d.ts +32 -0
- package/dist/services/blacklist.service.d.ts.map +1 -0
- package/dist/services/blacklist.service.js +59 -0
- package/dist/services/blacklist.service.js.map +1 -0
- package/dist/services/codeowners.service.d.ts +45 -0
- package/dist/services/codeowners.service.d.ts.map +1 -0
- package/dist/services/codeowners.service.js +200 -0
- package/dist/services/codeowners.service.js.map +1 -0
- package/dist/services/comment-builder.service.d.ts +48 -0
- package/dist/services/comment-builder.service.d.ts.map +1 -0
- package/dist/services/comment-builder.service.js +61 -0
- package/dist/services/comment-builder.service.js.map +1 -0
- package/dist/services/contributors.service.d.ts +52 -0
- package/dist/services/contributors.service.d.ts.map +1 -0
- package/dist/services/contributors.service.js +144 -0
- package/dist/services/contributors.service.js.map +1 -0
- package/dist/services/reviewer-service.d.ts +125 -0
- package/dist/services/reviewer-service.d.ts.map +1 -0
- package/dist/services/reviewer-service.js +554 -0
- package/dist/services/reviewer-service.js.map +1 -0
- package/dist/services/team-members.service.d.ts +29 -0
- package/dist/services/team-members.service.d.ts.map +1 -0
- package/dist/services/team-members.service.js +45 -0
- package/dist/services/team-members.service.js.map +1 -0
- package/dist/services/whitelist.service.d.ts +31 -0
- package/dist/services/whitelist.service.d.ts.map +1 -0
- package/dist/services/whitelist.service.js +51 -0
- package/dist/services/whitelist.service.js.map +1 -0
- package/dist/tools.d.ts +22 -0
- package/dist/tools.d.ts.map +1 -0
- package/dist/tools.js +176 -0
- package/dist/tools.js.map +1 -0
- package/dist/types/index.d.ts +502 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +91 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types.d.ts +219 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +7 -0
- package/dist/types.js.map +1 -0
- package/package.json +71 -0
|
@@ -0,0 +1,580 @@
|
|
|
1
|
+
import { readFileSync } from "fs";
|
|
2
|
+
import { join } from "path";
|
|
3
|
+
import simpleGit from "simple-git";
|
|
4
|
+
import { GitLabAPIDataSource } from "./gitlab-api-data-source.js";
|
|
5
|
+
import { Logger } from "../logging/logger.service.js";
|
|
6
|
+
import { ErrorHandler } from "../errors/error-handler.js";
|
|
7
|
+
import { ConfigService } from "../config/config.service.js";
|
|
8
|
+
/**
|
|
9
|
+
* Local git repository data source implementation
|
|
10
|
+
*
|
|
11
|
+
* Provides access to git data through local git operations using simple-git.
|
|
12
|
+
* Falls back to GitLab API for operations that fail locally.
|
|
13
|
+
* Extends GitLabAPIDataSource to inherit API-based methods.
|
|
14
|
+
*/
|
|
15
|
+
export class LocalGitDataSource extends GitLabAPIDataSource {
|
|
16
|
+
repoPath;
|
|
17
|
+
config;
|
|
18
|
+
/**
|
|
19
|
+
* Create a new local git data source
|
|
20
|
+
*
|
|
21
|
+
* @param gitlabApi - GitLab API client instance for fallback operations
|
|
22
|
+
* @param repoPath - Path to the local git repository
|
|
23
|
+
* @param logger - Optional logger instance for logging operations
|
|
24
|
+
* @param config - Optional configuration service for settings
|
|
25
|
+
*/
|
|
26
|
+
constructor(gitlabApi, repoPath, logger, config) {
|
|
27
|
+
super(gitlabApi, logger || new Logger('LocalGitDataSource'));
|
|
28
|
+
this.repoPath = repoPath;
|
|
29
|
+
this.config = config || new ConfigService();
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Get the project path from the git remote URL
|
|
33
|
+
*
|
|
34
|
+
* Parses the origin remote URL to extract the project path.
|
|
35
|
+
* Supports SSH, HTTPS, and git protocol URLs.
|
|
36
|
+
*
|
|
37
|
+
* @returns Promise resolving to the project path (e.g., "group/project")
|
|
38
|
+
* @throws {MCPError} If no origin remote is found or URL format is unsupported
|
|
39
|
+
*/
|
|
40
|
+
async getProjectFromRemote() {
|
|
41
|
+
const context = { repoPath: this.repoPath, dataSource: 'LocalGit' };
|
|
42
|
+
try {
|
|
43
|
+
const git = simpleGit(this.repoPath);
|
|
44
|
+
const remotes = await git.getRemotes(true);
|
|
45
|
+
const origin = remotes.find((r) => r.name === "origin");
|
|
46
|
+
if (!origin?.refs?.fetch) {
|
|
47
|
+
const remoteNames = remotes.map(r => r.name);
|
|
48
|
+
throw ErrorHandler.gitOperationError('No origin remote found in repository. Ensure the repository has an origin remote configured.', { ...context, remotes: remoteNames }, new Error('No origin remote'));
|
|
49
|
+
}
|
|
50
|
+
const url = origin.refs.fetch.replace(/\.git$/, "");
|
|
51
|
+
// ssh://user@host:port/path or ssh://user@host/path
|
|
52
|
+
const sshProtocol = /^ssh:\/\/(?:[^@]+@)?[^/]+(?::\d+)?\/(.*)/;
|
|
53
|
+
// https://host/path
|
|
54
|
+
const https = /^https?:\/\/[^/]+\/(.*)/;
|
|
55
|
+
// git://host/path
|
|
56
|
+
const gitProtocol = /^git:\/\/[^/]+\/(.*)/;
|
|
57
|
+
// user@host:path (SSH shorthand)
|
|
58
|
+
const sshShorthand = /^[^@]+@[^:]+:(.*)$/;
|
|
59
|
+
for (const pattern of [sshProtocol, https, gitProtocol, sshShorthand]) {
|
|
60
|
+
const match = url.match(pattern);
|
|
61
|
+
if (match) {
|
|
62
|
+
this.logger.debug('Parsed project from remote', {
|
|
63
|
+
project: match[1],
|
|
64
|
+
remoteUrl: url,
|
|
65
|
+
dataSource: 'LocalGit',
|
|
66
|
+
});
|
|
67
|
+
return match[1];
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
throw ErrorHandler.gitOperationError(`Cannot parse project path from remote URL. The URL format may not be supported.`, { ...context, remoteUrl: origin.refs.fetch }, new Error('Unsupported remote URL format'));
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
if (error instanceof Error && error.message.includes('MCP')) {
|
|
74
|
+
throw error;
|
|
75
|
+
}
|
|
76
|
+
throw ErrorHandler.gitOperationError('Failed to get project from remote', context, error instanceof Error ? error : new Error(String(error)));
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Get the current branch name from the local repository
|
|
81
|
+
*
|
|
82
|
+
* @returns Promise resolving to the current branch name
|
|
83
|
+
* @throws {MCPError} If repository is in detached HEAD state or branch cannot be determined
|
|
84
|
+
*/
|
|
85
|
+
async getCurrentBranch() {
|
|
86
|
+
const context = { repoPath: this.repoPath, dataSource: 'LocalGit' };
|
|
87
|
+
try {
|
|
88
|
+
const git = simpleGit(this.repoPath);
|
|
89
|
+
const status = await git.status();
|
|
90
|
+
if (!status.current) {
|
|
91
|
+
const errorContext = { ...context, isDetached: status.detached };
|
|
92
|
+
throw ErrorHandler.gitOperationError('Repository is in detached HEAD state or branch cannot be determined', errorContext, new Error('No current branch'));
|
|
93
|
+
}
|
|
94
|
+
this.logger.debug('Current branch detected', {
|
|
95
|
+
branch: status.current,
|
|
96
|
+
repoPath: this.repoPath,
|
|
97
|
+
dataSource: 'LocalGit',
|
|
98
|
+
});
|
|
99
|
+
return status.current;
|
|
100
|
+
}
|
|
101
|
+
catch (error) {
|
|
102
|
+
if (error instanceof Error && error.message.includes('MCP')) {
|
|
103
|
+
throw error;
|
|
104
|
+
}
|
|
105
|
+
throw ErrorHandler.gitOperationError('Failed to get current branch', context, error instanceof Error ? error : new Error(String(error)));
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Get the default branch from local git repository
|
|
110
|
+
*
|
|
111
|
+
* Queries the remote HEAD to determine the default branch.
|
|
112
|
+
* Falls back to GitLab API if local detection fails.
|
|
113
|
+
*
|
|
114
|
+
* @param project - The project ID or path
|
|
115
|
+
* @returns Promise resolving to the default branch name
|
|
116
|
+
* @throws {MCPError} If both local and API detection fail
|
|
117
|
+
*/
|
|
118
|
+
async getDefaultBranch(project) {
|
|
119
|
+
const endTimer = this.logger.startTimer('getDefaultBranch');
|
|
120
|
+
const context = { project, repoPath: this.repoPath, dataSource: 'LocalGit' };
|
|
121
|
+
try {
|
|
122
|
+
this.logger.info('Getting default branch from local git', {
|
|
123
|
+
project,
|
|
124
|
+
repoPath: this.repoPath,
|
|
125
|
+
dataSource: 'LocalGit',
|
|
126
|
+
});
|
|
127
|
+
const git = simpleGit(this.repoPath);
|
|
128
|
+
// Wrap git operation with retry logic
|
|
129
|
+
const result = await ErrorHandler.withRetry(async () => {
|
|
130
|
+
return await git.raw(['symbolic-ref', 'refs/remotes/origin/HEAD']);
|
|
131
|
+
}, {
|
|
132
|
+
maxRetries: this.config.get().maxRetries,
|
|
133
|
+
delayMs: this.config.get().retryDelayMs,
|
|
134
|
+
});
|
|
135
|
+
// Parse: refs/remotes/origin/main → main
|
|
136
|
+
const branch = result.trim().replace('refs/remotes/origin/', '');
|
|
137
|
+
if (!branch) {
|
|
138
|
+
throw new Error('Empty branch name returned from git');
|
|
139
|
+
}
|
|
140
|
+
this.logger.info('Default branch detected from local git', {
|
|
141
|
+
branch,
|
|
142
|
+
project,
|
|
143
|
+
dataSource: 'LocalGit',
|
|
144
|
+
});
|
|
145
|
+
endTimer();
|
|
146
|
+
return branch;
|
|
147
|
+
}
|
|
148
|
+
catch (error) {
|
|
149
|
+
endTimer();
|
|
150
|
+
// Graceful fallback to API
|
|
151
|
+
this.logger.warn('Local git default branch detection failed, falling back to API', {
|
|
152
|
+
...context,
|
|
153
|
+
error: error instanceof Error ? error.message : String(error),
|
|
154
|
+
});
|
|
155
|
+
try {
|
|
156
|
+
const branch = await super.getDefaultBranch(project);
|
|
157
|
+
this.logger.info('Default branch retrieved from API fallback', {
|
|
158
|
+
branch,
|
|
159
|
+
project,
|
|
160
|
+
dataSource: 'GitLabAPI (fallback)',
|
|
161
|
+
});
|
|
162
|
+
return branch;
|
|
163
|
+
}
|
|
164
|
+
catch (apiError) {
|
|
165
|
+
// If both local and API fail, throw error
|
|
166
|
+
this.logger.error('Both local and API default branch detection failed', apiError instanceof Error ? apiError : new Error(String(apiError)), context);
|
|
167
|
+
throw ErrorHandler.gitOperationError('Failed to get default branch from both local git and API', context, apiError instanceof Error ? apiError : new Error(String(apiError)));
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Get project contributors from local git history
|
|
173
|
+
*
|
|
174
|
+
* Analyzes commit history using configurable date range to identify contributors.
|
|
175
|
+
* Uses retry logic for git operations.
|
|
176
|
+
*
|
|
177
|
+
* @param project - The project ID or path (used for logging)
|
|
178
|
+
* @param commitSha - The commit SHA to analyze history from
|
|
179
|
+
* @returns Promise resolving to array of contributor email addresses (up to 100)
|
|
180
|
+
*/
|
|
181
|
+
async getProjectContributors(project, commitSha) {
|
|
182
|
+
const endTimer = this.logger.startTimer('getProjectContributors');
|
|
183
|
+
const context = { project, commitSha, repoPath: this.repoPath, dataSource: 'LocalGit' };
|
|
184
|
+
try {
|
|
185
|
+
this.logger.info('Getting contributors for commit', {
|
|
186
|
+
commitSha,
|
|
187
|
+
repoPath: this.repoPath,
|
|
188
|
+
dataSource: 'LocalGit',
|
|
189
|
+
});
|
|
190
|
+
// Use configurable date range from configuration (Requirement 6.5)
|
|
191
|
+
const contributorDays = this.config.get().contributorDays;
|
|
192
|
+
const sinceDate = new Date();
|
|
193
|
+
sinceDate.setDate(sinceDate.getDate() - contributorDays);
|
|
194
|
+
const sinceDateStr = sinceDate.toISOString().split("T")[0];
|
|
195
|
+
const git = simpleGit(this.repoPath);
|
|
196
|
+
// Wrap git operation with retry logic (Requirement 3.2)
|
|
197
|
+
const output = await ErrorHandler.withRetry(async () => {
|
|
198
|
+
return await git.raw([
|
|
199
|
+
"log",
|
|
200
|
+
commitSha,
|
|
201
|
+
"--format=%ae",
|
|
202
|
+
`--since=${sinceDateStr}`,
|
|
203
|
+
"--no-merges",
|
|
204
|
+
]);
|
|
205
|
+
}, {
|
|
206
|
+
maxRetries: this.config.get().maxRetries,
|
|
207
|
+
delayMs: this.config.get().retryDelayMs,
|
|
208
|
+
});
|
|
209
|
+
const commits = output
|
|
210
|
+
.trim()
|
|
211
|
+
.split("\n")
|
|
212
|
+
.filter((e) => e);
|
|
213
|
+
this.logger.debug('Contributor analysis complete', {
|
|
214
|
+
dateRange: sinceDateStr,
|
|
215
|
+
totalCommits: commits.length,
|
|
216
|
+
dataSource: 'LocalGit',
|
|
217
|
+
});
|
|
218
|
+
const contributorCounts = {};
|
|
219
|
+
commits
|
|
220
|
+
.filter((email) => email)
|
|
221
|
+
.forEach((email) => {
|
|
222
|
+
const normalizedEmail = email.toLowerCase();
|
|
223
|
+
contributorCounts[normalizedEmail] =
|
|
224
|
+
(contributorCounts[normalizedEmail] || 0) + 1;
|
|
225
|
+
});
|
|
226
|
+
const result = Object.entries(contributorCounts)
|
|
227
|
+
.sort(([, a], [, b]) => b - a)
|
|
228
|
+
.slice(0, 100)
|
|
229
|
+
.map(([email]) => email);
|
|
230
|
+
this.logger.info('Contributors retrieved', {
|
|
231
|
+
count: result.length,
|
|
232
|
+
dateRange: sinceDateStr,
|
|
233
|
+
dataSource: 'LocalGit',
|
|
234
|
+
});
|
|
235
|
+
endTimer();
|
|
236
|
+
return result;
|
|
237
|
+
}
|
|
238
|
+
catch (error) {
|
|
239
|
+
endTimer();
|
|
240
|
+
throw ErrorHandler.gitOperationError('Failed to get project contributors', context, error instanceof Error ? error : new Error(String(error)));
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Get git blame information from local repository
|
|
245
|
+
*
|
|
246
|
+
* Validates commit existence before attempting blame.
|
|
247
|
+
* Falls back to API if local blame fails (graceful degradation).
|
|
248
|
+
*
|
|
249
|
+
* @param project - The project ID or path
|
|
250
|
+
* @param path - The file path within the repository
|
|
251
|
+
* @param ref - The commit SHA to blame
|
|
252
|
+
* @returns Promise resolving to array of blame lines (empty array if both local and API fail)
|
|
253
|
+
*/
|
|
254
|
+
async getBlame(project, path, ref) {
|
|
255
|
+
const endTimer = this.logger.startTimer('getBlame');
|
|
256
|
+
const context = { project, path, ref: ref.substring(0, 8), repoPath: this.repoPath, dataSource: 'LocalGit' };
|
|
257
|
+
try {
|
|
258
|
+
// Validate commit exists before attempting blame (Requirement 6.1)
|
|
259
|
+
await this.validateCommitExists(ref);
|
|
260
|
+
const git = simpleGit(this.repoPath);
|
|
261
|
+
// Wrap git operation with retry logic (Requirement 3.2)
|
|
262
|
+
const result = await ErrorHandler.withRetry(async () => {
|
|
263
|
+
return await git.raw([
|
|
264
|
+
"blame",
|
|
265
|
+
"--line-porcelain",
|
|
266
|
+
ref,
|
|
267
|
+
"--",
|
|
268
|
+
path,
|
|
269
|
+
]);
|
|
270
|
+
}, {
|
|
271
|
+
maxRetries: this.config.get().maxRetries,
|
|
272
|
+
delayMs: this.config.get().retryDelayMs,
|
|
273
|
+
});
|
|
274
|
+
const lines = result.split("\n");
|
|
275
|
+
const blameData = [];
|
|
276
|
+
let currentCommit = null;
|
|
277
|
+
for (const line of lines) {
|
|
278
|
+
if (line.match(/^[0-9a-f]{40}/)) {
|
|
279
|
+
if (currentCommit && currentCommit.commit) {
|
|
280
|
+
blameData.push(currentCommit);
|
|
281
|
+
}
|
|
282
|
+
currentCommit = {
|
|
283
|
+
commit: {
|
|
284
|
+
id: line.split(" ")[0],
|
|
285
|
+
message: '',
|
|
286
|
+
parent_ids: [],
|
|
287
|
+
authored_date: '',
|
|
288
|
+
author_name: '',
|
|
289
|
+
author_email: '',
|
|
290
|
+
committed_date: '',
|
|
291
|
+
committer_name: '',
|
|
292
|
+
committer_email: ''
|
|
293
|
+
},
|
|
294
|
+
lines: ['1']
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
else if (line.startsWith("author-mail ") && currentCommit?.commit) {
|
|
298
|
+
currentCommit.commit.author_email = line.substring(13, line.length - 1);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
if (currentCommit && currentCommit.commit) {
|
|
302
|
+
blameData.push(currentCommit);
|
|
303
|
+
}
|
|
304
|
+
this.logger.debug('Blame operation successful', {
|
|
305
|
+
...context,
|
|
306
|
+
entries: blameData.length,
|
|
307
|
+
});
|
|
308
|
+
endTimer();
|
|
309
|
+
return blameData;
|
|
310
|
+
}
|
|
311
|
+
catch (error) {
|
|
312
|
+
endTimer();
|
|
313
|
+
// Graceful fallback to API (Requirement 6.2)
|
|
314
|
+
this.logger.warn('Local git blame failed, falling back to API', {
|
|
315
|
+
...context,
|
|
316
|
+
error: error instanceof Error ? error.message : String(error),
|
|
317
|
+
});
|
|
318
|
+
try {
|
|
319
|
+
const apiResult = await super.getBlame(project, path, ref);
|
|
320
|
+
return apiResult || [];
|
|
321
|
+
}
|
|
322
|
+
catch (apiError) {
|
|
323
|
+
// If both local and API fail, log and return empty array (graceful degradation)
|
|
324
|
+
this.logger.error('Both local and API blame failed', apiError instanceof Error ? apiError : new Error(String(apiError)), context);
|
|
325
|
+
return [];
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* Validates that a commit exists in the repository (Requirement 6.1)
|
|
331
|
+
*/
|
|
332
|
+
async validateCommitExists(commitSha) {
|
|
333
|
+
try {
|
|
334
|
+
const git = simpleGit(this.repoPath);
|
|
335
|
+
await git.catFile(["-e", commitSha]);
|
|
336
|
+
}
|
|
337
|
+
catch (error) {
|
|
338
|
+
const shortSha = commitSha.substring(0, 8);
|
|
339
|
+
throw ErrorHandler.gitOperationError(`Commit ${shortSha} does not exist in repository`, {
|
|
340
|
+
commitSha,
|
|
341
|
+
repoPath: this.repoPath,
|
|
342
|
+
dataSource: 'LocalGit',
|
|
343
|
+
}, error instanceof Error ? error : new Error(String(error)));
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
/**
|
|
347
|
+
* Get diffs for a merge request from local git repository
|
|
348
|
+
*
|
|
349
|
+
* Validates commits exist, handles special characters in paths,
|
|
350
|
+
* and fetches diffs in parallel for performance.
|
|
351
|
+
*
|
|
352
|
+
* @param project - The project ID or path
|
|
353
|
+
* @param mr - The merge request internal ID
|
|
354
|
+
* @returns Promise resolving to array of diffs
|
|
355
|
+
* @throws {MCPError} If merge request data is invalid or commits don't exist
|
|
356
|
+
*/
|
|
357
|
+
async getDiffs(project, mr) {
|
|
358
|
+
const endTimer = this.logger.startTimer('getDiffs');
|
|
359
|
+
const context = { project, mr, repoPath: this.repoPath, dataSource: 'LocalGit' };
|
|
360
|
+
try {
|
|
361
|
+
const mrData = await this.getMergeRequest(project, mr);
|
|
362
|
+
// Validate merge request data (Requirement 6.4)
|
|
363
|
+
if (!mrData?.diff_refs?.base_sha || !mrData?.diff_refs?.head_sha) {
|
|
364
|
+
throw ErrorHandler.validationError('Merge request data is missing diff_refs. The MR may not have been fetched correctly or may be in an invalid state.', {
|
|
365
|
+
...context,
|
|
366
|
+
diff_refs: mrData?.diff_refs,
|
|
367
|
+
});
|
|
368
|
+
}
|
|
369
|
+
const baseSha = mrData.diff_refs.base_sha;
|
|
370
|
+
const headSha = mrData.diff_refs.head_sha;
|
|
371
|
+
this.logger.debug('Processing diffs', {
|
|
372
|
+
...context,
|
|
373
|
+
baseSha: baseSha.substring(0, 8),
|
|
374
|
+
headSha: headSha.substring(0, 8),
|
|
375
|
+
});
|
|
376
|
+
// Validate commits exist (Requirement 6.1)
|
|
377
|
+
await this.validateCommitExists(baseSha);
|
|
378
|
+
await this.validateCommitExists(headSha);
|
|
379
|
+
const git = simpleGit(this.repoPath);
|
|
380
|
+
// Get file changes with retry logic (Requirement 3.2)
|
|
381
|
+
const nameStatus = await ErrorHandler.withRetry(async () => {
|
|
382
|
+
return await git.raw([
|
|
383
|
+
"diff",
|
|
384
|
+
"--name-status",
|
|
385
|
+
`${baseSha}..${headSha}`,
|
|
386
|
+
]);
|
|
387
|
+
}, {
|
|
388
|
+
maxRetries: this.config.get().maxRetries,
|
|
389
|
+
delayMs: this.config.get().retryDelayMs,
|
|
390
|
+
});
|
|
391
|
+
// Parse file changes with special character handling (Requirement 6.3)
|
|
392
|
+
const files = this.parseGitNameStatus(nameStatus);
|
|
393
|
+
this.logger.debug('Files changed', {
|
|
394
|
+
...context,
|
|
395
|
+
fileCount: files.length,
|
|
396
|
+
});
|
|
397
|
+
// Fetch diffs in parallel (Requirement 4.1)
|
|
398
|
+
const diffs = await Promise.all(files.map(async ({ status, path }) => {
|
|
399
|
+
return await this.getDiffForFile(git, baseSha, headSha, status, path, context);
|
|
400
|
+
}));
|
|
401
|
+
const withDiff = diffs.filter((d) => d.diff).length;
|
|
402
|
+
const addedOrDeletedFiles = diffs.filter((d) => d.new_file || d.deleted_file).length;
|
|
403
|
+
const modifiedFiles = diffs.length - addedOrDeletedFiles;
|
|
404
|
+
this.logger.info('Diffs retrieved', {
|
|
405
|
+
...context,
|
|
406
|
+
totalFiles: diffs.length,
|
|
407
|
+
filesWithDiff: withDiff,
|
|
408
|
+
addedOrDeleted: addedOrDeletedFiles,
|
|
409
|
+
modified: modifiedFiles,
|
|
410
|
+
});
|
|
411
|
+
// Validate we got meaningful results (Requirement 6.4)
|
|
412
|
+
// Only throw error if we have modified files but no diff content
|
|
413
|
+
// Added/deleted files legitimately have no diff content
|
|
414
|
+
if (withDiff === 0 && modifiedFiles > 0) {
|
|
415
|
+
const shortBaseSha = baseSha.substring(0, 8);
|
|
416
|
+
const shortHeadSha = headSha.substring(0, 8);
|
|
417
|
+
throw ErrorHandler.gitOperationError('No diff content was generated for modified files. This may indicate a repository state issue or that the commits are identical.', {
|
|
418
|
+
...context,
|
|
419
|
+
baseSha: shortBaseSha,
|
|
420
|
+
headSha: shortHeadSha,
|
|
421
|
+
fileCount: diffs.length,
|
|
422
|
+
modifiedFiles,
|
|
423
|
+
}, new Error('No diff content generated'));
|
|
424
|
+
}
|
|
425
|
+
endTimer();
|
|
426
|
+
return diffs;
|
|
427
|
+
}
|
|
428
|
+
catch (error) {
|
|
429
|
+
endTimer();
|
|
430
|
+
// Provide clear error context (Requirement 6.4)
|
|
431
|
+
if (error instanceof Error && error.message.includes('MCP')) {
|
|
432
|
+
// Already an MCPError, just rethrow
|
|
433
|
+
throw error;
|
|
434
|
+
}
|
|
435
|
+
throw ErrorHandler.gitOperationError('Failed to get diffs from local git repository', context, error instanceof Error ? error : new Error(String(error)));
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
/**
|
|
439
|
+
* Parses git name-status output with special character handling (Requirement 6.3)
|
|
440
|
+
*/
|
|
441
|
+
parseGitNameStatus(nameStatus) {
|
|
442
|
+
return nameStatus
|
|
443
|
+
.trim()
|
|
444
|
+
.split("\n")
|
|
445
|
+
.filter((line) => line)
|
|
446
|
+
.map((line) => {
|
|
447
|
+
// Handle tabs in file paths by splitting only on the first tab
|
|
448
|
+
const [status, ...pathParts] = line.split("\t");
|
|
449
|
+
// Rejoin path parts to handle paths with tabs or special characters
|
|
450
|
+
const path = pathParts.join("\t");
|
|
451
|
+
return { status, path };
|
|
452
|
+
});
|
|
453
|
+
}
|
|
454
|
+
/**
|
|
455
|
+
* Gets diff for a single file with error handling
|
|
456
|
+
*/
|
|
457
|
+
async getDiffForFile(git, baseSha, headSha, status, path, context) {
|
|
458
|
+
const oldPath = status !== "A" ? path : null;
|
|
459
|
+
const newPath = status !== "D" ? path : null;
|
|
460
|
+
let diff = "";
|
|
461
|
+
if (oldPath) {
|
|
462
|
+
try {
|
|
463
|
+
// Wrap git operation with retry logic
|
|
464
|
+
const rawDiff = await ErrorHandler.withRetry(async () => {
|
|
465
|
+
return await git.raw([
|
|
466
|
+
"diff",
|
|
467
|
+
`${baseSha}..${headSha}`,
|
|
468
|
+
"--",
|
|
469
|
+
oldPath,
|
|
470
|
+
]);
|
|
471
|
+
}, {
|
|
472
|
+
maxRetries: this.config.get().maxRetries,
|
|
473
|
+
delayMs: this.config.get().retryDelayMs,
|
|
474
|
+
});
|
|
475
|
+
// Strip git headers to match GitLab API format (only keep hunks starting with @@)
|
|
476
|
+
const lines = rawDiff.split("\n");
|
|
477
|
+
const firstHunkIndex = lines.findIndex((line) => line.startsWith("@@"));
|
|
478
|
+
diff =
|
|
479
|
+
firstHunkIndex >= 0
|
|
480
|
+
? lines.slice(firstHunkIndex).join("\n")
|
|
481
|
+
: rawDiff;
|
|
482
|
+
}
|
|
483
|
+
catch (e) {
|
|
484
|
+
// Log but don't fail - graceful degradation (Requirement 3.5)
|
|
485
|
+
this.logger.warn('Failed to get diff for file', {
|
|
486
|
+
...context,
|
|
487
|
+
path: oldPath,
|
|
488
|
+
error: e instanceof Error ? e.message : String(e),
|
|
489
|
+
});
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
return {
|
|
493
|
+
new_path: newPath || '',
|
|
494
|
+
old_path: oldPath || '',
|
|
495
|
+
a_mode: '',
|
|
496
|
+
b_mode: '',
|
|
497
|
+
deleted_file: status === "D",
|
|
498
|
+
new_file: status === "A",
|
|
499
|
+
renamed_file: false,
|
|
500
|
+
diff,
|
|
501
|
+
};
|
|
502
|
+
}
|
|
503
|
+
/**
|
|
504
|
+
* Get raw file content from local repository
|
|
505
|
+
*
|
|
506
|
+
* Tries git show first, falls back to filesystem read if that fails.
|
|
507
|
+
*
|
|
508
|
+
* @param project - The project ID or path (used for logging)
|
|
509
|
+
* @param branch - The branch name
|
|
510
|
+
* @param path - The file path within the repository
|
|
511
|
+
* @returns Promise resolving to file content or null if not found
|
|
512
|
+
* @throws {MCPError} If file is not found in git or filesystem
|
|
513
|
+
*/
|
|
514
|
+
async getRawFile(project, branch, path) {
|
|
515
|
+
const context = { project, branch, path, repoPath: this.repoPath, dataSource: 'LocalGit' };
|
|
516
|
+
try {
|
|
517
|
+
const git = simpleGit(this.repoPath);
|
|
518
|
+
// Try git show first with retry logic
|
|
519
|
+
const content = await ErrorHandler.withRetry(async () => {
|
|
520
|
+
return await git.show([`origin/${branch}:${path}`]);
|
|
521
|
+
}, {
|
|
522
|
+
maxRetries: this.config.get().maxRetries,
|
|
523
|
+
delayMs: this.config.get().retryDelayMs,
|
|
524
|
+
});
|
|
525
|
+
this.logger.debug('File retrieved from git', context);
|
|
526
|
+
return content;
|
|
527
|
+
}
|
|
528
|
+
catch (error) {
|
|
529
|
+
// Fallback to filesystem read
|
|
530
|
+
this.logger.debug('Git show failed, trying filesystem', {
|
|
531
|
+
...context,
|
|
532
|
+
error: error instanceof Error ? error.message : String(error),
|
|
533
|
+
});
|
|
534
|
+
try {
|
|
535
|
+
const filePath = join(this.repoPath, path);
|
|
536
|
+
const content = readFileSync(filePath, "utf-8");
|
|
537
|
+
this.logger.debug('File retrieved from filesystem', { ...context, filePath });
|
|
538
|
+
return content;
|
|
539
|
+
}
|
|
540
|
+
catch (fsError) {
|
|
541
|
+
const gitErrorMsg = error instanceof Error ? error.message : String(error);
|
|
542
|
+
const fsErrorMsg = fsError instanceof Error ? fsError.message : String(fsError);
|
|
543
|
+
throw ErrorHandler.notFoundError(`File not found in git or filesystem: ${path}`, {
|
|
544
|
+
...context,
|
|
545
|
+
gitError: gitErrorMsg,
|
|
546
|
+
fsError: fsErrorMsg,
|
|
547
|
+
});
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
/**
|
|
552
|
+
* Get and parse a JSON file from local repository
|
|
553
|
+
*
|
|
554
|
+
* @param project - The project ID or path
|
|
555
|
+
* @param branch - The branch name
|
|
556
|
+
* @param path - The file path within the repository
|
|
557
|
+
* @returns Promise resolving to parsed JSON object or null if not found
|
|
558
|
+
* @throws {MCPError} If the file cannot be parsed as JSON
|
|
559
|
+
*/
|
|
560
|
+
async getJsonFile(project, branch, path) {
|
|
561
|
+
const context = { project, branch, path, dataSource: 'LocalGit' };
|
|
562
|
+
try {
|
|
563
|
+
const content = await this.getRawFile(project, branch, path);
|
|
564
|
+
if (!content)
|
|
565
|
+
return null;
|
|
566
|
+
return JSON.parse(content);
|
|
567
|
+
}
|
|
568
|
+
catch (error) {
|
|
569
|
+
if (error instanceof Error && error.message.includes('MCP')) {
|
|
570
|
+
throw error;
|
|
571
|
+
}
|
|
572
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
573
|
+
throw ErrorHandler.validationError(`Failed to parse JSON file: ${path}`, {
|
|
574
|
+
...context,
|
|
575
|
+
error: errorMsg,
|
|
576
|
+
});
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
//# sourceMappingURL=local-git-data-source.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local-git-data-source.js","sourceRoot":"","sources":["../../src/datasources/local-git-data-source.ts"],"names":[],"mappings":"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"}
|