diff --git a/extensions/sql-database-projects/src/models/project.ts b/extensions/sql-database-projects/src/models/project.ts index 369016dde7..1eebc064db 100644 --- a/extensions/sql-database-projects/src/models/project.ts +++ b/extensions/sql-database-projects/src/models/project.ts @@ -263,7 +263,7 @@ export class Project { * Adds a folder to the project, and saves the project file * @param relativeFolderPath Relative path of the folder */ - public async addFolderItem(relativeFolderPath: string): Promise { + public async addFolderItem(relativeFolderPath: string): Promise { const absoluteFolderPath = path.join(this.projectFolderPath, relativeFolderPath); //If folder doesn't exist, create it @@ -347,13 +347,10 @@ export class Project { public async deleteFileFolder(entry: FileProjectEntry): Promise { // compile a list of folder contents to delete; if entry is a file, contents will contain only itself const toDeleteFiles: FileProjectEntry[] = this.files.concat(this.preDeployScripts).concat(this.postDeployScripts).concat(this.noneDeployScripts).filter(x => x.fsUri.fsPath.startsWith(entry.fsUri.fsPath) && x.type === EntryType.File); - const toDeleteFolders: FileProjectEntry[] = this.files.filter(x => x.fsUri.fsPath.startsWith(entry.fsUri.fsPath) && x.type === EntryType.Folder).sort(x => -x.relativePath.length); + const toDeleteFolders: FileProjectEntry[] = this.files.filter(x => x.fsUri.fsPath.startsWith(entry.fsUri.fsPath) && x.type === EntryType.Folder); 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 Promise.all(toDeleteFolders.map(x => fs.rmdir(x.fsUri.fsPath, { recursive: true }))); await this.exclude(entry); } diff --git a/extensions/sql-database-projects/src/test/projectController.test.ts b/extensions/sql-database-projects/src/test/projectController.test.ts index 148d6c3c84..436fc04c39 100644 --- a/extensions/sql-database-projects/src/test/projectController.test.ts +++ b/extensions/sql-database-projects/src/test/projectController.test.ts @@ -245,6 +245,33 @@ describe('ProjectsController', function (): void { should(await exists(noneEntry.fsUri.fsPath)).equal(true, 'none entry pre-deployment script is supposed to still exist on disk'); }); + it('Should delete folders with excluded items', async function (): Promise { + let proj = await testUtils.createTestProject(templates.newSqlProjectTemplate); + const setupResult = await setupDeleteExcludeTest(proj); + + const scriptEntry = setupResult[0], projTreeRoot = setupResult[1]; + const upperFolder = projTreeRoot.children.find(x => x.friendlyName === 'UpperFolder')!; + const lowerFolder = upperFolder.children.find(x => x.friendlyName === 'LowerFolder')!; + + const projController = new ProjectsController(); + + // Exclude files under LowerFolder + await projController.exclude(createWorkspaceTreeItem(lowerFolder.children.find(x => x.friendlyName === 'someScript.sql')!)); + await projController.exclude(createWorkspaceTreeItem(lowerFolder.children.find(x => x.friendlyName === 'someOtherScript.sql')!)); + + // Delete UpperFolder + await projController.delete(createWorkspaceTreeItem(projTreeRoot.children.find(x => x.friendlyName === 'UpperFolder')!)); + + // Reload edited sqlproj from disk + proj = await Project.openProject(proj.projectFilePath); + + // Confirm result + should(proj.files.some(x => x.relativePath === 'UpperFolder')).equal(false, 'UpperFolder should not be part of proj file any more'); + should(await exists(scriptEntry.fsUri.fsPath)).equal(false, 'script is supposed to be deleted from disk'); + should(await exists(lowerFolder.uri.fsPath)).equal(false, 'LowerFolder is supposed to be deleted from disk'); + should(await exists(upperFolder.uri.fsPath)).equal(false, 'UpperFolder is supposed to be deleted from disk'); + }); + it('Should reload correctly after changing sqlproj file', async function (): Promise { // create project const folderPath = await testUtils.generateTestFolderPath();