-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathextension.js
226 lines (192 loc) · 7.82 KB
/
extension.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
const vscode = require("vscode");
const path = require("path");
const fs = require("fs");
const { execSync } = require("child_process");
const { getGitProjectName } = require("./utils");
const CANCEL = "退出操作";
function generateWorkTreeName(targetBranch) {
return `${targetBranch}-worktree-vscodePlugin`;
}
function workTreeFlows({ repoPath, worktreePath, targetBranch, sourceBranch }) {
vscode.window.withProgress(
{
location: vscode.ProgressLocation.Notification,
title: "Processing Worktree",
cancellable: false,
},
async (progress) => {
progress.report({ message: "Creating new worktree..." });
// 创建新的工作区
try {
execSync(`git -C "${repoPath}" worktree add "${worktreePath}" "${targetBranch}"`, { stdio: "inherit" });
} catch (error) {
vscode.window.showErrorMessage(
`创建新的工作区失败,请检查分支是否存在,或者${worktreePath}工作区已经创建过 ${error.message}`
);
return;
}
progress.report({ message: "merging branch..." });
try {
try {
execSync(`git -C "${worktreePath}" switch "${targetBranch}"`, { stdio: "inherit" });
execSync(`git -C "${worktreePath}" pull`, { stdio: "inherit" });
} catch (error) {
vscode.window.showErrorMessage(
`拉取${targetBranch}代码失败, 可能存在代码冲突,请手动处理。. ${error.message}`
);
throw error;
}
// 合并代码到指定分支
try {
execSync(`git -C "${worktreePath}" merge "${sourceBranch}"`, { stdio: "inherit" });
} catch (error) {
vscode.window.showErrorMessage(
`合并分支失败 ${sourceBranch} -> ${targetBranch}. 可能存在代码冲突,请手动处理。 ${error.message}`
);
throw error;
}
try {
execSync(`git -C "${worktreePath}" push -u origin "${targetBranch}"`, { stdio: "inherit" });
} catch (error) {
vscode.window.showErrorMessage(
`推送失败 ${targetBranch}。请检查是否有推送该分支的权限或者检查网络连接是否正常。 ${error.message}`
);
throw error;
}
clearWorkTree({ repoPath, worktreePath, targetBranch });
vscode.window.showInformationMessage(`合并分支 ${sourceBranch} -> ${targetBranch} 成功`);
} catch (error) {
clearWorkTree({ repoPath, worktreePath, targetBranch });
vscode.window.showErrorMessage(
`合并分支失败 ${sourceBranch} -> ${targetBranch}: ${error.message} ${error.stderr}`
);
return;
}
triggerWebhooks();
progress.report({ message: "merge process finished ..." });
}
);
function clearWorkTree({ repoPath, worktreePath, targetBranch }) {
const worktreeBranch = generateWorkTreeName(targetBranch);
const worktreeAbsolutePath = path.resolve(repoPath, worktreePath);
// 检查工作区路径是否存在
const worktreeExists = fs.existsSync(worktreeAbsolutePath);
if (worktreeExists) {
try {
// 删除工作区
execSync(`git -C "${repoPath}" worktree remove ${worktreeBranch} --force`, { stdio: "inherit" });
execSync(`rm -rf "${worktreePath}"`, { stdio: "inherit" });
} catch (error) {
vscode.window.showErrorMessage(`删除工作区失败: ${error.message}`);
}
}
}
function triggerWebhooks() {
const config = vscode.workspace.getConfiguration("gitMergeBranchTo");
const urlConfigs = config.get("deployConfig").urlConfig || [];
const branches = config.get("branches") || [];
if (!urlConfigs.length || !branches.length) {
return;
}
const envList = urlConfigs.map((item) => item.env);
vscode.window
.showQuickPick([CANCEL, ...envList], {
canPickMany: false,
placeHolder: "选择要触发webhook的环境",
})
.then(async (selectedEnv) => {
if (selectedEnv === CANCEL) {
return;
}
const projectName = await getGitProjectName();
if (!projectName) {
vscode.window.showErrorMessage("未找到当前项目名, 请确保当前项目目录存在git仓库内");
return;
}
const config = urlConfigs.find((urlConfig) => urlConfig.env === selectedEnv);
if (
!config ||
!config.serverWebhookMap ||
!config.serverWebhookMap[projectName] ||
!config.serverWebhookMap[projectName].hookUrl
) {
vscode.window.showErrorMessage(`未找到 ${projectName} 的配置信息`);
return;
}
const { hookUrl: webhookUrl, webUrl } = config.serverWebhookMap[projectName];
const feishuId = vscode.workspace.getConfiguration("gitMergeBranchTo").get("feishuId");
const branch = config.defaultBranch
const data = JSON.stringify({ feishuId: feishuId, branch });
try {
execSync(`curl --header "Content-Type: application/json" --request POST --data '${data}' ${webhookUrl}`, {
stdio: "inherit",
});
vscode.window
.showInformationMessage(
`触发 webhook 成功。${webUrl ? `[查看流水线](${webUrl})` : ""}`,
{ modal: false },
{ title: "Open in Browser", command: "vscode.open" }
)
.then((selection) => {
if (selection?.command === "vscode.open") {
vscode.env.openExternal(vscode.Uri.parse(webUrl));
}
});
} catch (error) {
vscode.window.showErrorMessage(`触发 webhook 失败: ${error.message}`);
}
});
}
}
function manageWorktrees() {
const config = vscode.workspace.getConfiguration("gitMergeBranchTo");
const branches = config.get("branches");
if (!branches || !branches.length) {
const sourceBranch = getCurrentBranchName();
const targetBranch = sourceBranch.replace("feature/", "release/");
process.chdir(vscode.workspace.rootPath);
const isExistRemoteTargetBranch = execSync(`git ls-remote --heads origin ${targetBranch}`).toString();
if (isExistRemoteTargetBranch) {
execFlow(targetBranch);
} else {
vscode.window.showErrorMessage("未找到配置的分支列表");
}
return;
}
vscode.window
.showQuickPick(branches, {
canPickMany: false,
placeHolder: "选择你要合并到哪个分支",
})
.then((targetBranch) => {
if (!targetBranch || targetBranch === CANCEL) return;
execFlow(targetBranch);
});
function getCurrentBranchName() {
const gitExtension = vscode.extensions.getExtension("vscode.git").exports;
const gitApi = gitExtension.getAPI(1);
const repository = gitApi.repositories.find((repo) => repo.rootUri.fsPath === vscode.workspace.rootPath);
if (!repository) {
throw new Error("当前仓库无法识别");
}
return repository.state.HEAD?.name;
}
function execFlow(targetBranch) {
const sourceBranch = getCurrentBranchName();
const repoPath = vscode.workspace.rootPath;
const worktreePath = path.join(repoPath, generateWorkTreeName(targetBranch));
workTreeFlows({ repoPath, worktreePath, targetBranch, sourceBranch });
}
}
exports.activate = function activate(context) {
let disposable = vscode.commands.registerCommand("gitMergeBranchTo.merge-branch-to", manageWorktrees);
context.subscriptions.push(disposable);
// Add status bar item
const statusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right, 100);
statusBarItem.command = "gitMergeBranchTo.merge-branch-to";
statusBarItem.text = "$(git-branch) 合并分支到";
statusBarItem.tooltip = "合并分支到指定分支";
statusBarItem.show();
context.subscriptions.push(statusBarItem);
};
exports.deactivate = function deactivate() {};