Benjin/delete (#11054)

* Adding delete to package.json

* checkpoint

* Delete file working

* Working for nested folders

* Added file/folder deletion test

* addressing feedback

* Swapping QuickPick for modal

* Adding Exclude functionality

* reverting change to package.json
This commit is contained in:
Benjin Dubishar
2020-06-24 10:27:58 -07:00
committed by GitHub
parent 2ba0de10df
commit 00836e1890
11 changed files with 237 additions and 17 deletions

View File

@@ -27,7 +27,7 @@ export class Project {
public sqlCmdVariables: Record<string, string> = {};
public get projectFolderPath() {
return path.dirname(this.projectFilePath);
return Uri.file(path.dirname(this.projectFilePath)).fsPath;
}
private projFileXmlDoc: any = undefined;
@@ -179,6 +179,26 @@ export class Project {
return fileEntry;
}
public async exclude(entry: ProjectEntry): Promise<void> {
const toExclude: ProjectEntry[] = this.files.filter(x => x.fsUri.fsPath.startsWith(entry.fsUri.fsPath));
await this.removeFromProjFile(toExclude);
this.files = this.files.filter(x => !x.fsUri.fsPath.startsWith(entry.fsUri.fsPath));
}
public async deleteFileFolder(entry: ProjectEntry): Promise<void> {
// compile a list of folder contents to delete; if entry is a file, contents will contain only itself
const toDeleteFiles: ProjectEntry[] = this.files.filter(x => x.fsUri.fsPath.startsWith(entry.fsUri.fsPath) && x.type === EntryType.File);
const toDeleteFolders: ProjectEntry[] = this.files.filter(x => x.fsUri.fsPath.startsWith(entry.fsUri.fsPath) && x.type === EntryType.Folder).sort(x => -x.relativePath.length);
await Promise.all(toDeleteFiles.map(x => fs.unlink(x.fsUri.fsPath)));
for (const folder of toDeleteFolders) {
await fs.rmdir(folder.fsUri.fsPath); // TODO: replace .sort() and iteration with rmdir recursive flag once that's unbugged
}
await this.exclude(entry);
}
/**
* Set the compat level of the project
* Just used in tests right now, but can be used later if this functionality is added to the UI
@@ -290,6 +310,19 @@ export class Project {
this.findOrCreateItemGroup(constants.Build).appendChild(newFileNode);
}
private removeFileFromProjFile(path: string) {
const fileNodes = this.projFileXmlDoc.documentElement.getElementsByTagName(constants.Build);
for (let i = 0; i < fileNodes.length; i++) {
if (fileNodes[i].getAttribute(constants.Include) === path) {
fileNodes[i].parentNode.removeChild(fileNodes[i]);
return;
}
}
throw new Error(constants.unableToFindObject(path, constants.fileObject));
}
private addFolderToProjFile(path: string) {
const newFolderNode = this.projFileXmlDoc.createElement(constants.Folder);
newFolderNode.setAttribute(constants.Include, path);
@@ -297,6 +330,19 @@ export class Project {
this.findOrCreateItemGroup(constants.Folder).appendChild(newFolderNode);
}
private removeFolderFromProjFile(path: string) {
const folderNodes = this.projFileXmlDoc.documentElement.getElementsByTagName(constants.Folder);
for (let i = 0; i < folderNodes.length; i++) {
if (folderNodes[i].getAttribute(constants.Include) === path) {
folderNodes[i].parentNode.removeChild(folderNodes[i]);
return;
}
}
throw new Error(constants.unableToFindObject(path, constants.folderObject));
}
private addDatabaseReferenceToProjFile(entry: DatabaseReferenceProjectEntry): void {
// check if reference to this database already exists
if (this.databaseReferenceExists(entry)) {
@@ -424,6 +470,27 @@ export class Project {
await this.serializeToProjFile(this.projFileXmlDoc);
}
private async removeFromProjFile(entries: ProjectEntry | ProjectEntry[]) {
if (entries instanceof ProjectEntry) {
entries = [entries];
}
for (const entry of entries) {
switch (entry.type) {
case EntryType.File:
this.removeFileFromProjFile(entry.relativePath);
break;
case EntryType.Folder:
this.removeFolderFromProjFile(entry.relativePath);
break;
case EntryType.DatabaseReference:
break; // not required but adding so that we dont miss when we add new items
}
}
await this.serializeToProjFile(this.projFileXmlDoc);
}
private async serializeToProjFile(projFileContents: any) {
let xml = new xmldom.XMLSerializer().serializeToString(projFileContents);
xml = xmlFormat(xml, <any>{ collapseContent: true, indentation: ' ', lineSeparator: os.EOL }); // TODO: replace <any>

View File

@@ -22,6 +22,10 @@ export abstract class BaseProjectTreeItem {
abstract get treeItem(): vscode.TreeItem;
public get friendlyName(): string {
return path.parse(this.uri.path).base;
}
public get root() {
let node: BaseProjectTreeItem = this;

View File

@@ -88,7 +88,7 @@ export function sortFileFolderNodes(a: (FolderNode | FileNode), b: (FolderNode |
* Converts a full filesystem URI to a project-relative URI that's compatible with the project tree
*/
function fsPathToProjectUri(fileSystemUri: vscode.Uri, projectNode: ProjectRootTreeItem): vscode.Uri {
const projBaseDir = path.dirname(projectNode.project.projectFilePath);
const projBaseDir = projectNode.project.projectFolderPath;
let localUri = '';
if (fileSystemUri.fsPath.startsWith(projBaseDir)) {