diff --git a/extensions/sql-database-projects/src/models/project.ts b/extensions/sql-database-projects/src/models/project.ts index 9d11e151cb..d5d7be147b 100644 --- a/extensions/sql-database-projects/src/models/project.ts +++ b/extensions/sql-database-projects/src/models/project.ts @@ -122,13 +122,15 @@ export class Project implements ISqlProject { // check if this is an sdk style project https://docs.microsoft.com/en-us/dotnet/core/project-sdk/overview this._isSdkStyleProject = this.CheckForSdkStyleProject(); + // get pre and post deploy scripts specified in the sqlproj + this._preDeployScripts = this.readPreDeployScripts(); + this._postDeployScripts = this.readPostDeployScripts(); + this._noneDeployScripts = this.readNoneDeployScripts(); + // get files and folders this._files = await this.readFilesInProject(); this.files.push(...await this.readFolders()); - this._preDeployScripts = this.readPreDeployScripts(); - this._postDeployScripts = this.readPostDeployScripts(); - this._noneDeployScripts = this.readNoneDeployScripts(); this._databaseReferences = this.readDatabaseReferences(); this._importedTargets = this.readImportedTargets(); @@ -225,6 +227,13 @@ export class Project implements ISqlProject { } } + if (this.isSdkStyleProject) { + // remove any pre/post/none deploy scripts that were specified in the sqlproj so they aren't counted twice + this.preDeployScripts.forEach(f => filesSet.delete(f.relativePath)); + this.postDeployScripts.forEach(f => filesSet.delete(f.relativePath)); + this.noneDeployScripts.forEach(f => filesSet.delete(f.relativePath)); + } + // create a FileProjectEntry for each file const fileEntries: FileProjectEntry[] = []; filesSet.forEach(f => { diff --git a/extensions/sql-database-projects/src/test/baselines/openSdkStyleSqlProjectWithGlobsSpecifiedBaseline.xml b/extensions/sql-database-projects/src/test/baselines/openSdkStyleSqlProjectWithGlobsSpecifiedBaseline.xml index e93de1e8c3..88a388508a 100644 --- a/extensions/sql-database-projects/src/test/baselines/openSdkStyleSqlProjectWithGlobsSpecifiedBaseline.xml +++ b/extensions/sql-database-projects/src/test/baselines/openSdkStyleSqlProjectWithGlobsSpecifiedBaseline.xml @@ -20,6 +20,13 @@ + + + + + + + False diff --git a/extensions/sql-database-projects/src/test/project.test.ts b/extensions/sql-database-projects/src/test/project.test.ts index 7e8f32d21f..50310f8e7d 100644 --- a/extensions/sql-database-projects/src/test/project.test.ts +++ b/extensions/sql-database-projects/src/test/project.test.ts @@ -844,7 +844,7 @@ describe('Project: sdk style project content operations', function (): void { // Files and folders should(project.files.filter(f => f.type === EntryType.Folder).length).equal(3); - should(project.files.filter(f => f.type === EntryType.File).length).equal(17); + should(project.files.filter(f => f.type === EntryType.File).length).equal(13); // SqlCmdVariables should(Object.keys(project.sqlCmdVariables).length).equal(2); @@ -883,6 +883,27 @@ describe('Project: sdk style project content operations', function (): void { should(project.files.filter(f => f.relativePath === 'folder1\\').length).equal(1); }); + it('Should handle pre/post/none deploy scripts outside of project folder', async function (): Promise { + const testFolderPath = await testUtils.generateTestFolderPath(); + const mainProjectPath = path.join(testFolderPath, 'project'); + const otherFolderPath = path.join(testFolderPath, 'other'); + projFilePath = await testUtils.createTestSqlProjFile(baselines.openSdkStyleSqlProjectWithGlobsSpecifiedBaseline, mainProjectPath); + await testUtils.createDummyFileStructure(false, undefined, path.dirname(projFilePath)); + + // create files outside of project folder that are included in the project file + await fs.mkdir(otherFolderPath); + await testUtils.createOtherDummyFiles(otherFolderPath); + + const project: Project = await Project.openProject(projFilePath); + + // verify files, folders, pre/post/none deploy scripts were loaded correctly + should(project.files.filter(f => f.type === EntryType.Folder).length).equal(2); + should(project.files.filter(f => f.type === EntryType.File).length).equal(18); + should(project.preDeployScripts.length).equal(1); + should(project.postDeployScripts.length).equal(1); + should(project.noneDeployScripts.length).equal(1); + }); + it('Should handle globbing patterns listed in sqlproj', async function (): Promise { const testFolderPath = await testUtils.generateTestFolderPath(); const mainProjectPath = path.join(testFolderPath, 'project'); @@ -1056,15 +1077,17 @@ describe('Project: sdk style project content operations', function (): void { const project: Project = await Project.openProject(projFilePath); - should(project.files.filter(f => f.type === EntryType.File).length).equal(17); + 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.noneDeployScripts.length).equal(2); // try to exclude a glob included folder await project.exclude(project.files.find(f => f.relativePath === 'folder1\\')!); // verify folder and contents are excluded should(project.files.filter(f => f.type === EntryType.Folder).length).equal(1); - should(project.files.filter(f => f.type === EntryType.File).length).equal(9); + should(project.files.filter(f => f.type === EntryType.File).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 @@ -1082,7 +1105,7 @@ describe('Project: sdk style project content operations', function (): void { const project: Project = await Project.openProject(projFilePath); - should(project.files.filter(f => f.type === EntryType.File).length).equal(17); + should(project.files.filter(f => f.type === EntryType.File).length).equal(13); should(project.files.filter(f => f.type === EntryType.Folder).length).equal(3); // try to exclude a glob included folder @@ -1090,7 +1113,7 @@ describe('Project: sdk style project content operations', function (): void { // verify folder and contents are excluded should(project.files.filter(f => f.type === EntryType.Folder).length).equal(2); - should(project.files.filter(f => f.type === EntryType.File).length).equal(15); + should(project.files.filter(f => f.type === EntryType.File).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 diff --git a/extensions/sql-database-projects/src/test/testUtils.ts b/extensions/sql-database-projects/src/test/testUtils.ts index e1242be5c0..a298a42b1a 100644 --- a/extensions/sql-database-projects/src/test/testUtils.ts +++ b/extensions/sql-database-projects/src/test/testUtils.ts @@ -198,6 +198,9 @@ export async function createListOfFiles(filePath?: string): Promise { * - folder2 * -file1.sql * -file2.sql + * - Script.PreDeployment1.sql + * - Script.PostDeployment1.sql + * - Script.PostDeployment2.sql * */ export async function createOtherDummyFiles(testFolderPath: string): Promise { @@ -221,5 +224,13 @@ export async function createOtherDummyFiles(testFolderPath: string): Promise