@andrebuzeli/git-mcp 5.5.0 → 5.5.2

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