Adding Move, Exclude, and Rename support for folders (#22867)

* Adding exclude folder and base for move folder

* checkpoint

* rename

* Fixing up tests

* Adding exclude test to projController

* Adding tests

* fixing order of service.moveX() calls

* Updating move() order in sqlproj service

* PR feedback

* unskipping

* reskipping test

* Fixing folder move conditional

* updating comments
This commit is contained in:
Benjin Dubishar
2023-04-28 16:05:38 -07:00
committed by GitHub
parent 934d8ff8fa
commit 29ff6ca16c
9 changed files with 175 additions and 161 deletions

View File

@@ -349,8 +349,7 @@ describe('Project: sdk style project content operations', function (): void {
should(project.files.length).equal(0, 'There should not be any SQL object scripts after the excludes');
});
// skipped because exclude folder not yet supported
it.skip('Should handle excluding glob included folders', async function (): Promise<void> {
it('Should handle excluding glob included folders', async function (): Promise<void> {
const testFolderPath = await testUtils.generateTestFolderPath(this.test);
const projFilePath = await testUtils.createTestSqlProjFile(this.test, baselines.openSdkStyleSqlProjectBaseline, testFolderPath);
await testUtils.createDummyFileStructureWithPrePostDeployScripts(this.test, false, undefined, path.dirname(projFilePath));
@@ -362,23 +361,16 @@ describe('Project: sdk style project content operations', function (): void {
should(project.noneDeployScripts.length).equal(2);
// try to exclude a glob included folder
//await project.excludeFolder('folder1\\');
await project.excludeFolder('folder1');
// verify folder and contents are excluded
should(project.folders.length).equal(1);
should(project.files.length).equal(6);
should(project.noneDeployScripts.length).equal(1, 'Script.PostDeployment2.sql should have been excluded');
should(project.files.find(f => f.relativePath === 'folder1\\')).equal(undefined);
// verify sqlproj has glob exclude for folder, but not for files and inner folder
const projFileText = (await fs.readFile(projFilePath)).toString();
should(projFileText.includes('<Build Remove="folder1\\**" />')).equal(true, projFileText);
should(projFileText.includes('<Build Remove="folder1\\file1.sql" />')).equal(false, projFileText);
should(projFileText.includes('<Build Remove="folder1\\nestedFolder\\**" />')).equal(false, projFileText);
should(project.folders.find(f => f.relativePath === 'folder1')).equal(undefined);
});
// skipped because exclude folder not yet supported
it.skip('Should handle excluding nested glob included folders', async function (): Promise<void> {
it('Should handle excluding folders', async function (): Promise<void> {
const testFolderPath = await testUtils.generateTestFolderPath(this.test,);
const projFilePath = await testUtils.createTestSqlProjFile(this.test, baselines.openSdkStyleSqlProjectBaseline, testFolderPath);
await testUtils.createDummyFileStructureWithPrePostDeployScripts(this.test, false, undefined, path.dirname(projFilePath));
@@ -389,21 +381,16 @@ describe('Project: sdk style project content operations', function (): void {
should(project.folders.length).equal(3);
// try to exclude a glob included folder
//await project.excludeFolder('folder1\\nestedFolder\\');
await project.excludeFolder('folder1\\nestedFolder');
// verify folder and contents are excluded
should(project.folders.length).equal(2);
should(project.files.length).equal(11);
should(project.files.find(f => f.relativePath === 'folder1\\nestedFolder\\')).equal(undefined);
// verify sqlproj has glob exclude for folder, but not for files
const projFileText = (await fs.readFile(projFilePath)).toString();
should(projFileText.includes('<Build Remove="folder1\\nestedFolder\\**" />')).equal(true, projFileText);
should(projFileText.includes('<Build Remove="folder1\\nestedFolder\\otherFile1.sql" />')).equal(false, projFileText);
should(project.folders.find(f => f.relativePath === 'folder1\\nestedFolder')).equal(undefined);
});
// skipped because exclude folder not yet supported
it.skip('Should handle excluding explicitly included folders', async function (): Promise<void> {
it('Should handle excluding explicitly included folders', async function (): Promise<void> {
const testFolderPath = await testUtils.generateTestFolderPath(this.test,);
const projFilePath = await testUtils.createTestSqlProjFile(this.test, baselines.openSdkStyleSqlProjectWithFilesSpecifiedBaseline, testFolderPath);
await testUtils.createDummyFileStructure(this.test, false, undefined, path.dirname(projFilePath));
@@ -412,36 +399,27 @@ describe('Project: sdk style project content operations', function (): void {
should(project.files.length).equal(11);
should(project.folders.length).equal(2);
should(project.files.find(f => f.relativePath === 'folder1\\')!).not.equal(undefined);
should(project.files.find(f => f.relativePath === 'folder2\\')!).not.equal(undefined);
should(project.folders.find(f => f.relativePath === 'folder1')!).not.equal(undefined);
should(project.folders.find(f => f.relativePath === 'folder2')!).not.equal(undefined);
// try to exclude an explicitly included folder without trailing \ in sqlproj
//await project.excludeFolder('folder1\\');
await project.excludeFolder('folder1');
// verify folder and contents are excluded
should(project.folders.length).equal(1);
should(project.files.length).equal(6);
should(project.files.find(f => f.relativePath === 'folder1\\')).equal(undefined);
should(project.folders.find(f => f.relativePath === 'folder1')).equal(undefined);
// try to exclude an explicitly included folder with trailing \ in sqlproj
//await project.excludeFolder('folder2\\');
await project.excludeFolder('folder2');
// verify folder and contents are excluded
should(project.folders.length).equal(0);
should(project.files.length).equal(1);
should(project.files.find(f => f.relativePath === 'folder2\\')).equal(undefined);
// make sure both folders are removed from sqlproj and remove entry is 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(true, projFileText);
should(projFileText.includes('<Build Remove="folder2\\**" />')).equal(true, projFileText);
should(project.folders.find(f => f.relativePath === 'folder2')).equal(undefined);
});
// TODO: skipped until fix for folder trailing slashes comes in from DacFx
it.skip('Should handle deleting explicitly included folders', async function (): Promise<void> {
it('Should handle deleting explicitly included folders', async function (): Promise<void> {
const testFolderPath = await testUtils.generateTestFolderPath(this.test,);
const projFilePath = await testUtils.createTestSqlProjFile(this.test, baselines.openSdkStyleSqlProjectWithFilesSpecifiedBaseline, testFolderPath);
await testUtils.createDummyFileStructureWithPrePostDeployScripts(this.test, false, undefined, path.dirname(projFilePath));
@@ -450,32 +428,24 @@ describe('Project: sdk style project content operations', function (): void {
should(project.files.length).equal(13);
should(project.folders.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);
should(project.folders.find(f => f.relativePath === 'folder1')!).not.equal(undefined);
should(project.folders.find(f => f.relativePath === 'folder2')!).not.equal(undefined);
// try to delete an explicitly included folder with the trailing \ in sqlproj
await project.deleteFolder('folder2\\');
await project.deleteFolder('folder2');
// verify the project not longer has folder2 and its contents
should(project.folders.length).equal(2);
should(project.files.length).equal(8);
should(project.files.find(f => f.relativePath === 'folder2\\')).equal(undefined);
should(project.folders.find(f => f.relativePath === 'folder2')).equal(undefined);
// try to delete an explicitly included folder without trailing \ in sqlproj
await project.deleteFolder('folder1\\');
await project.deleteFolder('folder1');
// verify the project not longer has folder1 and its contents
should(project.folders.length).equal(0);
should(project.files.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);
should(project.folders.find(f => f.relativePath === 'folder1')).equal(undefined);
});
// TODO: remove once DacFx exposes both absolute and relative outputPath
@@ -890,7 +860,7 @@ describe('Project: database references', function (): void {
should(project.databaseReferences.length).equal(1, 'There should be one database reference after trying to add a reference to testProject again');
});
it.skip('Should update sqlcmd variable values if value changes', async function (): Promise<void> {
it('Should update sqlcmd variable values if value changes', async function (): Promise<void> {
const projFilePath = await testUtils.createTestSqlProjFile(this.test, baselines.newProjectFileBaseline);
const project = await Project.openProject(projFilePath);
const databaseVariable = 'test3Db';
@@ -933,12 +903,6 @@ describe('Project: database references', function (): void {
should(project.databaseReferences.length).equal(1, 'There should be a database reference after adding a reference to test3');
should(project.databaseReferences[0].referenceName).equal('test3', 'The database reference should be test3');
should(project.sqlCmdVariables.size).equal(2, 'There should still be 2 sqlcmdvars after adding the dacpac reference again with different sqlcmdvar values');
projFileText = (await fs.readFile(projFilePath)).toString();
should(projFileText).containEql('<SqlCmdVariable Include="test3Db">');
should(projFileText).containEql('<DefaultValue>newDbName</DefaultValue>');
should(projFileText).containEql('<SqlCmdVariable Include="otherServer">');
should(projFileText).containEql('<DefaultValue>newServerName</DefaultValue>');
});
});
@@ -1140,7 +1104,6 @@ describe('Project: round trip updates', function (): void {
await testUpdateInRoundTrip(this.test, baselines.SSDTProjectFileBaseline);
});
// skipped until https://mssqltools.visualstudio.com/SQL%20Tools%20Semester%20Work%20Tracking/_workitems/edit/15749 is fixed
it.skip('Should update SSDT project with new system database references', async function (): Promise<void> {
await testUpdateInRoundTrip(this.test, baselines.SSDTUpdatedProjectBaseline);
});