git-push-mcp 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,351 @@
1
+ const simpleGit = require('simple-git');
2
+
3
+ class GitOperator {
4
+ constructor(logger) {
5
+ this.logger = logger;
6
+ this.git = simpleGit();
7
+ }
8
+
9
+ /**
10
+ * 检查是否为Git仓库
11
+ */
12
+ async checkRepository() {
13
+ try {
14
+ await this.git.status();
15
+ return { isRepository: true };
16
+ } catch (error) {
17
+ return { isRepository: false, error: error.message };
18
+ }
19
+ }
20
+
21
+ /**
22
+ * 获取Git状态
23
+ */
24
+ async getStatus() {
25
+ try {
26
+ this.logger.info('获取Git状态', { service: 'git-push-mcp' });
27
+ const status = await this.git.status();
28
+
29
+ return {
30
+ success: true,
31
+ modified: status.modified,
32
+ created: status.created,
33
+ deleted: status.deleted,
34
+ staged: status.staged,
35
+ untracked: status.not_added,
36
+ conflicted: status.conflicted,
37
+ isClean: status.isClean(),
38
+ currentBranch: status.current,
39
+ tracking: status.tracking
40
+ };
41
+ } catch (error) {
42
+ this.logger.error('获取状态失败', {
43
+ error: error?.message || '未知错误',
44
+ stack: error?.stack,
45
+ service: 'git-push-mcp'
46
+ });
47
+ throw new Error(error?.message || '获取Git状态失败');
48
+ }
49
+ }
50
+
51
+ /**
52
+ * 添加文件到暂存区
53
+ */
54
+ async addFiles(files = '.') {
55
+ try {
56
+ this.logger.info(`添加文件到暂存区: ${files}`, { service: 'git-push-mcp' });
57
+
58
+ if (files === '.' || files === 'all') {
59
+ await this.git.add('.');
60
+ } else if (Array.isArray(files)) {
61
+ await this.git.add(files);
62
+ } else {
63
+ await this.git.add(files);
64
+ }
65
+
66
+ return { success: true };
67
+ } catch (error) {
68
+ this.logger.error('添加文件失败', {
69
+ error: error?.message || '未知错误',
70
+ files,
71
+ service: 'git-push-mcp'
72
+ });
73
+ throw new Error(error?.message || '添加文件失败');
74
+ }
75
+ }
76
+
77
+ /**
78
+ * 提交更改
79
+ */
80
+ async commit(message, options = {}) {
81
+ try {
82
+ this.logger.info(`提交更改: ${message}`);
83
+
84
+ const commitOptions = {
85
+ '--no-verify': options.noVerify || false
86
+ };
87
+
88
+ if (options.allowEmpty) {
89
+ commitOptions['--allow-empty'] = true;
90
+ }
91
+
92
+ const result = await this.git.commit(message, undefined, commitOptions);
93
+
94
+ return {
95
+ success: true,
96
+ data: {
97
+ commit: result.commit,
98
+ summary: result.summary
99
+ },
100
+ message: `提交成功: ${message}`
101
+ };
102
+ } catch (error) {
103
+ this.logger.error('提交失败:', error);
104
+ return {
105
+ success: false,
106
+ error: error.message
107
+ };
108
+ }
109
+ }
110
+
111
+ /**
112
+ * 推送到远程仓库
113
+ */
114
+ async push(options = {}) {
115
+ try {
116
+ this.logger.info('推送更改到远程仓库');
117
+
118
+ const pushOptions = [];
119
+ if (options.force) {
120
+ pushOptions.push('--force');
121
+ }
122
+
123
+ const result = await this.git.push(pushOptions);
124
+
125
+ return {
126
+ success: true,
127
+ data: result,
128
+ message: '推送成功'
129
+ };
130
+ } catch (error) {
131
+ this.logger.error('推送失败:', error);
132
+ return {
133
+ success: false,
134
+ error: error.message
135
+ };
136
+ }
137
+ }
138
+
139
+ /**
140
+ * 获取提交日志
141
+ */
142
+ async getLog(limit = 10) {
143
+ try {
144
+ this.logger.info(`获取最近${limit}条提交日志`);
145
+
146
+ const logs = await this.git.log({ maxCount: limit });
147
+
148
+ return {
149
+ success: true,
150
+ data: logs.all.map(commit => ({
151
+ hash: commit.hash,
152
+ date: commit.date,
153
+ message: commit.message,
154
+ author: commit.author_name
155
+ }))
156
+ };
157
+ } catch (error) {
158
+ this.logger.error('获取日志失败:', error);
159
+ return {
160
+ success: false,
161
+ error: error.message
162
+ };
163
+ }
164
+ }
165
+
166
+ /**
167
+ * 获取差异统计
168
+ */
169
+ async getDiff() {
170
+ try {
171
+ this.logger.info('获取差异统计');
172
+
173
+ const diff = await this.git.diff(['--stat']);
174
+
175
+ return {
176
+ success: true,
177
+ data: diff
178
+ };
179
+ } catch (error) {
180
+ this.logger.error('获取差异失败:', error);
181
+ return {
182
+ success: false,
183
+ error: error.message
184
+ };
185
+ }
186
+ }
187
+
188
+ /**
189
+ * 创建新分支
190
+ */
191
+ async createBranch(branchName) {
192
+ try {
193
+ this.logger.info(`创建分支: ${branchName}`);
194
+
195
+ await this.git.checkoutLocalBranch(branchName);
196
+
197
+ return {
198
+ success: true,
199
+ message: `分支创建成功: ${branchName}`
200
+ };
201
+ } catch (error) {
202
+ this.logger.error('创建分支失败:', error);
203
+ return {
204
+ success: false,
205
+ error: error.message
206
+ };
207
+ }
208
+ }
209
+
210
+ /**
211
+ * 切换分支
212
+ */
213
+ async checkoutBranch(branchName) {
214
+ try {
215
+ this.logger.info(`切换到分支: ${branchName}`);
216
+
217
+ await this.git.checkout(branchName);
218
+
219
+ return {
220
+ success: true,
221
+ message: `已切换到分支: ${branchName}`
222
+ };
223
+ } catch (error) {
224
+ this.logger.error('切换分支失败:', error);
225
+ return {
226
+ success: false,
227
+ error: error.message
228
+ };
229
+ }
230
+ }
231
+
232
+ /**
233
+ * 获取所有分支
234
+ */
235
+ async getBranches() {
236
+ try {
237
+ this.logger.info('获取分支列表');
238
+
239
+ const branches = await this.git.branch();
240
+
241
+ return {
242
+ success: true,
243
+ data: {
244
+ current: branches.current,
245
+ local: branches.all.filter(b => !b.startsWith('remotes/')),
246
+ remote: branches.all.filter(b => b.startsWith('remotes/'))
247
+ }
248
+ };
249
+ } catch (error) {
250
+ this.logger.error('获取分支失败:', error);
251
+ return {
252
+ success: false,
253
+ error: error.message
254
+ };
255
+ }
256
+ }
257
+
258
+ /**
259
+ * 撤销工作区更改
260
+ */
261
+ async resetWorkingDirectory(files = '.') {
262
+ try {
263
+ this.logger.info(`撤销工作区更改: ${files}`);
264
+
265
+ if (files === '.') {
266
+ await this.git.reset('hard');
267
+ } else {
268
+ await this.git.checkout(files);
269
+ }
270
+
271
+ return {
272
+ success: true,
273
+ message: '已撤销更改'
274
+ };
275
+ } catch (error) {
276
+ this.logger.error('撤销更改失败:', error);
277
+ return {
278
+ success: false,
279
+ error: error.message
280
+ };
281
+ }
282
+ }
283
+
284
+ /**
285
+ * 撤销暂存区更改
286
+ */
287
+ async unstageFiles(files = '.') {
288
+ try {
289
+ this.logger.info(`撤销暂存区更改: ${files}`);
290
+
291
+ if (files === '.') {
292
+ await this.git.reset();
293
+ } else {
294
+ await this.git.reset('HEAD', files);
295
+ }
296
+
297
+ return {
298
+ success: true,
299
+ message: '已撤销暂存'
300
+ };
301
+ } catch (error) {
302
+ this.logger.error('撤销暂存失败:', error);
303
+ return {
304
+ success: false,
305
+ error: error.message
306
+ };
307
+ }
308
+ }
309
+
310
+ /**
311
+ * 获取仓库根目录
312
+ */
313
+ async getRepoRoot() {
314
+ try {
315
+ const root = await this.git.revparse(['--show-toplevel']);
316
+ return {
317
+ success: true,
318
+ root: root.trim()
319
+ };
320
+ } catch (error) {
321
+ return {
322
+ success: false,
323
+ error: error.message
324
+ };
325
+ }
326
+ }
327
+
328
+ /**
329
+ * 执行自定义Git命令
330
+ */
331
+ async executeCustomCommand(command, args = []) {
332
+ try {
333
+ this.logger.info(`执行自定义命令: git ${command} ${args.join(' ')}`);
334
+
335
+ const result = await this.git.raw([command, ...args]);
336
+
337
+ return {
338
+ success: true,
339
+ data: result
340
+ };
341
+ } catch (error) {
342
+ this.logger.error('执行自定义命令失败:', error);
343
+ return {
344
+ success: false,
345
+ error: error.message
346
+ };
347
+ }
348
+ }
349
+ }
350
+
351
+ module.exports = { GitOperator };