Handle delete folder for SDK style sql projects (#17961)

* handle delete folder for sdk style projects

* cleanup

* compare original sqlproj contents

* remove redundant checks
This commit is contained in:
Kim Santiago
2021-12-20 12:43:30 -08:00
committed by GitHub
parent 2bf3c28370
commit 443257e699
3 changed files with 94 additions and 4 deletions

View File

@@ -1052,9 +1052,8 @@ export class Project implements ISqlProject {
// again when they convert to an SDK-style project
if (this.isSdkStyleProject) {
// update sqlproj if a node was deleted and load files and folders again
if (deleted) {
await this.writeToSqlProjAndUpdateFilesFolders();
}
await this.writeToSqlProjAndUpdateFilesFolders();
// get latest folders to see if it still exists
const currentFolders = await this.readFolders();

View File

@@ -35,7 +35,7 @@
</ItemGroup>
<ItemGroup>
<PostDeploy Include="Script.PostDeployment1.sql" />
<None Include="folder1\Script.PostDeployment1.sql" />
<None Include="folder1\Script.PostDeployment2.sql" />
</ItemGroup>
<ItemGroup>
<ArtifactReference Condition="'$(NetCoreBuild)' == 'true'" Include="$(NETCoreTargetsPath)\SystemDacpacs\150\master.dacpac">

View File

@@ -1253,6 +1253,97 @@ describe('Project: sdk style project content operations', function (): void {
should(project.files.find(f => f.relativePath === 'folder3\\')!).not.equal(undefined, 'folder3\\ should be loaded');
should(project.files.find(f => f.relativePath === 'folder3\\innerFolder\\')!).not.equal(undefined, 'folder3\\innerFolder\\ should be loaded');
});
it('Should handle deleting empty folders', async function (): Promise<void> {
const testFolderPath = await testUtils.generateTestFolderPath();
projFilePath = await testUtils.createTestSqlProjFile(baselines.newSdkStyleProjectSdkNodeBaseline, testFolderPath);
const project: Project = await Project.openProject(projFilePath);
const beforeProjFileText = (await fs.readFile(projFilePath)).toString();
should(project.files.filter(f => f.type === EntryType.File).length).equal(0);
should(project.files.filter(f => f.type === EntryType.Folder).length).equal(0);
// add an empty folder
await project.addFolderItem('folder1');
// verify folder was added
should(project.files.filter(f => f.type === EntryType.Folder).length).equal(1);
should(project.files.filter(f => f.type === EntryType.File).length).equal(0);
should(project.files.find(f => f.relativePath === 'folder1\\')).not.equal(undefined, 'folder1 should have been added');
// verify entry was added for the new empty folder in the sqlproj
let projFileText = (await fs.readFile(projFilePath)).toString();
should(projFileText.includes('<Folder Include="folder1\\" />')).equal(true, projFileText);
// delete the empty folder
await project.deleteFileFolder(project.files.find(f => f.relativePath === 'folder1\\')!);
should(project.files.filter(f => f.type === EntryType.Folder).length).equal(0, 'folder1 should have been deleted');
// verify the folder entry was removed from the sqlproj and a Build Remove was not added
projFileText = (await fs.readFile(projFilePath)).toString();
should(projFileText.trimEnd() === beforeProjFileText.trimEnd()).equal(true, 'The sqlproj should not have changed after deleting folder1');
});
it('Should handle deleting not empty glob included folders', async function (): Promise<void> {
const testFolderPath = await testUtils.generateTestFolderPath();
projFilePath = await testUtils.createTestSqlProjFile(baselines.openSdkStyleSqlProjectBaseline, testFolderPath);
await testUtils.createDummyFileStructureWithPrePostDeployScripts(false, undefined, path.dirname(projFilePath));
const project: Project = await Project.openProject(projFilePath);
const beforeProjFileText = (await fs.readFile(projFilePath)).toString();
should(project.files.filter(f => f.type === EntryType.File).length).equal(13);
should(project.files.filter(f => f.type === EntryType.Folder).length).equal(3);
// delete a folder with contents
await project.deleteFileFolder(project.files.find(f => f.relativePath === 'folder2\\')!);
should(project.files.filter(f => f.type === EntryType.File).length).equal(8);
should(project.files.filter(f => f.type === EntryType.Folder).length).equal(2);
// verify the folder entry was removed from the sqlproj and a Build Remove was not added
const projFileText = (await fs.readFile(projFilePath)).toString();
should(projFileText.trimEnd() === beforeProjFileText.trimEnd()).equal(true, 'The sqlproj should not have changed after deleting folder2');
});
it('Should handle deleting explicitly included folders', async function (): Promise<void> {
const testFolderPath = await testUtils.generateTestFolderPath();
projFilePath = await testUtils.createTestSqlProjFile(baselines.openSdkStyleSqlProjectWithFilesSpecifiedBaseline, testFolderPath);
await testUtils.createDummyFileStructureWithPrePostDeployScripts(false, undefined, path.dirname(projFilePath));
const project: Project = await Project.openProject(projFilePath);
should(project.files.filter(f => f.type === EntryType.File).length).equal(13);
should(project.files.filter(f => f.type === EntryType.Folder).length).equal(3);
should(project.files.find(f => f.relativePath === 'folder1\\')!).not.equal(undefined);
should(project.files.find(f => f.relativePath === 'folder2\\')!).not.equal(undefined);
// try to delete an explicitly included folder with the trailing \ in sqlproj
await project.deleteFileFolder(project.files.find(f => f.relativePath === 'folder2\\')!);
// verify the project not longer has folder2 and its contents
should(project.files.filter(f => f.type === EntryType.Folder).length).equal(2);
should(project.files.filter(f => f.type === EntryType.File).length).equal(8);
should(project.files.find(f => f.relativePath === 'folder2\\')).equal(undefined);
// try to delete an explicitly included folder without trailing \ in sqlproj
await project.deleteFileFolder(project.files.find(f => f.relativePath === 'folder1\\')!);
// verify the project not longer has folder1 and its contents
should(project.files.filter(f => f.type === EntryType.Folder).length).equal(0);
should(project.files.filter(f => f.type === EntryType.File).length).equal(1);
should(project.files.find(f => f.relativePath === 'folder1\\')).equal(undefined);
// make sure both folders are removed from sqlproj and Build Remove entries were not added
const projFileText = (await fs.readFile(projFilePath)).toString();
should(projFileText.includes('<Folder Include="folder1" />')).equal(false, projFileText);
should(projFileText.includes('<Folder Include="folder2\\" />')).equal(false, projFileText);
should(projFileText.includes('<Build Remove="folder1\\**" />')).equal(false, projFileText);
should(projFileText.includes('<Build Remove="folder2\\**" />')).equal(false, projFileText);
});
});
describe('Project: add SQLCMD Variables', function (): void {