@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.
- package/README.md +25 -0
- package/dist/config.d.ts +5 -131
- package/dist/config.js +28 -430
- package/dist/index.d.ts +1 -21
- package/dist/index.js +66 -144
- package/dist/providers/giteaProvider.d.ts +3 -0
- package/dist/providers/giteaProvider.js +12 -0
- package/dist/providers/githubProvider.d.ts +2 -0
- package/dist/providers/githubProvider.js +7 -0
- package/dist/providers/providerManager.d.ts +11 -0
- package/dist/providers/providerManager.js +48 -0
- package/dist/server.d.ts +6 -40
- package/dist/server.js +30 -700
- package/dist/tools/gitAnalytics.d.ts +29 -0
- package/dist/tools/gitAnalytics.js +72 -0
- package/dist/tools/gitArchive.d.ts +6 -0
- package/dist/tools/gitArchive.js +27 -0
- package/dist/tools/gitBackup.d.ts +10 -0
- package/dist/tools/gitBackup.js +44 -0
- package/dist/tools/gitBranches.d.ts +72 -0
- package/dist/tools/gitBranches.js +97 -0
- package/dist/tools/gitConfig.d.ts +34 -0
- package/dist/tools/gitConfig.js +73 -0
- package/dist/tools/gitFiles.d.ts +24 -0
- package/dist/tools/gitFiles.js +53 -0
- package/dist/tools/gitIssues.d.ts +21 -0
- package/dist/tools/gitIssues.js +193 -0
- package/dist/tools/gitMonitor.d.ts +51 -0
- package/dist/tools/gitMonitor.js +102 -0
- package/dist/tools/gitPackages.d.ts +6 -0
- package/dist/tools/gitPackages.js +28 -0
- package/dist/tools/gitPulls.d.ts +74 -0
- package/dist/tools/gitPulls.js +190 -0
- package/dist/tools/gitRelease.d.ts +34 -0
- package/dist/tools/gitRelease.js +99 -0
- package/dist/tools/gitRemote.d.ts +51 -0
- package/dist/tools/gitRemote.js +68 -0
- package/dist/tools/gitReset.d.ts +34 -0
- package/dist/tools/gitReset.js +64 -0
- package/dist/tools/gitStash.d.ts +41 -0
- package/dist/tools/gitStash.js +67 -0
- package/dist/tools/gitSync.d.ts +25 -0
- package/dist/tools/gitSync.js +51 -0
- package/dist/tools/gitTags.d.ts +30 -0
- package/dist/tools/gitTags.js +69 -0
- package/dist/tools/gitWorkflow.d.ts +69 -0
- package/dist/tools/gitWorkflow.js +129 -0
- package/dist/types.d.ts +10 -0
- package/dist/types.js +2 -0
- package/dist/utils/errors.d.ts +13 -0
- package/dist/utils/errors.js +22 -0
- package/dist/utils/safetyController.d.ts +1 -0
- package/dist/utils/safetyController.js +15 -0
- package/package.json +7 -2
- package/dist/config.d.ts.map +0 -1
- package/dist/config.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/providers/base-provider.d.ts +0 -66
- package/dist/providers/base-provider.d.ts.map +0 -1
- package/dist/providers/base-provider.js +0 -65
- package/dist/providers/base-provider.js.map +0 -1
- package/dist/providers/gitea-provider.d.ts +0 -79
- package/dist/providers/gitea-provider.d.ts.map +0 -1
- package/dist/providers/gitea-provider.js +0 -576
- package/dist/providers/gitea-provider.js.map +0 -1
- package/dist/providers/github-provider.d.ts +0 -74
- package/dist/providers/github-provider.d.ts.map +0 -1
- package/dist/providers/github-provider.js +0 -683
- package/dist/providers/github-provider.js.map +0 -1
- package/dist/providers/index.d.ts +0 -13
- package/dist/providers/index.d.ts.map +0 -1
- package/dist/providers/index.js +0 -35
- package/dist/providers/index.js.map +0 -1
- package/dist/providers/provider-factory.d.ts +0 -49
- package/dist/providers/provider-factory.d.ts.map +0 -1
- package/dist/providers/provider-factory.js +0 -193
- package/dist/providers/provider-factory.js.map +0 -1
- package/dist/providers/provider-operation-handler.d.ts +0 -115
- package/dist/providers/provider-operation-handler.d.ts.map +0 -1
- package/dist/providers/provider-operation-handler.js +0 -449
- package/dist/providers/provider-operation-handler.js.map +0 -1
- package/dist/providers/types.d.ts +0 -200
- package/dist/providers/types.d.ts.map +0 -1
- package/dist/providers/types.js +0 -8
- package/dist/providers/types.js.map +0 -1
- package/dist/server.d.ts.map +0 -1
- package/dist/server.js.map +0 -1
- package/dist/tools/git-analytics.d.ts +0 -237
- package/dist/tools/git-analytics.d.ts.map +0 -1
- package/dist/tools/git-analytics.js +0 -828
- package/dist/tools/git-analytics.js.map +0 -1
- package/dist/tools/git-archive.d.ts +0 -113
- package/dist/tools/git-archive.d.ts.map +0 -1
- package/dist/tools/git-archive.js +0 -466
- package/dist/tools/git-archive.js.map +0 -1
- package/dist/tools/git-auto-monitor.d.ts +0 -180
- package/dist/tools/git-auto-monitor.d.ts.map +0 -1
- package/dist/tools/git-auto-monitor.js +0 -522
- package/dist/tools/git-auto-monitor.js.map +0 -1
- package/dist/tools/git-backup.d.ts +0 -105
- package/dist/tools/git-backup.d.ts.map +0 -1
- package/dist/tools/git-backup.js +0 -414
- package/dist/tools/git-backup.js.map +0 -1
- package/dist/tools/git-branches.d.ts +0 -183
- package/dist/tools/git-branches.d.ts.map +0 -1
- package/dist/tools/git-branches.js +0 -507
- package/dist/tools/git-branches.js.map +0 -1
- package/dist/tools/git-config.d.ts +0 -119
- package/dist/tools/git-config.d.ts.map +0 -1
- package/dist/tools/git-config.js +0 -449
- package/dist/tools/git-config.js.map +0 -1
- package/dist/tools/git-files.d.ts +0 -150
- package/dist/tools/git-files.d.ts.map +0 -1
- package/dist/tools/git-files.js +0 -536
- package/dist/tools/git-files.js.map +0 -1
- package/dist/tools/git-history.d.ts +0 -253
- package/dist/tools/git-history.d.ts.map +0 -1
- package/dist/tools/git-history.js +0 -824
- package/dist/tools/git-history.js.map +0 -1
- package/dist/tools/git-issues.d.ts +0 -164
- package/dist/tools/git-issues.d.ts.map +0 -1
- package/dist/tools/git-issues.js +0 -349
- package/dist/tools/git-issues.js.map +0 -1
- package/dist/tools/git-monitor.d.ts +0 -154
- package/dist/tools/git-monitor.d.ts.map +0 -1
- package/dist/tools/git-monitor.js +0 -531
- package/dist/tools/git-monitor.js.map +0 -1
- package/dist/tools/git-packages.d.ts +0 -157
- package/dist/tools/git-packages.d.ts.map +0 -1
- package/dist/tools/git-packages.js +0 -534
- package/dist/tools/git-packages.js.map +0 -1
- package/dist/tools/git-pulls.d.ts +0 -180
- package/dist/tools/git-pulls.d.ts.map +0 -1
- package/dist/tools/git-pulls.js +0 -378
- package/dist/tools/git-pulls.js.map +0 -1
- package/dist/tools/git-release.d.ts +0 -161
- package/dist/tools/git-release.d.ts.map +0 -1
- package/dist/tools/git-release.js +0 -466
- package/dist/tools/git-release.js.map +0 -1
- package/dist/tools/git-remote.d.ts +0 -128
- package/dist/tools/git-remote.d.ts.map +0 -1
- package/dist/tools/git-remote.js +0 -542
- package/dist/tools/git-remote.js.map +0 -1
- package/dist/tools/git-reset.d.ts +0 -120
- package/dist/tools/git-reset.d.ts.map +0 -1
- package/dist/tools/git-reset.js +0 -479
- package/dist/tools/git-reset.js.map +0 -1
- package/dist/tools/git-stash.d.ts +0 -124
- package/dist/tools/git-stash.d.ts.map +0 -1
- package/dist/tools/git-stash.js +0 -506
- package/dist/tools/git-stash.js.map +0 -1
- package/dist/tools/git-sync.d.ts +0 -154
- package/dist/tools/git-sync.d.ts.map +0 -1
- package/dist/tools/git-sync.js +0 -479
- package/dist/tools/git-sync.js.map +0 -1
- package/dist/tools/git-tags.d.ts +0 -136
- package/dist/tools/git-tags.d.ts.map +0 -1
- package/dist/tools/git-tags.js +0 -470
- package/dist/tools/git-tags.js.map +0 -1
- package/dist/tools/git-update.d.ts +0 -224
- package/dist/tools/git-update.d.ts.map +0 -1
- package/dist/tools/git-update.js +0 -948
- package/dist/tools/git-update.js.map +0 -1
- package/dist/tools/git-workflow.d.ts +0 -189
- package/dist/tools/git-workflow.d.ts.map +0 -1
- package/dist/tools/git-workflow.js +0 -551
- package/dist/tools/git-workflow.js.map +0 -1
- package/dist/utils/credential-manager.d.ts +0 -119
- package/dist/utils/credential-manager.d.ts.map +0 -1
- package/dist/utils/credential-manager.js +0 -450
- package/dist/utils/credential-manager.js.map +0 -1
- package/dist/utils/data-merger.d.ts +0 -49
- package/dist/utils/data-merger.d.ts.map +0 -1
- package/dist/utils/data-merger.js +0 -233
- package/dist/utils/data-merger.js.map +0 -1
- package/dist/utils/git-command-executor.d.ts +0 -330
- package/dist/utils/git-command-executor.d.ts.map +0 -1
- package/dist/utils/git-command-executor.js +0 -901
- package/dist/utils/git-command-executor.js.map +0 -1
- package/dist/utils/logger.d.ts +0 -143
- package/dist/utils/logger.d.ts.map +0 -1
- package/dist/utils/logger.js +0 -473
- package/dist/utils/logger.js.map +0 -1
- package/dist/utils/operation-error-handler.d.ts +0 -97
- package/dist/utils/operation-error-handler.d.ts.map +0 -1
- package/dist/utils/operation-error-handler.js +0 -367
- package/dist/utils/operation-error-handler.js.map +0 -1
- package/dist/utils/parameter-validator.d.ts +0 -49
- package/dist/utils/parameter-validator.d.ts.map +0 -1
- package/dist/utils/parameter-validator.js +0 -647
- package/dist/utils/parameter-validator.js.map +0 -1
- package/dist/utils/repository-checker.d.ts +0 -46
- package/dist/utils/repository-checker.d.ts.map +0 -1
- package/dist/utils/repository-checker.js +0 -151
- package/dist/utils/repository-checker.js.map +0 -1
- package/dist/utils/repository-detector.d.ts +0 -128
- package/dist/utils/repository-detector.d.ts.map +0 -1
- package/dist/utils/repository-detector.js +0 -422
- package/dist/utils/repository-detector.js.map +0 -1
- package/dist/utils/repository-sync.d.ts +0 -67
- package/dist/utils/repository-sync.d.ts.map +0 -1
- package/dist/utils/repository-sync.js +0 -344
- package/dist/utils/repository-sync.js.map +0 -1
- package/dist/utils/response-formatter.d.ts +0 -146
- package/dist/utils/response-formatter.d.ts.map +0 -1
- package/dist/utils/response-formatter.js +0 -378
- package/dist/utils/response-formatter.js.map +0 -1
- package/dist/utils/retry.d.ts +0 -12
- package/dist/utils/retry.d.ts.map +0 -1
- package/dist/utils/retry.js +0 -28
- package/dist/utils/retry.js.map +0 -1
- package/dist/utils/safety-warnings.d.ts +0 -56
- package/dist/utils/safety-warnings.d.ts.map +0 -1
- package/dist/utils/safety-warnings.js +0 -330
- package/dist/utils/safety-warnings.js.map +0 -1
- package/dist/utils/terminal-controller.d.ts +0 -79
- package/dist/utils/terminal-controller.d.ts.map +0 -1
- package/dist/utils/terminal-controller.js +0 -291
- package/dist/utils/terminal-controller.js.map +0 -1
- package/dist/utils/user-friendly-formatter.d.ts +0 -45
- package/dist/utils/user-friendly-formatter.d.ts.map +0 -1
- package/dist/utils/user-friendly-formatter.js +0 -175
- 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
|