0
0

卫星模块获取功能已实现,仅简单测试,未深度测试

This commit is contained in:
xubing
2025-12-02 16:30:53 +08:00
parent 07acf9f617
commit 3f512e8646
9 changed files with 475 additions and 297 deletions

View File

@@ -27,7 +27,6 @@ var __importDefault = (this && this.__importDefault) || 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 fs = __importStar(require("fs"));
@@ -72,7 +71,9 @@ class ConfigPanel {
this.moduleFolders = [];
this.currentModuleFolderFileTree = [];
this.projectPaths = new Map();
this.pendingUploadFolderId = null;
// 上传相关local 上传 / git 上传
this.pendingUploadFolderId = null; // local -> git
this.pendingGitUploadFolderId = null; // git -> repo更新或新分支
// 仓库配置
this.repoConfigs = [];
// 状态管理
@@ -99,7 +100,6 @@ class ConfigPanel {
// =============================================
generateUniqueId(prefix, existingItems) {
let idNumber = 1;
// 先找到当前最大的数字
const existingIds = existingItems.map(item => item.id);
const numberPattern = /\d+$/;
for (const id of existingIds) {
@@ -117,7 +117,6 @@ class ConfigPanel {
// 仓库配置相关
// =============================================
getRepoConfigPath() {
// 按你的需求:配置文件保存在插件安装位置
return path.join(this.extensionUri.fsPath, 'dcsp-repos.json');
}
async loadRepoConfigs() {
@@ -134,7 +133,6 @@ class ConfigPanel {
}
const parsed = JSON.parse(content);
if (Array.isArray(parsed)) {
// 兼容老格式:直接是数组
this.repoConfigs = parsed;
}
else if (parsed && Array.isArray(parsed.repos)) {
@@ -178,6 +176,9 @@ class ConfigPanel {
vscode.window.showErrorMessage(`打开仓库配置文件失败: ${error}`);
}
}
/**
* 通用:弹出仓库选择弹窗(不区分“获取分支 / 上传”,使用 pendingXXX 做上下文判断)
*/
async openRepoSelect() {
await this.loadRepoConfigs();
if (!this.repoConfigs || this.repoConfigs.length === 0) {
@@ -185,12 +186,17 @@ class ConfigPanel {
}
if (this.isWebviewDisposed)
return;
// 仅传递仓库名给前端,用于下拉选择
this.panel.webview.postMessage({
type: 'showRepoSelect',
repos: this.repoConfigs.map(r => ({ name: r.name }))
});
}
/**
* 仓库选择确认后的统一入口
* - local 上传pendingUploadFolderId 有值
* - git 上传pendingGitUploadFolderId 有值
* - 其余:当作“获取分支”处理
*/
async handleRepoSelectedForBranches(repoName) {
await this.loadRepoConfigs();
const repo = this.repoConfigs.find(r => r.name === repoName);
@@ -198,34 +204,84 @@ class ConfigPanel {
vscode.window.showErrorMessage(`在仓库配置中未找到名为 "${repoName}" 的仓库,请检查 dcsp-repos.json。`);
return;
}
// ---------------------------------------------------
// 1⃣ 新逻辑Local 上传pendingUploadFolderId 不为空)
// ---------------------------------------------------
// 1⃣ Local 模块上传local -> git
if (this.pendingUploadFolderId) {
const localFolderId = this.pendingUploadFolderId;
this.pendingUploadFolderId = null; // 必须清空,避免影响其他操作
this.pendingUploadFolderId = null;
console.log("🚀 Local 上传流程repo =", repoName, "folderId =", localFolderId);
const folder = this.moduleFolders.find(f => f.id === localFolderId);
if (!folder) {
if (!folder || folder.type !== 'local') {
vscode.window.showErrorMessage("未找到要上传的本地模块文件夹");
return;
}
// 生成本地路径
const fullPath = this.getModuleFolderFullPath(folder);
if (!fullPath) {
vscode.window.showErrorMessage("无法确定本地模块文件夹路径");
return;
}
// 自动从本地文件夹名生成分支名
const branchName = path.basename(fullPath);
console.log("🌿 自动生成分支名:", branchName);
// 正式执行上传
console.log("🌿 Local 上传自动生成分支名:", branchName);
await this.uploadLocalModuleFolder(localFolderId, repo.url, branchName);
return;
}
// ---------------------------------------------------
// 2⃣ 旧逻辑:获取分支
// ---------------------------------------------------
// 2⃣ Git 模块上传git -> repo
if (this.pendingGitUploadFolderId) {
const gitFolderId = this.pendingGitUploadFolderId;
this.pendingGitUploadFolderId = null;
console.log("🚀 Git 上传流程repo =", repoName, "folderId =", gitFolderId);
const folder = this.moduleFolders.find(f => f.id === gitFolderId);
if (!folder || folder.type !== 'git') {
vscode.window.showErrorMessage("未找到要上传的 Git 模块文件夹");
return;
}
const newFolderName = folder.localPath.split('/').pop() ?? '';
const oldFolderName = folder.originalFolderName ?? newFolderName;
const isRenamed = newFolderName !== oldFolderName;
const isSameRepo = !!folder.originalRepoUrl && folder.originalRepoUrl === repo.url;
console.log('🔍 Git 上传判断:');
console.log(' oldFolderName:', oldFolderName);
console.log(' newFolderName:', newFolderName);
console.log(' isRenamed :', isRenamed);
console.log(' folderRepo :', folder.originalRepoUrl);
console.log(' selectedRepo :', repo.url);
console.log(' isSameRepo :', isSameRepo);
const fullPath = this.getModuleFolderFullPath(folder);
if (!fullPath) {
vscode.window.showErrorMessage("无法确定 Git 模块文件夹路径");
return;
}
// 2.1 未改名 + 还是原来的仓库 → 直接在原分支上 push更新代码
if (!isRenamed && isSameRepo) {
console.log('✅ 未改名 & 同仓库:执行原始 push 逻辑');
await this.uploadGitModuleFolder(gitFolderId);
return;
}
// 2.2 改了名字 或 换了仓库 → 使用“当前文件夹名”作为分支,推送到选中仓库
console.log('🆕 名称改变或仓库改变:以文件夹名作为新分支上传');
await vscode.window.withProgress({
location: vscode.ProgressLocation.Notification,
title: `正在上传 Git 仓库: ${folder.name}`,
cancellable: false
}, async (progress) => {
try {
progress.report({ increment: 0, message: '准备上传...' });
await this.pushGitModuleFolderToRepoWithBranch(fullPath, repo.url, newFolderName);
folder.uploaded = true;
folder.originalFolderName = newFolderName;
folder.originalRepoUrl = repo.url;
await this.saveCurrentProjectData();
progress.report({ increment: 100, message: '完成' });
vscode.window.showInformationMessage(`✅ Git 仓库已上传到 ${repo.name} 的分支 ${newFolderName}`);
this.updateWebview();
}
catch (error) {
console.error('❌ Git 上传到新仓库/分支失败:', error);
vscode.window.showErrorMessage(`推送失败: ${error.message || error}`);
}
});
return;
}
// 3⃣ 默认:获取分支(用于“获取仓库”-> 克隆)
this.currentRepoForBranches = repo;
await this.fetchBranchesForRepo(repo);
}
@@ -297,7 +353,9 @@ class ConfigPanel {
// 上传功能
'uploadGitModuleFolder': (data) => this.uploadGitModuleFolder(data.folderId, data.username, data.password),
'openRepoSelectForUpload': (data) => this.handleOpenRepoSelectForUpload(data.folderId),
'uploadLocalModuleFolder': (data) => this.uploadLocalModuleFolder(data.folderId, data.repoUrl, data.branchName)
'uploadLocalModuleFolder': (data) => this.uploadLocalModuleFolder(data.folderId, data.repoUrl, data.branchName),
'openRepoSelectForGitUpload': (data) => this.openRepoSelectForGitUpload(data.folderId),
'repoSelectedForGitUpload': (data) => this.handleRepoSelectedForGitUpload(data.folderId, data.repoName)
};
const handler = messageHandlers[data.type];
if (handler) {
@@ -510,7 +568,6 @@ class ConfigPanel {
async handleOpenRepoSelectForUpload(folderId) {
console.log("📌 Local 上传:收到 openRepoSelectForUploadfolderId =", folderId);
this.pendingUploadFolderId = folderId;
// 复用你现有的仓库选择弹窗
await this.openRepoSelect();
}
async deleteConfig(configId) {
@@ -741,7 +798,9 @@ class ConfigPanel {
name: displayName,
type: 'git',
localPath: relativePath,
containerId: this.currentContainerId
containerId: this.currentContainerId,
originalFolderName: folderName,
originalRepoUrl: url
};
await vscode.window.withProgress({
location: vscode.ProgressLocation.Notification,
@@ -948,6 +1007,10 @@ class ConfigPanel {
// =============================================
// 上传功能方法
// =============================================
/**
* 旧的 Git 模块上传逻辑:直接在当前远程 / 当前分支上 commit + push
* 现在只在“未改名 + 同仓库”的场景下被调用
*/
async uploadGitModuleFolder(folderId, username, password) {
const folder = this.moduleFolders.find(f => f.id === folderId);
if (!folder || folder.type !== 'git') {
@@ -1011,6 +1074,8 @@ class ConfigPanel {
progress.report({ increment: 100, message: '完成' });
folder.type = 'git';
folder.uploaded = true;
folder.originalFolderName = branchName;
folder.originalRepoUrl = repoUrl;
await this.saveCurrentProjectData();
vscode.window.showInformationMessage(`本地文件夹成功上传到 Git 仓库: ${folder.name} -> ${branchName}`);
this.updateWebview();
@@ -1030,6 +1095,56 @@ class ConfigPanel {
}
});
}
/**
* Git 模块以“当前文件夹名”为分支,推送到任意仓库 URL
* 不修改现有 remote 配置,直接用 URL 形式 push
*/
async pushGitModuleFolderToRepoWithBranch(fullPath, repoUrl, branchName) {
return new Promise((resolve, reject) => {
const { exec } = require('child_process');
console.log('🚀 准备以新分支推送到仓库:', { fullPath, repoUrl, branchName });
// 先检查是否有未提交修改
exec('git status --porcelain', {
cwd: fullPath,
encoding: 'utf8'
}, (statusError, statusStdout, statusStderr) => {
if (statusError) {
console.error('❌ 检查 Git 状态失败:', statusError);
reject(new Error(`检查 Git 状态失败: ${statusStderr || statusError.message}`));
return;
}
const hasChanges = !!statusStdout.trim();
console.log('📋 有未提交更改?:', hasChanges, ', status =\n', statusStdout);
const commands = [];
// 获取完整的仓库历史
commands.push('git fetch --unshallow');
// 切换 / 创建分支
commands.push(`git checkout -B "${branchName}"`);
// 有变更就先提交
if (hasChanges) {
commands.push('git add .');
commands.push(`git commit -m "Auto commit from DCSP - ${new Date().toLocaleString()}"`);
}
// 直接用 URL 形式推送,不依赖 remote 名称
commands.push(`git push -u "${repoUrl}" "${branchName}" --force`);
console.log('🧰 即将执行命令链:', commands.join(' && '));
exec(commands.join(' && '), {
cwd: fullPath,
encoding: 'utf8'
}, (error, stdout, stderr) => {
console.log('📋 Git push stdout:', stdout);
console.log('📋 Git push stderr:', stderr);
if (error) {
console.error('❌ Git 推送失败:', error);
reject(new Error(stderr || error.message));
return;
}
console.log('✅ Git 推送到指定仓库/分支成功');
resolve();
});
});
});
}
// =============================================
// Git 命令行工具方法
// =============================================
@@ -1079,7 +1194,7 @@ class ConfigPanel {
return new Promise((resolve, reject) => {
const { exec } = require('child_process');
console.log('📁 初始化 Git 仓库...');
exec(`git init && git checkout -b ${branchName}`, {
exec(`git init && git checkout -b "${branchName}"`, {
cwd: fullPath,
encoding: 'utf8'
}, (error, stdout, stderr) => {
@@ -1097,7 +1212,7 @@ class ConfigPanel {
return new Promise((resolve, reject) => {
const { exec } = require('child_process');
console.log('📡 添加远程仓库...');
exec(`git remote add origin ${repoUrl}`, {
exec(`git remote add origin "${repoUrl}"`, {
cwd: fullPath,
encoding: 'utf8'
}, (error, stdout, stderr) => {
@@ -1117,7 +1232,7 @@ class ConfigPanel {
console.log('💾 提交初始文件...');
const commands = [
'git add .',
`git commit -m "Initial commit from DCSP - ${new Date().toLocaleString()}"`,
`git commit -m "Initial commit from DCSP - ${new Date().toLocaleString()}"`
];
exec(commands.join(' && '), {
cwd: fullPath,
@@ -1142,7 +1257,7 @@ class ConfigPanel {
return new Promise((resolve, reject) => {
const { exec } = require('child_process');
console.log('🚀 强制推送到远程仓库...');
exec(`git push -u origin ${branchName} --force`, {
exec(`git push -u origin "${branchName}" --force`, {
cwd: fullPath,
encoding: 'utf8'
}, (error, stdout, stderr) => {
@@ -1552,6 +1667,11 @@ class ConfigPanel {
return [];
}
}
async handleRepoSelectedForGitUpload(folderId, repoName) {
// 兼容:如果前端用的是 repoSelectedForGitUpload 事件,则这里转成统一逻辑
this.pendingGitUploadFolderId = folderId;
await this.handleRepoSelectedForBranches(repoName);
}
// =============================================
// 工具方法
// =============================================
@@ -1681,7 +1801,7 @@ class ConfigPanel {
const newFullPath = path.join(path.dirname(fullPath), newName);
try {
await fs.promises.rename(fullPath, newFullPath);
// 更新 localPath
// 更新 localPath注意originalFolderName 不更新,用于判断“是否改名过”)
folder.localPath = folder.localPath.replace(/\/[^/]+$/, '/' + newName);
await this.saveCurrentProjectData();
vscode.window.showInformationMessage(`已重命名文件夹: ${oldName}${newName}`);
@@ -1706,6 +1826,11 @@ class ConfigPanel {
console.error('更新 Webview 失败:', error);
}
}
async openRepoSelectForGitUpload(folderId) {
console.log('📌 Git 上传:收到 openRepoSelectForGitUploadfolderId =', folderId);
this.pendingGitUploadFolderId = folderId;
await this.openRepoSelect();
}
getWebviewContent() {
switch (this.currentView) {
case 'projects':