@andrebuzeli/git-mcp 5.0.5 → 5.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (215) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +143 -89
  3. package/dist/config.d.ts +72 -71
  4. package/dist/config.d.ts.map +1 -1
  5. package/dist/config.js +226 -139
  6. package/dist/config.js.map +1 -1
  7. package/dist/index.d.ts +15 -17
  8. package/dist/index.d.ts.map +1 -1
  9. package/dist/index.js +133 -128
  10. package/dist/index.js.map +1 -1
  11. package/dist/providers/base-provider.d.ts +42 -153
  12. package/dist/providers/base-provider.d.ts.map +1 -1
  13. package/dist/providers/base-provider.js +42 -302
  14. package/dist/providers/base-provider.js.map +1 -1
  15. package/dist/providers/gitea-provider.d.ts +67 -118
  16. package/dist/providers/gitea-provider.d.ts.map +1 -1
  17. package/dist/providers/gitea-provider.js +487 -1161
  18. package/dist/providers/gitea-provider.js.map +1 -1
  19. package/dist/providers/github-provider.d.ts +70 -81
  20. package/dist/providers/github-provider.d.ts.map +1 -1
  21. package/dist/providers/github-provider.js +641 -278
  22. package/dist/providers/github-provider.js.map +1 -1
  23. package/dist/providers/index.d.ts +9 -9
  24. package/dist/providers/index.d.ts.map +1 -1
  25. package/dist/providers/index.js +13 -19
  26. package/dist/providers/index.js.map +1 -1
  27. package/dist/providers/provider-factory.d.ts +29 -59
  28. package/dist/providers/provider-factory.d.ts.map +1 -1
  29. package/dist/providers/provider-factory.js +134 -265
  30. package/dist/providers/provider-factory.js.map +1 -1
  31. package/dist/providers/provider-operation-handler.d.ts +93 -0
  32. package/dist/providers/provider-operation-handler.d.ts.map +1 -0
  33. package/dist/providers/provider-operation-handler.js +280 -0
  34. package/dist/providers/provider-operation-handler.js.map +1 -0
  35. package/dist/providers/types.d.ts +201 -355
  36. package/dist/providers/types.d.ts.map +1 -1
  37. package/dist/providers/types.js +3 -2
  38. package/dist/providers/types.js.map +1 -1
  39. package/dist/server.d.ts +34 -8
  40. package/dist/server.d.ts.map +1 -1
  41. package/dist/server.js +436 -494
  42. package/dist/server.js.map +1 -1
  43. package/dist/tools/git-analytics.d.ts +239 -16
  44. package/dist/tools/git-analytics.d.ts.map +1 -1
  45. package/dist/tools/git-analytics.js +737 -25
  46. package/dist/tools/git-analytics.js.map +1 -1
  47. package/dist/tools/git-archive.d.ts +109 -15
  48. package/dist/tools/git-archive.d.ts.map +1 -1
  49. package/dist/tools/git-archive.js +462 -10
  50. package/dist/tools/git-archive.js.map +1 -1
  51. package/dist/tools/git-backup.d.ts +101 -15
  52. package/dist/tools/git-backup.d.ts.map +1 -1
  53. package/dist/tools/git-backup.js +410 -10
  54. package/dist/tools/git-backup.js.map +1 -1
  55. package/dist/tools/git-branches.d.ts +141 -15
  56. package/dist/tools/git-branches.d.ts.map +1 -1
  57. package/dist/tools/git-branches.js +466 -11
  58. package/dist/tools/git-branches.js.map +1 -1
  59. package/dist/tools/git-config.d.ts +115 -15
  60. package/dist/tools/git-config.d.ts.map +1 -1
  61. package/dist/tools/git-config.js +446 -11
  62. package/dist/tools/git-config.js.map +1 -1
  63. package/dist/tools/git-files.d.ts +179 -59
  64. package/dist/tools/git-files.d.ts.map +1 -1
  65. package/dist/tools/git-files.js +682 -222
  66. package/dist/tools/git-files.js.map +1 -1
  67. package/dist/tools/git-issues.d.ts +158 -15
  68. package/dist/tools/git-issues.d.ts.map +1 -1
  69. package/dist/tools/git-issues.js +323 -11
  70. package/dist/tools/git-issues.js.map +1 -1
  71. package/dist/tools/git-monitor.d.ts +149 -14
  72. package/dist/tools/git-monitor.d.ts.map +1 -1
  73. package/dist/tools/git-monitor.js +528 -11
  74. package/dist/tools/git-monitor.js.map +1 -1
  75. package/dist/tools/git-packages.d.ts +163 -15
  76. package/dist/tools/git-packages.d.ts.map +1 -1
  77. package/dist/tools/git-packages.js +526 -11
  78. package/dist/tools/git-packages.js.map +1 -1
  79. package/dist/tools/git-pulls.d.ts +174 -15
  80. package/dist/tools/git-pulls.d.ts.map +1 -1
  81. package/dist/tools/git-pulls.js +352 -11
  82. package/dist/tools/git-pulls.js.map +1 -1
  83. package/dist/tools/git-release.d.ts +167 -15
  84. package/dist/tools/git-release.d.ts.map +1 -1
  85. package/dist/tools/git-release.js +465 -11
  86. package/dist/tools/git-release.js.map +1 -1
  87. package/dist/tools/git-remote.d.ts +124 -15
  88. package/dist/tools/git-remote.d.ts.map +1 -1
  89. package/dist/tools/git-remote.js +539 -11
  90. package/dist/tools/git-remote.js.map +1 -1
  91. package/dist/tools/git-reset.d.ts +100 -15
  92. package/dist/tools/git-reset.d.ts.map +1 -1
  93. package/dist/tools/git-reset.js +409 -11
  94. package/dist/tools/git-reset.js.map +1 -1
  95. package/dist/tools/git-stash.d.ts +120 -15
  96. package/dist/tools/git-stash.d.ts.map +1 -1
  97. package/dist/tools/git-stash.js +503 -11
  98. package/dist/tools/git-stash.js.map +1 -1
  99. package/dist/tools/git-sync.d.ts +160 -16
  100. package/dist/tools/git-sync.d.ts.map +1 -1
  101. package/dist/tools/git-sync.js +462 -113
  102. package/dist/tools/git-sync.js.map +1 -1
  103. package/dist/tools/git-tags.d.ts +142 -15
  104. package/dist/tools/git-tags.d.ts.map +1 -1
  105. package/dist/tools/git-tags.js +471 -11
  106. package/dist/tools/git-tags.js.map +1 -1
  107. package/dist/tools/git-workflow.d.ts +151 -80
  108. package/dist/tools/git-workflow.d.ts.map +1 -1
  109. package/dist/tools/git-workflow.js +407 -912
  110. package/dist/tools/git-workflow.js.map +1 -1
  111. package/dist/utils/credential-manager.d.ts +119 -0
  112. package/dist/utils/credential-manager.d.ts.map +1 -0
  113. package/dist/utils/credential-manager.js +450 -0
  114. package/dist/utils/credential-manager.js.map +1 -0
  115. package/dist/utils/git-command-executor.d.ts +326 -0
  116. package/dist/utils/git-command-executor.d.ts.map +1 -0
  117. package/dist/utils/git-command-executor.js +877 -0
  118. package/dist/utils/git-command-executor.js.map +1 -0
  119. package/dist/utils/logger.d.ts +143 -0
  120. package/dist/utils/logger.d.ts.map +1 -0
  121. package/dist/utils/logger.js +473 -0
  122. package/dist/utils/logger.js.map +1 -0
  123. package/dist/utils/operation-error-handler.d.ts +54 -41
  124. package/dist/utils/operation-error-handler.d.ts.map +1 -1
  125. package/dist/utils/operation-error-handler.js +211 -227
  126. package/dist/utils/operation-error-handler.js.map +1 -1
  127. package/dist/utils/parameter-validator.d.ts +41 -0
  128. package/dist/utils/parameter-validator.d.ts.map +1 -0
  129. package/dist/utils/parameter-validator.js +464 -0
  130. package/dist/utils/parameter-validator.js.map +1 -0
  131. package/dist/utils/repository-detector.d.ts +128 -0
  132. package/dist/utils/repository-detector.d.ts.map +1 -0
  133. package/dist/utils/repository-detector.js +422 -0
  134. package/dist/utils/repository-detector.js.map +1 -0
  135. package/dist/utils/response-formatter.d.ts +146 -0
  136. package/dist/utils/response-formatter.d.ts.map +1 -0
  137. package/dist/utils/response-formatter.js +378 -0
  138. package/dist/utils/response-formatter.js.map +1 -0
  139. package/dist/utils/retry.d.ts +12 -0
  140. package/dist/utils/retry.d.ts.map +1 -0
  141. package/dist/utils/retry.js +28 -0
  142. package/dist/utils/retry.js.map +1 -0
  143. package/dist/utils/terminal-controller.d.ts +73 -139
  144. package/dist/utils/terminal-controller.d.ts.map +1 -1
  145. package/dist/utils/terminal-controller.js +234 -459
  146. package/dist/utils/terminal-controller.js.map +1 -1
  147. package/package.json +79 -60
  148. package/dist/providers/error-handler.d.ts +0 -51
  149. package/dist/providers/error-handler.d.ts.map +0 -1
  150. package/dist/providers/error-handler.js +0 -176
  151. package/dist/providers/error-handler.js.map +0 -1
  152. package/dist/providers/github-provider-backup.d.ts +0 -81
  153. package/dist/providers/github-provider-backup.d.ts.map +0 -1
  154. package/dist/providers/github-provider-backup.js +0 -1179
  155. package/dist/providers/github-provider-backup.js.map +0 -1
  156. package/dist/providers/github-provider-complete.d.ts +0 -1
  157. package/dist/providers/github-provider-complete.d.ts.map +0 -1
  158. package/dist/providers/github-provider-complete.js +0 -2
  159. package/dist/providers/github-provider-complete.js.map +0 -1
  160. package/dist/tools/git-init.d.ts +0 -50
  161. package/dist/tools/git-init.d.ts.map +0 -1
  162. package/dist/tools/git-init.js +0 -258
  163. package/dist/tools/git-init.js.map +0 -1
  164. package/dist/tools/git-log.d.ts +0 -67
  165. package/dist/tools/git-log.d.ts.map +0 -1
  166. package/dist/tools/git-log.js +0 -320
  167. package/dist/tools/git-log.js.map +0 -1
  168. package/dist/tools/git-status.d.ts +0 -29
  169. package/dist/tools/git-status.d.ts.map +0 -1
  170. package/dist/tools/git-status.js +0 -182
  171. package/dist/tools/git-status.js.map +0 -1
  172. package/dist/tools/git-update.d.ts +0 -34
  173. package/dist/tools/git-update.d.ts.map +0 -1
  174. package/dist/tools/git-update.js +0 -191
  175. package/dist/tools/git-update.js.map +0 -1
  176. package/dist/utils/auto-detection.d.ts +0 -120
  177. package/dist/utils/auto-detection.d.ts.map +0 -1
  178. package/dist/utils/auto-detection.js +0 -259
  179. package/dist/utils/auto-detection.js.map +0 -1
  180. package/dist/utils/configuration-error-generator.d.ts +0 -41
  181. package/dist/utils/configuration-error-generator.d.ts.map +0 -1
  182. package/dist/utils/configuration-error-generator.js +0 -168
  183. package/dist/utils/configuration-error-generator.js.map +0 -1
  184. package/dist/utils/configuration-validator.d.ts +0 -67
  185. package/dist/utils/configuration-validator.d.ts.map +0 -1
  186. package/dist/utils/configuration-validator.js +0 -257
  187. package/dist/utils/configuration-validator.js.map +0 -1
  188. package/dist/utils/error-handler.d.ts +0 -107
  189. package/dist/utils/error-handler.d.ts.map +0 -1
  190. package/dist/utils/error-handler.js +0 -331
  191. package/dist/utils/error-handler.js.map +0 -1
  192. package/dist/utils/git-operations.d.ts +0 -200
  193. package/dist/utils/git-operations.d.ts.map +0 -1
  194. package/dist/utils/git-operations.js +0 -836
  195. package/dist/utils/git-operations.js.map +0 -1
  196. package/dist/utils/multi-provider-error-handler.d.ts +0 -75
  197. package/dist/utils/multi-provider-error-handler.d.ts.map +0 -1
  198. package/dist/utils/multi-provider-error-handler.js +0 -276
  199. package/dist/utils/multi-provider-error-handler.js.map +0 -1
  200. package/dist/utils/multi-provider-operation-handler.d.ts +0 -113
  201. package/dist/utils/multi-provider-operation-handler.d.ts.map +0 -1
  202. package/dist/utils/multi-provider-operation-handler.js +0 -303
  203. package/dist/utils/multi-provider-operation-handler.js.map +0 -1
  204. package/dist/utils/provider-operation-handler.d.ts +0 -80
  205. package/dist/utils/provider-operation-handler.d.ts.map +0 -1
  206. package/dist/utils/provider-operation-handler.js +0 -201
  207. package/dist/utils/provider-operation-handler.js.map +0 -1
  208. package/dist/utils/response-helper.d.ts +0 -57
  209. package/dist/utils/response-helper.d.ts.map +0 -1
  210. package/dist/utils/response-helper.js +0 -54
  211. package/dist/utils/response-helper.js.map +0 -1
  212. package/dist/utils/user-detection.d.ts +0 -25
  213. package/dist/utils/user-detection.d.ts.map +0 -1
  214. package/dist/utils/user-detection.js +0 -54
  215. package/dist/utils/user-detection.js.map +0 -1
