0
0

添加了本地和git的区分

This commit is contained in:
xubing
2025-11-28 14:16:19 +08:00
parent 17e9dc1451
commit 2fd84439b7
9 changed files with 355 additions and 212 deletions

View File

@@ -7,6 +7,7 @@ import { ProjectView } from './views/ProjectView';
import { AircraftView } from './views/AircraftView';
import { ContainerView } from './views/ContainerView';
import { ConfigView } from './views/ConfigView';
import { ModuleFolder } from './types/DataTypes';
// 数据模型接口
interface Project {
@@ -34,15 +35,6 @@ interface Config {
containerId: string;
}
// 统一的模块文件夹接口,合并 gitRepos 和 mergedFolders
interface ModuleFolder {
id: string;
name: string;
type: 'git' | 'merged'; // 类型标识
localPath: string; // 相对路径,如 "/项目1/飞行器1/容器1/test-code"
containerId: string;
}
interface GitFileTree {
name: string;
type: 'file' | 'folder';
@@ -309,11 +301,11 @@ export class ConfigPanel {
break;
case 'openMergedFolderInVSCode':
await this.openTheModuleFolder('merged', data.folderId);
await this.openTheModuleFolder('local', data.folderId);
break;
case 'loadMergedFolder':
await this.openTheModuleFolder('merged', data.folderId);
await this.openTheModuleFolder('local', data.folderId);
break;
case 'openTheModuleFolder':
@@ -421,85 +413,93 @@ export class ConfigPanel {
/**
* 添加 Git 模块文件夹到容器目录
*/
private async addGitModuleFolder(url: string, name: string, branch?: string): Promise<void> {
try {
// 验证 URL
if (!url || !url.startsWith('http')) {
vscode.window.showErrorMessage('请输入有效的 Git 仓库 URL');
return;
}
private async addGitModuleFolder(url: string, displayName: string, folderName: string, branch?: string): Promise<void> {
try {
// 验证 URL
if (!url || !url.startsWith('http')) {
vscode.window.showErrorMessage('请输入有效的 Git 仓库 URL');
return;
}
if (!this.currentContainerId) {
vscode.window.showErrorMessage('请先选择容器');
return;
}
if (!this.currentContainerId) {
vscode.window.showErrorMessage('请先选择容器');
return;
}
const folderId = 'git-' + Date.now();
// 构建本地路径
const container = this.containers.find(c => c.id === this.currentContainerId);
if (!container) {
vscode.window.showErrorMessage('未找到容器');
return;
}
const folderId = 'git-' + Date.now();
// 构建本地路径
const container = this.containers.find(c => c.id === this.currentContainerId);
if (!container) {
vscode.window.showErrorMessage('未找到容器');
return;
}
const aircraft = this.aircrafts.find(a => a.id === container.aircraftId);
if (!aircraft) {
vscode.window.showErrorMessage('未找到飞行器');
return;
}
const aircraft = this.aircrafts.find(a => a.id === container.aircraftId);
if (!aircraft) {
vscode.window.showErrorMessage('未找到飞行器');
return;
}
const projectPath = this.projectPaths.get(aircraft.projectId);
if (!projectPath) {
vscode.window.showErrorMessage('未找到项目路径');
return;
}
const projectPath = this.projectPaths.get(aircraft.projectId);
if (!projectPath) {
vscode.window.showErrorMessage('未找到项目路径');
return;
}
// 构建相对路径(从项目路径开始)
const relativePath = `/${aircraft.projectId}/${aircraft.name}/${container.name}/${name}`;
// 完整路径用于实际操作
const localPath = path.join(projectPath, aircraft.name, container.name, name);
console.log(`📁 Git模块文件夹将保存到: ${localPath}`);
console.log(`📁 相对路径: ${relativePath}`);
// 构建相对路径(从项目路径开始)- 使用 folderName 作为实际文件夹名
const relativePath = `/${aircraft.projectId}/${aircraft.name}/${container.name}/${folderName}`;
// 完整路径用于实际操作 - 使用 folderName 作为实际文件夹名
const localPath = path.join(projectPath, aircraft.name, container.name, folderName);
console.log(`📁 准备克隆仓库: ${displayName}, 分支: ${branch}, 路径: ${localPath}`);
console.log(`📁 相对路径: ${relativePath}`);
// 检查是否已存在相同名称的模块文件夹
const existingFolder = this.moduleFolders.find(folder =>
folder.name === name && folder.containerId === this.currentContainerId
);
if (existingFolder) {
vscode.window.showWarningMessage('该名称的模块文件夹已存在');
return;
}
// 修复:检查是否已存在相同实际路径的模块文件夹,而不是显示名称
const existingFolder = this.moduleFolders.find(folder =>
folder.localPath === relativePath && folder.containerId === this.currentContainerId
);
if (existingFolder) {
vscode.window.showWarningMessage(`该路径的模块文件夹已存在: ${folderName}`);
return;
}
const newFolder: ModuleFolder = {
id: folderId,
name: name,
type: 'git',
localPath: relativePath, // 存储相对路径
containerId: this.currentContainerId
};
const newFolder: ModuleFolder = {
id: folderId,
name: displayName, // 使用显示名称
type: 'git',
localPath: relativePath, // 存储相对路径
containerId: this.currentContainerId
};
console.log(`📁 准备克隆仓库: ${name}, 分支: ${branch}, 路径: ${localPath}`);
// 显示进度
await vscode.window.withProgress({
location: vscode.ProgressLocation.Notification,
title: `正在克隆仓库: ${displayName}`,
cancellable: false
}, async (progress) => {
progress.report({ increment: 0 });
// 显示进度
await vscode.window.withProgress({
location: vscode.ProgressLocation.Notification,
title: `正在克隆仓库: ${name}`,
cancellable: false
}, async (progress) => {
progress.report({ increment: 0 });
try {
// 确保父目录存在
const parentDir = path.dirname(localPath);
await fs.promises.mkdir(parentDir, { recursive: true });
// 检查目标目录是否已存在
let dirExists = false;
try {
// 确保目录存在
await fs.promises.mkdir(localPath, { recursive: true });
await fs.promises.access(localPath);
dirExists = true;
} catch {
dirExists = false;
}
// 检查目录是否为空
if (dirExists) {
const dirContents = await fs.promises.readdir(localPath);
if (dirContents.length > 0) {
const confirm = await vscode.window.showWarningMessage(
`目标目录不为空,确定要覆盖吗?`,
`目标目录 "${folderName}" 不为空,确定要覆盖吗?`,
{ modal: true },
'确定覆盖',
'取消'
@@ -518,54 +518,86 @@ export class ConfigPanel {
}
}
}
// 克隆仓库
await git.clone({
fs: fs,
http: http,
dir: localPath,
url: url,
singleBranch: true,
depth: 1,
ref: branch || 'main',
onProgress: (event: any) => {
if (event.total) {
const percent = (event.loaded / event.total) * 100;
progress.report({ increment: percent, message: `${event.phase}...` });
}
}
});
console.log('✅ Git克隆成功完成');
this.moduleFolders.push(newFolder);
await this.saveCurrentProjectData();
console.log('✅ Git模块文件夹数据已保存到项目文件');
vscode.window.showInformationMessage(`Git 仓库克隆成功: ${name}`);
// 检查 Webview 状态后再加载文件树
if (!this.isWebviewDisposed) {
console.log('🌳 开始加载模块文件夹文件树...');
// 自动加载文件树
this.currentModuleFolderId = folderId;
await this.loadModuleFolderFileTree(folderId);
console.log('✅ 模块文件夹文件树加载完成');
} else {
console.log('⚠️ Webview 已被销毁,跳过文件树加载');
}
} catch (error) {
console.error('❌ 在克隆过程中捕获错误:', error);
vscode.window.showErrorMessage(`克隆仓库失败: ${error}`);
}
});
} catch (error) {
console.error('❌ 在addGitModuleFolder外部捕获错误:', error);
vscode.window.showErrorMessage(`添加 Git 模块文件夹失败: ${error}`);
}
console.log(`🚀 开始克隆: ${url} -> ${localPath}, 分支: ${branch}`);
// 克隆仓库
await git.clone({
fs: fs,
http: http,
dir: localPath,
url: url,
singleBranch: true,
depth: 1,
ref: branch || 'main',
onProgress: (event: any) => {
console.log(`📊 克隆进度: ${event.phase} - ${event.loaded}/${event.total}`);
if (event.total) {
const percent = (event.loaded / event.total) * 100;
progress.report({
increment: percent,
message: `${event.phase}... (${Math.round(percent)}%)`
});
} else {
progress.report({ message: `${event.phase}...` });
}
}
});
console.log('✅ Git克隆成功完成');
// 验证克隆是否真的成功
const clonedContents = await fs.promises.readdir(localPath);
console.log(`📁 克隆后的目录内容:`, clonedContents);
if (clonedContents.length === 0) {
throw new Error('克隆后目录为空,可能克隆失败');
}
// 只有在克隆成功后才添加到列表
this.moduleFolders.push(newFolder);
await this.saveCurrentProjectData();
console.log('✅ Git模块文件夹数据已保存到项目文件');
vscode.window.showInformationMessage(`Git 仓库克隆成功: ${displayName}`);
// 检查 Webview 状态后再加载文件树
if (!this.isWebviewDisposed) {
console.log('🌳 开始加载模块文件夹文件树...');
// 自动加载文件树
this.currentModuleFolderId = folderId;
await this.loadModuleFolderFileTree(folderId);
console.log('✅ 模块文件夹文件树加载完成');
} else {
console.log('⚠️ Webview 已被销毁,跳过文件树加载');
}
} catch (error) {
console.error('❌ 在克隆过程中捕获错误:', error);
// 清理:如果克隆失败,删除可能创建的不完整目录
try {
if (fs.existsSync(localPath)) {
await fs.promises.rm(localPath, { recursive: true, force: true });
console.log('🧹 已清理克隆失败的目录');
}
} catch (cleanupError) {
console.error('清理失败目录时出错:', cleanupError);
}
vscode.window.showErrorMessage(`克隆仓库失败: ${error}`);
// 重新抛出错误,让外部知道克隆失败
throw error;
}
});
} catch (error) {
console.error('❌ 在addGitModuleFolder外部捕获错误:', error);
vscode.window.showErrorMessage(`添加 Git 模块文件夹失败: ${error}`);
}
}
/**
* 加载模块文件夹
@@ -1457,42 +1489,63 @@ export class ConfigPanel {
return root;
}
private async cloneBranches(url: string, branches: string[]): Promise<void> {
try {
console.log('🚀 开始克隆分支:', { url, branches });
// 显示总进度
await vscode.window.withProgress({
location: vscode.ProgressLocation.Notification,
title: `正在克隆 ${branches.length} 个分支`,
cancellable: false
}, async (progress) => {
for (let i = 0; i < branches.length; i++) {
const branch = branches[i];
const progressPercent = (i / branches.length) * 100;
progress.report({
increment: progressPercent,
message: `克隆分支: ${branch} (${i + 1}/${branches.length})`
});
console.log(`📥 克隆分支: ${branch}`);
await this.addGitModuleFolder(url, this.generateModuleFolderName(url, branch), branch);
}
});
vscode.window.showInformationMessage(`成功克隆 ${branches.length} 个分支`);
} catch (error) {
console.error('❌ 克隆分支失败:', error);
vscode.window.showErrorMessage(`克隆分支失败: ${error}`);
}
}
private generateModuleFolderName(url: string, branch: string): { displayName: string; folderName: string } {
const repoName = url.split('/').pop()?.replace('.git', '') || 'unknown-repo';
const branchSafeName = branch.replace(/[^a-zA-Z0-9-_]/g, '-');
return {
displayName: repoName, // 配置栏显示的名称(只显示仓库名)
folderName: branchSafeName // 实际文件夹名称(只显示分支名)
};
}
private generateModuleFolderName(url: string, branch: string): string {
const repoName = url.split('/').pop()?.replace('.git', '') || 'unknown-repo';
const branchSafeName = branch.replace(/[^a-zA-Z0-9-_]/g, '-');
return `${repoName}-${branchSafeName}`;
private async cloneBranches(url: string, branches: string[]): Promise<void> {
try {
console.log('🚀 开始克隆分支:', { url, branches });
let successCount = 0;
let failCount = 0;
// 显示总进度
await vscode.window.withProgress({
location: vscode.ProgressLocation.Notification,
title: `正在克隆 ${branches.length} 个分支`,
cancellable: false
}, async (progress) => {
for (let i = 0; i < branches.length; i++) {
const branch = branches[i];
const progressPercent = (i / branches.length) * 100;
progress.report({
increment: progressPercent,
message: `克隆分支: ${branch} (${i + 1}/${branches.length})`
});
console.log(`📥 开始克隆分支: ${branch}`);
try {
const folderNames = this.generateModuleFolderName(url, branch);
await this.addGitModuleFolder(url, folderNames.displayName, folderNames.folderName, branch);
successCount++;
console.log(`✅ 分支克隆成功: ${branch}`);
} catch (error) {
failCount++;
console.error(`❌ 分支克隆失败: ${branch}`, error);
// 继续克隆其他分支,不中断整个流程
}
}
});
// 显示最终结果
if (failCount === 0) {
vscode.window.showInformationMessage(`成功克隆 ${successCount} 个分支`);
} else {
vscode.window.showWarningMessage(`克隆完成: ${successCount} 个成功, ${failCount} 个失败`);
}
} catch (error) {
console.error('❌ 克隆分支失败:', error);
vscode.window.showErrorMessage(`克隆分支失败: ${error}`);
}
}
// 更新视图
private updateWebview() {
@@ -1704,9 +1757,9 @@ export class ConfigPanel {
// 创建合并文件夹记录
const newFolder: ModuleFolder = {
id: 'merged-' + Date.now(),
id: 'local-' + Date.now(),
name: displayName,
type: 'merged',
type: 'local',
localPath: relativePath,
containerId: this.currentContainerId
};
@@ -1801,7 +1854,7 @@ export class ConfigPanel {
* @param type 模块类型:'git' 或 'merged'
* @param id 模块 ID
*/
private async openTheModuleFolder(type: 'git' | 'merged', id: string): Promise<void> {
private async openTheModuleFolder(type: 'git' | 'local', id: string): Promise<void> {
const folder = this.moduleFolders.find(f => f.id === id);
if (!folder) {
vscode.window.showErrorMessage('未找到指定的模块文件夹');