初步给项目、飞行器、容器页面添加了git拉取功能
This commit is contained in:
@@ -24,7 +24,6 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.ConfigPanel = void 0;
|
||||
// src/panels/ConfigPanel.ts
|
||||
const vscode = __importStar(require("vscode"));
|
||||
const path = __importStar(require("path"));
|
||||
const ProjectView_1 = require("./views/ProjectView");
|
||||
@@ -60,6 +59,7 @@ class ConfigPanel {
|
||||
this.currentModuleFolderId = '';
|
||||
// 仓库配置
|
||||
this.repoConfigs = [];
|
||||
this.currentCloneScope = 'config';
|
||||
// 状态管理
|
||||
this.isWebviewDisposed = false;
|
||||
this.currentModuleFolderFileTree = [];
|
||||
@@ -93,9 +93,10 @@ class ConfigPanel {
|
||||
await this.loadRepoConfigs();
|
||||
}
|
||||
/**
|
||||
* 弹出仓库选择弹窗(仅用于“获取仓库 -> 获取分支”)
|
||||
* 按作用域弹出仓库选择弹窗(仅用于“获取仓库 -> 获取分支”)
|
||||
*/
|
||||
async openRepoSelect() {
|
||||
async openRepoSelectForScope(scope) {
|
||||
this.currentCloneScope = scope;
|
||||
await this.loadRepoConfigs();
|
||||
if (this.repoConfigs.length === 0) {
|
||||
vscode.window.showWarningMessage('尚未配置任何仓库,请先点击右上角 "仓库配置" 按钮编辑 dcsp-repos.json。');
|
||||
@@ -108,6 +109,12 @@ class ConfigPanel {
|
||||
repos: this.repoConfigs.map(r => ({ name: r.name }))
|
||||
});
|
||||
}
|
||||
/**
|
||||
* ConfigView 使用的默认版本(保持兼容)
|
||||
*/
|
||||
async openRepoSelect() {
|
||||
return this.openRepoSelectForScope('config');
|
||||
}
|
||||
/**
|
||||
* 弹出“上传代码”时的仓库 + 分支选择弹窗
|
||||
*/
|
||||
@@ -263,6 +270,9 @@ class ConfigPanel {
|
||||
// Git 仓库管理
|
||||
'openRepoConfig': () => this.openRepoConfig(),
|
||||
'openRepoSelect': () => this.openRepoSelect(),
|
||||
'openRepoSelectForProject': () => this.openRepoSelectForScope('project'),
|
||||
'openRepoSelectForAircraft': () => this.openRepoSelectForScope('aircraft'),
|
||||
'openRepoSelectForContainer': () => this.openRepoSelectForScope('container'),
|
||||
'repoSelectedForBranches': (data) => this.handleRepoSelectedForBranches(data.repoName),
|
||||
// Git 分支管理
|
||||
'fetchBranches': (data) => this.fetchBranches(data.url),
|
||||
@@ -587,7 +597,34 @@ class ConfigPanel {
|
||||
vscode.window.showErrorMessage(`获取分支失败: ${error}`);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 根据当前作用域,把选中的分支克隆到不同层级
|
||||
*/
|
||||
async cloneBranches(branches) {
|
||||
if (!this.currentRepoForBranches) {
|
||||
vscode.window.showErrorMessage('请先通过"获取仓库"选择一个仓库');
|
||||
return;
|
||||
}
|
||||
switch (this.currentCloneScope) {
|
||||
case 'project':
|
||||
await this.cloneBranchesToProjects(branches);
|
||||
break;
|
||||
case 'aircraft':
|
||||
await this.cloneBranchesToAircrafts(branches);
|
||||
break;
|
||||
case 'container':
|
||||
await this.cloneBranchesToContainers(branches);
|
||||
break;
|
||||
case 'config':
|
||||
default:
|
||||
await this.cloneBranchesToModuleFolders(branches);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 原有逻辑:在 ConfigView 中,把分支克隆为当前容器下的 git 模块文件夹
|
||||
*/
|
||||
async cloneBranchesToModuleFolders(branches) {
|
||||
if (!this.currentRepoForBranches) {
|
||||
vscode.window.showErrorMessage('请先通过"获取仓库"选择一个仓库');
|
||||
return;
|
||||
@@ -635,6 +672,206 @@ class ConfigPanel {
|
||||
vscode.window.showErrorMessage(`克隆分支失败: ${error}`);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* ProjectView 用:把分支克隆为完整项目
|
||||
* 每个分支会弹出一个路径输入框,克隆整个仓库到该路径,如果有 .dcsp-data.json 则自动加载为项目
|
||||
*/
|
||||
async cloneBranchesToProjects(branches) {
|
||||
if (!this.currentRepoForBranches) {
|
||||
vscode.window.showErrorMessage('请先通过"获取仓库"选择一个仓库');
|
||||
return;
|
||||
}
|
||||
const url = this.currentRepoForBranches.url;
|
||||
const tasks = [];
|
||||
for (const branch of branches) {
|
||||
const pathInput = await vscode.window.showInputBox({
|
||||
prompt: `请输入分支 "${branch}" 的项目存储路径(绝对路径,系统将自动创建该文件夹)`,
|
||||
placeHolder: `/path/to/your/project/${branch}`,
|
||||
validateInput: (value) => {
|
||||
if (!value)
|
||||
return '路径不能为空';
|
||||
return null;
|
||||
}
|
||||
});
|
||||
if (!pathInput) {
|
||||
vscode.window.showWarningMessage(`已取消分支 ${branch} 的克隆`);
|
||||
continue;
|
||||
}
|
||||
tasks.push({ branch, targetPath: pathInput });
|
||||
}
|
||||
if (tasks.length === 0) {
|
||||
return;
|
||||
}
|
||||
let successCount = 0;
|
||||
let failCount = 0;
|
||||
await vscode.window.withProgress({
|
||||
location: vscode.ProgressLocation.Notification,
|
||||
title: `正在克隆 ${tasks.length} 个项目分支`,
|
||||
cancellable: false
|
||||
}, async (progress) => {
|
||||
for (let i = 0; i < tasks.length; i++) {
|
||||
const { branch, targetPath } = tasks[i];
|
||||
progress.report({
|
||||
message: `克隆项目分支: ${branch} (${i + 1}/${tasks.length})`
|
||||
});
|
||||
try {
|
||||
await GitService_1.GitService.cloneRepository(url, targetPath, branch, undefined, this.currentRepoForBranches?.username, this.currentRepoForBranches?.token);
|
||||
// 克隆完成后,尝试加载项目数据(如果有 .dcsp-data.json)
|
||||
try {
|
||||
const projectId = await this.projectService.loadProjectData(targetPath);
|
||||
if (projectId) {
|
||||
this.currentProjectId = projectId;
|
||||
successCount++;
|
||||
}
|
||||
else {
|
||||
// 没有 dscp-data 也算成功克隆,只是不会自动出现在列表里
|
||||
successCount++;
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
console.warn('加载克隆项目数据失败:', err);
|
||||
successCount++;
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
console.error(`❌ 项目分支克隆失败: ${branch}`, error);
|
||||
failCount++;
|
||||
}
|
||||
}
|
||||
});
|
||||
await vscode.commands.executeCommand('workbench.files.action.refreshFilesExplorer');
|
||||
if (failCount === 0) {
|
||||
vscode.window.showInformationMessage(`成功克隆 ${successCount} 个项目分支`);
|
||||
}
|
||||
else {
|
||||
vscode.window.showWarningMessage(`项目克隆完成: ${successCount} 个成功, ${failCount} 个失败`);
|
||||
}
|
||||
this.currentView = 'projects';
|
||||
this.updateWebview();
|
||||
}
|
||||
/**
|
||||
* AircraftView 用:把分支克隆为当前项目下的飞行器
|
||||
* 目标路径:<projectPath>/<分支名>,克隆后自动解析容器/配置/模块,并写入 dscp-data.json
|
||||
*/
|
||||
async cloneBranchesToAircrafts(branches) {
|
||||
if (!this.currentRepoForBranches) {
|
||||
vscode.window.showErrorMessage('请先通过"获取仓库"选择一个仓库');
|
||||
return;
|
||||
}
|
||||
if (!this.currentProjectId) {
|
||||
vscode.window.showErrorMessage('请先选择项目');
|
||||
return;
|
||||
}
|
||||
const projectPath = this.projectService.getProjectPath(this.currentProjectId);
|
||||
if (!projectPath) {
|
||||
vscode.window.showErrorMessage('未找到项目路径');
|
||||
return;
|
||||
}
|
||||
const url = this.currentRepoForBranches.url;
|
||||
const username = this.currentRepoForBranches.username;
|
||||
const token = this.currentRepoForBranches.token;
|
||||
let successCount = 0;
|
||||
let failCount = 0;
|
||||
await vscode.window.withProgress({
|
||||
location: vscode.ProgressLocation.Notification,
|
||||
title: `正在克隆飞行器分支`,
|
||||
cancellable: false
|
||||
}, async (progress) => {
|
||||
for (let i = 0; i < branches.length; i++) {
|
||||
const branch = branches[i];
|
||||
const aircraftName = branch.trim();
|
||||
if (!aircraftName)
|
||||
continue;
|
||||
const localPath = path.join(projectPath, aircraftName);
|
||||
progress.report({
|
||||
message: `克隆飞行器分支: ${branch} (${i + 1}/${branches.length})`
|
||||
});
|
||||
try {
|
||||
await GitService_1.GitService.cloneRepository(url, localPath, branch, undefined, username, token);
|
||||
await this.projectService.importAircraftFromExistingFolder(this.currentProjectId, aircraftName);
|
||||
successCount++;
|
||||
}
|
||||
catch (error) {
|
||||
console.error(`❌ 飞行器分支克隆失败: ${branch}`, error);
|
||||
failCount++;
|
||||
}
|
||||
}
|
||||
});
|
||||
await this.saveCurrentProjectData();
|
||||
await vscode.commands.executeCommand('workbench.files.action.refreshFilesExplorer');
|
||||
if (failCount === 0) {
|
||||
vscode.window.showInformationMessage(`成功克隆 ${successCount} 个飞行器`);
|
||||
}
|
||||
else {
|
||||
vscode.window.showWarningMessage(`飞行器克隆完成: ${successCount} 个成功, ${failCount} 个失败`);
|
||||
}
|
||||
this.currentView = 'aircrafts';
|
||||
this.updateWebview();
|
||||
}
|
||||
/**
|
||||
* ContainerView 用:把分支克隆为当前飞行器下的容器
|
||||
* 目标路径:<projectPath>/<当前飞行器名>/<分支名>,克隆后自动解析配置/模块,并写入 dscp-data.json
|
||||
*/
|
||||
async cloneBranchesToContainers(branches) {
|
||||
if (!this.currentRepoForBranches) {
|
||||
vscode.window.showErrorMessage('请先通过"获取仓库"选择一个仓库');
|
||||
return;
|
||||
}
|
||||
if (!this.currentProjectId || !this.currentAircraftId) {
|
||||
vscode.window.showErrorMessage('请先选择项目和飞行器');
|
||||
return;
|
||||
}
|
||||
const projectPath = this.projectService.getProjectPath(this.currentProjectId);
|
||||
if (!projectPath) {
|
||||
vscode.window.showErrorMessage('未找到项目路径');
|
||||
return;
|
||||
}
|
||||
const aircraftName = this.getAircraftName();
|
||||
if (!aircraftName || aircraftName === '未知飞行器') {
|
||||
vscode.window.showErrorMessage('未找到当前飞行器名称');
|
||||
return;
|
||||
}
|
||||
const url = this.currentRepoForBranches.url;
|
||||
const username = this.currentRepoForBranches.username;
|
||||
const token = this.currentRepoForBranches.token;
|
||||
let successCount = 0;
|
||||
let failCount = 0;
|
||||
await vscode.window.withProgress({
|
||||
location: vscode.ProgressLocation.Notification,
|
||||
title: `正在克隆容器分支`,
|
||||
cancellable: false
|
||||
}, async (progress) => {
|
||||
for (let i = 0; i < branches.length; i++) {
|
||||
const branch = branches[i];
|
||||
const containerName = branch.trim();
|
||||
if (!containerName)
|
||||
continue;
|
||||
const localPath = path.join(projectPath, aircraftName, containerName);
|
||||
progress.report({
|
||||
message: `克隆容器分支: ${branch} (${i + 1}/${branches.length})`
|
||||
});
|
||||
try {
|
||||
await GitService_1.GitService.cloneRepository(url, localPath, branch, undefined, username, token);
|
||||
await this.projectService.importContainerFromExistingFolder(this.currentAircraftId, containerName);
|
||||
successCount++;
|
||||
}
|
||||
catch (error) {
|
||||
console.error(`❌ 容器分支克隆失败: ${branch}`, error);
|
||||
failCount++;
|
||||
}
|
||||
}
|
||||
});
|
||||
await this.saveCurrentProjectData();
|
||||
await vscode.commands.executeCommand('workbench.files.action.refreshFilesExplorer');
|
||||
if (failCount === 0) {
|
||||
vscode.window.showInformationMessage(`成功克隆 ${successCount} 个容器`);
|
||||
}
|
||||
else {
|
||||
vscode.window.showWarningMessage(`容器克隆完成: ${successCount} 个成功, ${failCount} 个失败`);
|
||||
}
|
||||
this.currentView = 'containers';
|
||||
this.updateWebview();
|
||||
}
|
||||
async addGitModuleFolder(url, displayName, folderName, branch, username, token) {
|
||||
try {
|
||||
if (!url || !url.startsWith('http')) {
|
||||
@@ -1197,6 +1434,9 @@ class ConfigPanel {
|
||||
// =============================================
|
||||
// Webview 更新方法
|
||||
// =============================================
|
||||
// =============================================
|
||||
// Webview 更新方法
|
||||
// =============================================
|
||||
updateWebview() {
|
||||
if (this.isWebviewDisposed) {
|
||||
console.log('⚠️ Webview 已被销毁,跳过更新');
|
||||
@@ -1225,7 +1465,10 @@ class ConfigPanel {
|
||||
const project = this.projectService.getProjects().find(p => p.id === this.currentProjectId);
|
||||
const currentAircraft = this.projectService.getAircraftsByProject(this.currentProjectId)
|
||||
.find(a => a.id === this.currentAircraftId);
|
||||
const projectContainers = this.projectService.getContainersByAircraft(this.currentAircraftId);
|
||||
// ✅ 只在 UI 层隐藏名为 .git 的容器
|
||||
const projectContainers = this.projectService
|
||||
.getContainersByAircraft(this.currentAircraftId)
|
||||
.filter(c => c.name !== '.git');
|
||||
return this.containerView.render({
|
||||
project: project,
|
||||
aircraft: currentAircraft,
|
||||
|
||||
Reference in New Issue
Block a user