@@ -0,0 +1,877 @@
1
+ "use strict";
2
+ /**
3
+ * Git Command Executor
4
+ *
5
+ * Specialized utility for executing Git commands with proper error handling,
6
+ * repository validation, and Git-specific operations.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.gitCommandExecutor = exports.GitCommandExecutor = void 0;
10
+ const terminal_controller_js_1 = require("./terminal-controller.js");
11
+ class GitCommandExecutor {
12
+ terminal;
13
+ constructor() {
14
+ this.terminal = new terminal_controller_js_1.TerminalController();
15
+ }
16
+ /**
17
+ * Execute Git command with enhanced error handling
18
+ */
19
+ async executeGitCommand(command, args = [], projectPath, options = {}) {
20
+ // Validate Git is available
21
+ const gitAvailable = await this.terminal.commandExists('git');
22
+ if (!gitAvailable) {
23
+ return {
24
+ success: false,
25
+ stdout: '',
26
+ stderr: 'Git command not found. Please install Git.',
27
+ exitCode: 127,
28
+ executionTime: 0,
29
+ command: `git ${command} ${args.join(' ')}`,
30
+ gitError: {
31
+ type: 'command_not_found',
32
+ suggestion: 'Install Git from https://git-scm.com/'
33
+ }
34
+ };
35
+ }
36
+ // Validate project path if provided
37
+ if (projectPath) {
38
+ const dirValidation = await this.terminal.validateDirectory(projectPath);
39
+ if (!dirValidation.exists) {
40
+ return {
41
+ success: false,
42
+ stdout: '',
43
+ stderr: `Directory does not exist: ${projectPath}`,
44
+ exitCode: 1,
45
+ executionTime: 0,
46
+ command: `git ${command} ${args.join(' ')}`,
47
+ gitError: {
48
+ type: 'not_a_repository',
49
+ suggestion: 'Ensure the project path exists and is accessible'
50
+ }
51
+ };
52
+ }
53
+ }
54
+ // Execute Git command
55
+ const result = await this.terminal.executeCommand('git', [command, ...args], {
56
+ cwd: projectPath,
57
+ timeout: options.timeout || 30000,
58
+ env: options.env
59
+ });
60
+ // Enhance result with Git-specific error analysis
61
+ const gitResult = {
62
+ ...result,
63
+ isGitRepository: await this.isGitRepository(projectPath),
64
+ gitError: this.analyzeGitError(result)
65
+ };
66
+ return gitResult;
67
+ }
68
+ /**
69
+ * Check if directory is a Git repository
70
+ */
71
+ async isGitRepository(projectPath) {
72
+ try {
73
+ const result = await this.terminal.executeCommand('git', ['rev-parse', '--git-dir'], { cwd: projectPath });
74
+ return result.success;
75
+ }
76
+ catch {
77
+ return false;
78
+ }
79
+ }
80
+ /**
81
+ * Initialize Git repository
82
+ */
83
+ async initRepository(projectPath, bare = false) {
84
+ const args = bare ? ['--bare'] : [];
85
+ return this.executeGitCommand('init', args, projectPath);
86
+ }
87
+ /**
88
+ * Get repository status
89
+ */
90
+ async getStatus(projectPath) {
91
+ const result = await this.executeGitCommand('status', ['--porcelain', '-b'], projectPath);
92
+ if (result.success) {
93
+ const parsedStatus = this.parseGitStatus(result.stdout);
94
+ return {
95
+ ...result,
96
+ parsedStatus
97
+ };
98
+ }
99
+ return result;
100
+ }
101
+ /**
102
+ * Add files to staging area
103
+ */
104
+ async addFiles(projectPath, files = ['.']) {
105
+ return this.executeGitCommand('add', files, projectPath);
106
+ }
107
+ /**
108
+ * Commit changes
109
+ */
110
+ async commit(projectPath, message, options = {}) {
111
+ const args = ['-m', message];
112
+ if (options.amend)
113
+ args.push('--amend');
114
+ if (options.signoff)
115
+ args.push('--signoff');
116
+ if (options.author)
117
+ args.push('--author', options.author);
118
+ return this.executeGitCommand('commit', args, projectPath);
119
+ }
120
+ /**
121
+ * Push changes to remote
122
+ */
123
+ async push(projectPath, remote = 'origin', branch, options = {}) {
124
+ const args = [remote];
125
+ if (branch)
126
+ args.push(branch);
127
+ if (options.force)
128
+ args.push('--force');
129
+ if (options.setUpstream)
130
+ args.push('--set-upstream');
131
+ return this.executeGitCommand('push', args, projectPath);
132
+ }
133
+ /**
134
+ * Pull changes from remote
135
+ */
136
+ async pull(projectPath, remote = 'origin', branch, options = {}) {
137
+ const args = [remote];
138
+ if (branch)
139
+ args.push(branch);
140
+ if (options.rebase)
141
+ args.push('--rebase');
142
+ if (options.force)
143
+ args.push('--force');
144
+ return this.executeGitCommand('pull', args, projectPath);
145
+ }
146
+ /**
147
+ * Fetch from remote
148
+ */
149
+ async fetch(projectPath, remote = 'origin', options = {}) {
150
+ const args = [remote];
151
+ if (options.all)
152
+ args.push('--all');
153
+ if (options.prune)
154
+ args.push('--prune');
155
+ return this.executeGitCommand('fetch', args, projectPath);
156
+ }
157
+ /**
158
+ * Get current branch name
159
+ */
160
+ async getCurrentBranch(projectPath) {
161
+ const result = await this.executeGitCommand('branch', ['--show-current'], projectPath);
162
+ return {
163
+ ...result,
164
+ branch: result.success ? result.stdout.trim() : undefined
165
+ };
166
+ }
167
+ /**
168
+ * Get remote URL
169
+ */
170
+ async getRemoteUrl(projectPath, remote = 'origin') {
171
+ const result = await this.executeGitCommand('remote', ['get-url', remote], projectPath);
172
+ return {
173
+ ...result,
174
+ url: result.success ? result.stdout.trim() : undefined
175
+ };
176
+ }
177
+ /**
178
+ * Clone repository
179
+ */
180
+ async cloneRepository(url, targetPath, options = {}) {
181
+ const args = [url, targetPath];
182
+ if (options.branch)
183
+ args.push('--branch', options.branch);
184
+ if (options.depth)
185
+ args.push('--depth', options.depth.toString());
186
+ if (options.recursive)
187
+ args.push('--recursive');
188
+ return this.executeGitCommand('clone', args);
189
+ }
190
+ /**
191
+ * Create and archive repository backup
192
+ */
193
+ async createBackup(projectPath, backupPath, format = 'tar') {
194
+ const extension = format === 'zip' ? 'zip' : 'tar.gz';
195
+ const outputFile = `${backupPath}.${extension}`;
196
+ const formatArg = format === 'zip' ? 'zip' : 'tar.gz';
197
+ return this.executeGitCommand('archive', ['--format', formatArg, '--output', outputFile, 'HEAD'], projectPath);
198
+ }
199
+ /**
200
+ * List branches
201
+ */
202
+ async listBranches(projectPath, options = {}) {
203
+ const args = [];
204
+ if (options.all)
205
+ args.push('-a');
206
+ if (options.remote)
207
+ args.push('-r');
208
+ const result = await this.executeGitCommand('branch', args, projectPath);
209
+ if (result.success) {
210
+ const lines = result.stdout.split('\n').filter(line => line.trim());
211
+ const branches = [];
212
+ const remoteBranches = [];
213
+ for (const line of lines) {
214
+ const cleanLine = line.replace(/^\*?\s+/, '').trim();
215
+ if (cleanLine.startsWith('remotes/')) {
216
+ remoteBranches.push(cleanLine.replace('remotes/', ''));
217
+ }
218
+ else if (cleanLine && !cleanLine.includes('->')) {
219
+ branches.push(cleanLine);
220
+ }
221
+ }
222
+ return {
223
+ ...result,
224
+ branches: options.remote ? undefined : branches,
225
+ remoteBranches: options.all || options.remote ? remoteBranches : undefined
226
+ };
227
+ }
228
+ return result;
229
+ }
230
+ /**
231
+ * Create branch
232
+ */
233
+ async createBranch(projectPath, branchName, sourceBranch) {
234
+ const args = [branchName];
235
+ if (sourceBranch)
236
+ args.push(sourceBranch);
237
+ return this.executeGitCommand('branch', args, projectPath);
238
+ }
239
+ /**
240
+ * Delete branch
241
+ */
242
+ async deleteBranch(projectPath, branchName, force = false) {
243
+ const args = [force ? '-D' : '-d', branchName];
244
+ return this.executeGitCommand('branch', args, projectPath);
245
+ }
246
+ /**
247
+ * Checkout branch
248
+ */
249
+ async checkoutBranch(projectPath, branchName, options = {}) {
250
+ const args = [branchName];
251
+ if (options.create)
252
+ args.unshift('-b');
253
+ if (options.force)
254
+ args.push('--force');
255
+ return this.executeGitCommand('checkout', args, projectPath);
256
+ }
257
+ /**
258
+ * Get branch information
259
+ */
260
+ async getBranchInfo(projectPath, branchName) {
261
+ // Check if branch exists
262
+ const listResult = await this.listBranches(projectPath, { all: true });
263
+ if (!listResult.success) {
264
+ return listResult;
265
+ }
266
+ const allBranches = [...(listResult.branches || []), ...(listResult.remoteBranches || [])];
267
+ const exists = allBranches.some(branch => branch === branchName || branch.endsWith(`/${branchName}`));
268
+ if (!exists) {
269
+ return {
270
+ success: true,
271
+ stdout: '',
272
+ stderr: '',
273
+ exitCode: 0,
274
+ executionTime: 0,
275
+ command: `git branch info ${branchName}`,
276
+ exists: false
277
+ };
278
+ }
279
+ // Get last commit
280
+ const logResult = await this.executeGitCommand('log', ['-1', '--format=%H %s', branchName], projectPath);
281
+ // Get upstream info
282
+ const upstreamResult = await this.executeGitCommand('rev-parse', ['--abbrev-ref', `${branchName}@{upstream}`], projectPath);
283
+ // Get ahead/behind info if upstream exists
284
+ let ahead = 0;
285
+ let behind = 0;
286
+ if (upstreamResult.success) {
287
+ const countResult = await this.executeGitCommand('rev-list', ['--left-right', '--count', `${branchName}...${upstreamResult.stdout.trim()}`], projectPath);
288
+ if (countResult.success) {
289
+ const counts = countResult.stdout.trim().split('\t');
290
+ ahead = parseInt(counts[0]) || 0;
291
+ behind = parseInt(counts[1]) || 0;
292
+ }
293
+ }
294
+ const isRemote = (listResult.remoteBranches || []).some(branch => branch === branchName || branch.endsWith(`/${branchName}`));
295
+ return {
296
+ success: true,
297
+ stdout: logResult.stdout,
298
+ stderr: '',
299
+ exitCode: 0,
300
+ executionTime: logResult.executionTime,
301
+ command: `git branch info ${branchName}`,
302
+ exists: true,
303
+ isRemote,
304
+ lastCommit: logResult.success ? logResult.stdout.trim() : undefined,
305
+ upstream: upstreamResult.success ? upstreamResult.stdout.trim() : undefined,
306
+ ahead,
307
+ behind
308
+ };
309
+ }
310
+ /**
311
+ * Get branch commits
312
+ */
313
+ async getBranchCommits(projectPath, branchName, limit = 10) {
314
+ const result = await this.executeGitCommand('log', ['-n', limit.toString(), '--format=%H|%s|%an|%ad', '--date=iso', branchName], projectPath);
315
+ if (result.success) {
316
+ const commits = result.stdout
317
+ .split('\n')
318
+ .filter(line => line.trim())
319
+ .map(line => {
320
+ const [hash, message, author, date] = line.split('|');
321
+ return { hash, message, author, date };
322
+ });
323
+ return {
324
+ ...result,
325
+ commits
326
+ };
327
+ }
328
+ return result;
329
+ }
330
+ /**
331
+ * Merge branch
332
+ */
333
+ async mergeBranch(projectPath, branchName, options = {}) {
334
+ const args = [branchName];
335
+ if (options.force)
336
+ args.push('--force');
337
+ if (options.noFf)
338
+ args.push('--no-ff');
339
+ if (options.squash)
340
+ args.push('--squash');
341
+ const result = await this.executeGitCommand('merge', args, projectPath);
342
+ if (result.success) {
343
+ // Get merge commit hash
344
+ const commitResult = await this.executeGitCommand('rev-parse', ['HEAD'], projectPath);
345
+ return {
346
+ ...result,
347
+ mergeCommit: commitResult.success ? commitResult.stdout.trim() : undefined,
348
+ conflicts: []
349
+ };
350
+ }
351
+ else {
352
+ // Check for conflicts
353
+ const statusResult = await this.getStatus(projectPath);
354
+ const conflicts = statusResult.parsedStatus?.conflicted || [];
355
+ return {
356
+ ...result,
357
+ conflicts
358
+ };
359
+ }
360
+ }
361
+ /**
362
+ * Compare branches
363
+ */
364
+ async compareBranches(projectPath, baseBranch, compareBranch) {
365
+ // Get ahead/behind count
366
+ const countResult = await this.executeGitCommand('rev-list', ['--left-right', '--count', `${baseBranch}...${compareBranch}`], projectPath);
367
+ let behind = 0;
368
+ let ahead = 0;
369
+ if (countResult.success) {
370
+ const counts = countResult.stdout.trim().split('\t');
371
+ behind = parseInt(counts[0]) || 0;
372
+ ahead = parseInt(counts[1]) || 0;
373
+ }
374
+ // Get commits
375
+ const commitsResult = await this.executeGitCommand('log', ['--format=%H|%s|%an|%ad', '--date=iso', `${baseBranch}..${compareBranch}`], projectPath);
376
+ const commits = commitsResult.success
377
+ ? commitsResult.stdout
378
+ .split('\n')
379
+ .filter(line => line.trim())
380
+ .map(line => {
381
+ const [hash, message, author, date] = line.split('|');
382
+ return { hash, message, author, date };
383
+ })
384
+ : [];
385
+ // Get file changes
386
+ const diffResult = await this.executeGitCommand('diff', ['--numstat', `${baseBranch}...${compareBranch}`], projectPath);
387
+ const files = [];
388
+ let totalInsertions = 0;
389
+ let totalDeletions = 0;
390
+ if (diffResult.success) {
391
+ const lines = diffResult.stdout.split('\n').filter(line => line.trim());
392
+ for (const line of lines) {
393
+ const parts = line.split('\t');
394
+ if (parts.length >= 3) {
395
+ const insertions = parseInt(parts[0]) || 0;
396
+ const deletions = parseInt(parts[1]) || 0;
397
+ const file = parts[2];
398
+ files.push({
399
+ file,
400
+ status: insertions > 0 && deletions > 0 ? 'modified' : insertions > 0 ? 'added' : 'deleted',
401
+ insertions,
402
+ deletions
403
+ });
404
+ totalInsertions += insertions;
405
+ totalDeletions += deletions;
406
+ }
407
+ }
408
+ }
409
+ return {
410
+ success: true,
411
+ stdout: `${ahead} commits ahead, ${behind} commits behind`,
412
+ stderr: '',
413
+ exitCode: 0,
414
+ executionTime: countResult.executionTime + commitsResult.executionTime + diffResult.executionTime,
415
+ command: `git compare ${baseBranch}...${compareBranch}`,
416
+ ahead,
417
+ behind,
418
+ commits,
419
+ files,
420
+ insertions: totalInsertions,
421
+ deletions: totalDeletions
422
+ };
423
+ }
424
+ /**
425
+ * List tags
426
+ */
427
+ async listTags(projectPath, options = {}) {
428
+ const args = ['tag'];
429
+ if (options.pattern)
430
+ args.push('-l', options.pattern);
431
+ if (options.sort)
432
+ args.push('--sort', options.sort);
433
+ const result = await this.executeGitCommand('tag', args.slice(1), projectPath);
434
+ if (result.success) {
435
+ const tags = result.stdout
436
+ .split('\n')
437
+ .map(line => line.trim())
438
+ .filter(line => line);
439
+ return {
440
+ ...result,
441
+ tags
442
+ };
443
+ }
444
+ return result;
445
+ }
446
+ /**
447
+ * Create tag
448
+ */
449
+ async createTag(projectPath, tagName, options = {}) {
450
+ const args = [tagName];
451
+ if (options.force)
452
+ args.unshift('-f');
453
+ if (options.annotated || options.message) {
454
+ args.unshift('-a');
455
+ if (options.message) {
456
+ args.push('-m', options.message);
457
+ }
458
+ }
459
+ if (options.commit)
460
+ args.push(options.commit);
461
+ return this.executeGitCommand('tag', args, projectPath);
462
+ }
463
+ /**
464
+ * Delete tag
465
+ */
466
+ async deleteTag(projectPath, tagName, options = {}) {
467
+ const args = ['-d', tagName];
468
+ if (options.force)
469
+ args[0] = '-D';
470
+ return this.executeGitCommand('tag', args, projectPath);
471
+ }
472
+ /**
473
+ * Delete remote tag
474
+ */
475
+ async deleteRemoteTag(projectPath, remote, tagName) {
476
+ return this.executeGitCommand('push', [remote, '--delete', tagName], projectPath);
477
+ }
478
+ /**
479
+ * Get tag information
480
+ */
481
+ async getTagInfo(projectPath, tagName) {
482
+ // Check if tag exists
483
+ const listResult = await this.listTags(projectPath);
484
+ if (!listResult.success) {
485
+ return listResult;
486
+ }
487
+ const exists = (listResult.tags || []).includes(tagName);
488
+ if (!exists) {
489
+ return {
490
+ success: true,
491
+ stdout: '',
492
+ stderr: '',
493
+ exitCode: 0,
494
+ executionTime: 0,
495
+ command: `git tag info ${tagName}`,
496
+ exists: false
497
+ };
498
+ }
499
+ // Get tag object type
500
+ const typeResult = await this.executeGitCommand('cat-file', ['-t', tagName], projectPath);
501
+ const isAnnotated = typeResult.success && typeResult.stdout.trim() === 'tag';
502
+ // Get commit hash
503
+ const commitResult = await this.executeGitCommand('rev-list', ['-n', '1', tagName], projectPath);
504
+ let message = '';
505
+ let tagger = '';
506
+ let date = '';
507
+ if (isAnnotated) {
508
+ // Get annotated tag information
509
+ const showResult = await this.executeGitCommand('show', ['-s', '--format=%B%n---TAGGER---%n%an%n---DATE---%n%ad', '--date=iso', tagName], projectPath);
510
+ if (showResult.success) {
511
+ const parts = showResult.stdout.split('---TAGGER---');
512
+ if (parts.length > 1) {
513
+ message = parts[0].trim();
514
+ const taggerParts = parts[1].split('---DATE---');
515
+ if (taggerParts.length > 1) {
516
+ tagger = taggerParts[0].trim();
517
+ date = taggerParts[1].trim();
518
+ }
519
+ }
520
+ }
521
+ }
522
+ return {
523
+ success: true,
524
+ stdout: `Tag: ${tagName}`,
525
+ stderr: '',
526
+ exitCode: 0,
527
+ executionTime: typeResult.executionTime + commitResult.executionTime,
528
+ command: `git tag info ${tagName}`,
529
+ exists: true,
530
+ type: isAnnotated ? 'annotated' : 'lightweight',
531
+ commit: commitResult.success ? commitResult.stdout.trim() : undefined,
532
+ message: message || undefined,
533
+ tagger: tagger || undefined,
534
+ date: date || undefined
535
+ };
536
+ }
537
+ /**
538
+ * Get commit information
539
+ */
540
+ async getCommitInfo(projectPath, commitHash) {
541
+ const result = await this.executeGitCommand('show', ['-s', '--format=%H|%an|%ad|%s', '--date=iso', commitHash], projectPath);
542
+ if (result.success) {
543
+ const [hash, author, date, message] = result.stdout.trim().split('|');
544
+ return {
545
+ ...result,
546
+ hash,
547
+ author,
548
+ date,
549
+ message
550
+ };
551
+ }
552
+ return result;
553
+ }
554
+ /**
555
+ * Get Git configuration value
556
+ */
557
+ async getConfig(projectPath, key, options = {}) {
558
+ const args = ['config'];
559
+ if (options.global)
560
+ args.push('--global');
561
+ if (options.local)
562
+ args.push('--local');
563
+ if (options.system)
564
+ args.push('--system');
565
+ args.push(key);
566
+ const result = await this.executeGitCommand('config', args.slice(1), projectPath);
567
+ return {
568
+ ...result,
569
+ value: result.success ? result.stdout.trim() : undefined
570
+ };
571
+ }
572
+ /**
573
+ * Set Git configuration value
574
+ */
575
+ async setConfig(projectPath, key, value, options = {}) {
576
+ const args = ['config'];
577
+ if (options.global)
578
+ args.push('--global');
579
+ if (options.local)
580
+ args.push('--local');
581
+ if (options.system)
582
+ args.push('--system');
583
+ args.push(key, value);
584
+ return this.executeGitCommand('config', args.slice(1), projectPath);
585
+ }
586
+ /**
587
+ * Unset Git configuration value
588
+ */
589
+ async unsetConfig(projectPath, key, options = {}) {
590
+ const args = ['config'];
591
+ if (options.global)
592
+ args.push('--global');
593
+ if (options.local)
594
+ args.push('--local');
595
+ if (options.system)
596
+ args.push('--system');
597
+ args.push('--unset', key);
598
+ return this.executeGitCommand('config', args.slice(1), projectPath);
599
+ }
600
+ /**
601
+ * List Git configuration
602
+ */
603
+ async listConfig(projectPath, options = {}) {
604
+ const args = ['config'];
605
+ if (options.global)
606
+ args.push('--global');
607
+ if (options.local)
608
+ args.push('--local');
609
+ if (options.system)
610
+ args.push('--system');
611
+ if (options.showOrigin)
612
+ args.push('--show-origin');
613
+ args.push('--list');
614
+ const result = await this.executeGitCommand('config', args.slice(1), projectPath);
615
+ if (result.success) {
616
+ const configs = [];
617
+ const lines = result.stdout.split('\n').filter(line => line.trim());
618
+ for (const line of lines) {
619
+ if (options.showOrigin) {
620
+ const match = line.match(/^([^\t]+)\t(.+?)=(.*)$/);
621
+ if (match) {
622
+ const [, origin, key, value] = match;
623
+ configs.push({ key, value, origin });
624
+ }
625
+ }
626
+ else {
627
+ const equalIndex = line.indexOf('=');
628
+ if (equalIndex > 0) {
629
+ const key = line.substring(0, equalIndex);
630
+ const value = line.substring(equalIndex + 1);
631
+ configs.push({ key, value });
632
+ }
633
+ }
634
+ }
635
+ return {
636
+ ...result,
637
+ configs
638
+ };
639
+ }
640
+ return result;
641
+ }
642
+ /**
643
+ * Edit Git configuration
644
+ */
645
+ async editConfig(projectPath, options = {}) {
646
+ const args = ['config'];
647
+ if (options.global)
648
+ args.push('--global');
649
+ if (options.local)
650
+ args.push('--local');
651
+ if (options.system)
652
+ args.push('--system');
653
+ args.push('--edit');
654
+ return this.executeGitCommand('config', args.slice(1), projectPath);
655
+ }
656
+ /**
657
+ * Show Git configuration with details
658
+ */
659
+ async showConfig(projectPath, key, options = {}) {
660
+ const args = ['config'];
661
+ if (options.global)
662
+ args.push('--global');
663
+ if (options.local)
664
+ args.push('--local');
665
+ if (options.system)
666
+ args.push('--system');
667
+ if (options.showOrigin)
668
+ args.push('--show-origin');
669
+ if (options.showScope)
670
+ args.push('--show-scope');
671
+ if (key) {
672
+ args.push(key);
673
+ }
674
+ else {
675
+ args.push('--list');
676
+ }
677
+ const result = await this.executeGitCommand('config', args.slice(1), projectPath);
678
+ if (result.success) {
679
+ const configs = [];
680
+ if (key) {
681
+ // Single key result
682
+ configs.push({
683
+ key,
684
+ value: result.stdout.trim(),
685
+ origin: options.showOrigin ? 'unknown' : undefined,
686
+ scope: options.showScope ? 'unknown' : undefined
687
+ });
688
+ }
689
+ else {
690
+ // List result
691
+ const lines = result.stdout.split('\n').filter(line => line.trim());
692
+ for (const line of lines) {
693
+ if (options.showOrigin && options.showScope) {
694
+ const match = line.match(/^([^\t]+)\t([^\t]+)\t(.+?)=(.*)$/);
695
+ if (match) {
696
+ const [, origin, scope, key, value] = match;
697
+ configs.push({ key, value, origin, scope });
698
+ }
699
+ }
700
+ else if (options.showOrigin) {
701
+ const match = line.match(/^([^\t]+)\t(.+?)=(.*)$/);
702
+ if (match) {
703
+ const [, origin, key, value] = match;
704
+ configs.push({ key, value, origin });
705
+ }
706
+ }
707
+ else if (options.showScope) {
708
+ const match = line.match(/^([^\t]+)\t(.+?)=(.*)$/);
709
+ if (match) {
710
+ const [, scope, key, value] = match;
711
+ configs.push({ key, value, scope });
712
+ }
713
+ }
714
+ else {
715
+ const equalIndex = line.indexOf('=');
716
+ if (equalIndex > 0) {
717
+ const key = line.substring(0, equalIndex);
718
+ const value = line.substring(equalIndex + 1);
719
+ configs.push({ key, value });
720
+ }
721
+ }
722
+ }
723
+ }
724
+ return {
725
+ ...result,
726
+ configs
727
+ };
728
+ }
729
+ return result;
730
+ }
731
+ /**
732
+ * Parse Git status output
733
+ */
734
+ parseGitStatus(statusOutput) {
735
+ const lines = statusOutput.split('\n').filter(line => line.trim());
736
+ const branchLine = lines[0];
737
+ // Parse branch info
738
+ let branch = 'main';
739
+ let ahead = 0;
740
+ let behind = 0;
741
+ if (branchLine.startsWith('## ')) {
742
+ const branchInfo = branchLine.substring(3);
743
+ const parts = branchInfo.split('...');
744
+ branch = parts[0];
745
+ if (parts[1]) {
746
+ const trackingInfo = parts[1];
747
+ const aheadMatch = trackingInfo.match(/ahead (\d+)/);
748
+ const behindMatch = trackingInfo.match(/behind (\d+)/);
749
+ if (aheadMatch)
750
+ ahead = parseInt(aheadMatch[1]);
751
+ if (behindMatch)
752
+ behind = parseInt(behindMatch[1]);
753
+ }
754
+ }
755
+ // Parse file status
756
+ const staged = [];
757
+ const unstaged = [];
758
+ const untracked = [];
759
+ const conflicted = [];
760
+ const modified = [];
761
+ const added = [];
762
+ for (let i = 1; i < lines.length; i++) {
763
+ const line = lines[i];
764
+ if (line.length < 3)
765
+ continue;
766
+ const indexStatus = line[0];
767
+ const workTreeStatus = line[1];
768
+ const fileName = line.substring(3);
769
+ if (indexStatus === 'U' || workTreeStatus === 'U' ||
770
+ (indexStatus === 'A' && workTreeStatus === 'A') ||
771
+ (indexStatus === 'D' && workTreeStatus === 'D')) {
772
+ conflicted.push(fileName);
773
+ }
774
+ else if (indexStatus !== ' ' && indexStatus !== '?') {
775
+ staged.push(fileName);
776
+ if (indexStatus === 'A') {
777
+ added.push(fileName);
778
+ }
779
+ else if (indexStatus === 'M') {
780
+ modified.push(fileName);
781
+ }
782
+ }
783
+ else if (workTreeStatus !== ' ' && workTreeStatus !== '?') {
784
+ unstaged.push(fileName);
785
+ if (workTreeStatus === 'M') {
786
+ modified.push(fileName);
787
+ }
788
+ }
789
+ else if (indexStatus === '?' && workTreeStatus === '?') {
790
+ untracked.push(fileName);
791
+ }
792
+ }
793
+ return {
794
+ branch,
795
+ ahead,
796
+ behind,
797
+ staged,
798
+ unstaged,
799
+ untracked,
800
+ conflicted,
801
+ modified,
802
+ added,
803
+ clean: staged.length === 0 && unstaged.length === 0 && untracked.length === 0
804
+ };
805
+ }
806
+ /**
807
+ * Reset repository to specific commit/state
808
+ */
809
+ async reset(projectPath, options) {
810
+ const args = [options.type];
811
+ // Add commit reference if specified
812
+ if (options.commit) {
813
+ args.push(options.commit);
814
+ }
815
+ // Add paths for mixed reset with specific files
816
+ if (options.type === 'mixed' && options.paths && options.paths.length > 0) {
817
+ args.push('--');
818
+ args.push(...options.paths);
819
+ }
820
+ // Add additional options
821
+ if (options.options) {
822
+ if (options.options.keepIndex)
823
+ args.push('--keep-index');
824
+ if (options.options.noRefresh)
825
+ args.push('--no-refresh');
826
+ if (options.options.quiet)
827
+ args.push('--quiet');
828
+ if (options.options.merge)
829
+ args.push('--merge');
830
+ if (options.options.keep)
831
+ args.push('--keep');
832
+ }
833
+ return await this.executeGitCommand('reset', args, projectPath);
834
+ }
835
+ /**
836
+ * Analyze Git error and provide suggestions
837
+ */
838
+ analyzeGitError(result) {
839
+ if (result.success)
840
+ return undefined;
841
+ const stderr = result.stderr.toLowerCase();
842
+ const stdout = result.stdout.toLowerCase();
843
+ const errorText = `${stderr} ${stdout}`;
844
+ if (errorText.includes('not a git repository')) {
845
+ return {
846
+ type: 'not_a_repository',
847
+ suggestion: 'Initialize a Git repository with "git init" or navigate to an existing repository'
848
+ };
849
+ }
850
+ if (errorText.includes('authentication failed') || errorText.includes('permission denied')) {
851
+ return {
852
+ type: 'authentication',
853
+ suggestion: 'Check your Git credentials and ensure you have access to the repository'
854
+ };
855
+ }
856
+ if (errorText.includes('network') || errorText.includes('connection') || errorText.includes('timeout')) {
857
+ return {
858
+ type: 'network',
859
+ suggestion: 'Check your internet connection and repository URL'
860
+ };
861
+ }
862
+ if (errorText.includes('merge conflict') || errorText.includes('conflict')) {
863
+ return {
864
+ type: 'merge_conflict',
865
+ suggestion: 'Resolve merge conflicts and commit the changes'
866
+ };
867
+ }
868
+ return {
869
+ type: 'unknown',
870
+ suggestion: 'Check the error message for more details'
871
+ };
872
+ }
873
+ }
874
+ exports.GitCommandExecutor = GitCommandExecutor;
875
+ // Export singleton instance
876
+ exports.gitCommandExecutor = new GitCommandExecutor();
877
+ //# sourceMappingURL=git-command-executor.js.map