194 lines
5.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import * as vscode from 'vscode';
import * as fs from 'fs';
import { AbsPath, opeParam } from '../global';
import { hdlDir, hdlFile, hdlPath } from '../hdlFs';
import { Library } from '../global/prjInfo';
import { Path } from '../../resources/hdlParser';
interface LibFileChange {
add: AbsPath[],
del: AbsPath[],
}
interface LibStatus {
type?: string,
list: AbsPath[]
}
/**
* a与b的差集
* @param a
* @param b
* @returns
*/
function diffElement<T>(a: T[], b: T[]): T[] {
const bSet = new Set<T>(b);
return a.filter(el => !bSet.has(el));
}
function removeDuplicates<T>(a: T[]): T[] {
const aSet = new Set(a);
return [...aSet];
}
class LibManage {
curr: LibStatus;
next: LibStatus;
constructor() {
this.curr = { list : [] };
this.next = { list : [] };
}
public get customerPath(): AbsPath {
return opeParam.prjInfo.libCustomPath;
}
public get srcPath(): AbsPath {
return opeParam.prjInfo.arch.hardware.src;
}
public get simPath(): AbsPath {
return opeParam.prjInfo.arch.hardware.sim;
}
public get prjPath(): AbsPath {
return opeParam.prjInfo.arch.prjPath;
}
public get localLibPath(): AbsPath {
return hdlPath.join(this.srcPath, 'lib');
}
public get sourceLibPath(): AbsPath {
return hdlPath.join(opeParam.extensionPath, 'lib');
}
public get libCustomPath(): AbsPath {
return opeParam.prjInfo.libCustomPath;
}
public processLibFiles(library: Library): LibFileChange {
// 在不设置state属性的时候默认为remote
this.next.list = this.getLibFiles(library);
if (!hdlFile.isHasAttr(library, 'state')) {
this.next.type = 'remote';
} else {
if (library.state !== 'remote' && library.state !== 'local') {
return {
'add' : [],
'del' : [],
};
}
this.next.type = library.state;
}
// 处于初始状态时的情况
if (!this.curr.type) {
if (!hdlFile.isDir(this.localLibPath)) {
this.curr.type = 'local';
} else {
this.curr.type = 'remote';
}
}
const state = `${this.curr.type}-${this.next.type}`;
let add: AbsPath[] = [];
let del: AbsPath[] = [];
switch (state) {
case 'remote-remote':
add = diffElement(this.next.list, this.curr.list);
del = diffElement(this.curr.list, this.next.list);
break;
case 'remote-local':
// 删除的内容全是remote的将curr的交出去即可
del = this.curr.list;
// 将新增的全部复制到本地交给monitor进行处理
this.remote2Local(this.next.list, (src, dist) => {
hdlFile.copyFile(src, dist);
});
break;
case 'local-remote':
// 本地的lib全部删除交给monitor进行处理
const fn = async () => {
if (fs.existsSync(this.localLibPath)) {
const needNotice = vscode.workspace.getConfiguration('prj.file.structure.notice');
if (needNotice) {
let select = await vscode.window.showWarningMessage("local lib will be removed.", 'Yes', 'Cancel');
if (select === "Yes") {
hdlDir.rmdir(this.localLibPath);
}
} else {
hdlDir.rmdir(this.localLibPath);
}
}
};
fn();
// 增加的内容全是remote的将next的交出去即可
add = this.next.list;
break;
case 'local-local':
// 只管理library里面的内容如果自己再localPath里加减代码则不去管理
add = diffElement(this.next.list, this.curr.list);
del = diffElement(this.curr.list, this.next.list);
this.remote2Local(add, (src, dist) => {
hdlFile.copyFile(src, dist);
});
this.remote2Local(del, (src, dist) => {
hdlFile.removeFile(dist);
});
add = []; del = [];
break;
default: break;
}
return { add, del };
}
getLibFiles(library: Library) {
const libFileList: AbsPath[] = [];
const prjInfo = opeParam.prjInfo;
// collect common libs
prjInfo.getLibraryCommonPaths().forEach(absPath => libFileList.push(...hdlFile.getHDLFiles(absPath)));
// collect custom libs
prjInfo.getLibraryCustomPaths().forEach(absPath => libFileList.push(...hdlFile.getHDLFiles(absPath)));
// Remove duplicate HDL files
return removeDuplicates(libFileList);
}
remote2Local(remotes: Path[], callback: (src: AbsPath, dist: AbsPath) => void) {
const localLibPath = this.localLibPath;
const sourceLibPath = this.sourceLibPath;
const customerPath = this.customerPath;
const customerPathValid = hdlFile.isDir(customerPath);
for (const src of remotes) {
let dist;
if (customerPathValid && src.includes(customerPath)) {
dist = src.replace(customerPath, localLibPath);
} else {
dist = src.replace(sourceLibPath, localLibPath);
}
callback(src, dist);
}
}
};
const libManage = new LibManage();
export {
libManage,
LibManage
};