diff --git a/extensions/sql-database-projects/resources/templates/newSqlProjectTemplate.xml b/extensions/sql-database-projects/resources/templates/newSqlProjectTemplate.xml
index 6ebef84f7c..0e69c4d9f6 100644
--- a/extensions/sql-database-projects/resources/templates/newSqlProjectTemplate.xml
+++ b/extensions/sql-database-projects/resources/templates/newSqlProjectTemplate.xml
@@ -61,4 +61,7 @@
+
+
+
diff --git a/extensions/sql-database-projects/src/common/constants.ts b/extensions/sql-database-projects/src/common/constants.ts
index 5ed000bc8c..843deb8408 100644
--- a/extensions/sql-database-projects/src/common/constants.ts
+++ b/extensions/sql-database-projects/src/common/constants.ts
@@ -111,6 +111,11 @@ export const Include = 'Include';
export const Import = 'Import';
export const Project = 'Project';
export const Condition = 'Condition';
+export const Target = 'Target';
+export const Name = 'Name';
+export const AfterCleanTarget = 'AfterClean';
+export const Delete = 'Delete';
+export const Files = 'Files';
export const PackageReference = 'PackageReference';
export const Version = 'Version';
export const PrivateAssets = 'PrivateAssets';
@@ -128,6 +133,7 @@ export const SqlDbPresentCondition = '\'$(SQLDBExtensionsRefPath)\' != \'\'';
export const SqlDbNotPresentCondition = '\'$(SQLDBExtensionsRefPath)\' == \'\'';
export const RoundTripSqlDbPresentCondition = '\'$(NetCoreBuild)\' != \'true\' AND \'$(SQLDBExtensionsRefPath)\' != \'\'';
export const RoundTripSqlDbNotPresentCondition = '\'$(NetCoreBuild)\' != \'true\' AND \'$(SQLDBExtensionsRefPath)\' == \'\'';
+export const ProjJsonToClean = '$(BaseIntermediateOutputPath)\\project.assets.json';
// SqlProj Reference Assembly Information
export const NETFrameworkAssembly = 'Microsoft.NETFramework.ReferenceAssemblies';
diff --git a/extensions/sql-database-projects/src/models/project.ts b/extensions/sql-database-projects/src/models/project.ts
index 07df32ffde..45d25dc29a 100644
--- a/extensions/sql-database-projects/src/models/project.ts
+++ b/extensions/sql-database-projects/src/models/project.ts
@@ -78,6 +78,7 @@ export class Project {
await fs.copyFile(this.projectFilePath, this.projectFilePath + '_backup');
await this.updateImportToSupportRoundTrip();
await this.updatePackageReferenceInProjFile();
+ await this.updateAfterCleanTargetInProjFile();
}
private async updateImportToSupportRoundTrip(): Promise {
@@ -99,6 +100,30 @@ export class Project {
await this.updateImportedTargetsToProjFile(constants.NetCoreCondition, constants.NetCoreTargets, undefined);
}
+ private async updateAfterCleanTargetInProjFile(): Promise {
+ // Search if clean target already present, update it
+ for (let i = 0; i < this.projFileXmlDoc.documentElement.getElementsByTagName(constants.Target).length; i++) {
+ const afterCleanNode = this.projFileXmlDoc.documentElement.getElementsByTagName(constants.Target)[i];
+ const name = afterCleanNode.getAttribute(constants.Name);
+ if (name === constants.AfterCleanTarget) {
+ return await this.createCleanFileNode(afterCleanNode);
+ }
+ }
+
+ // If clean target not found, create new
+ const afterCleanNode = this.projFileXmlDoc.createElement(constants.Target);
+ afterCleanNode.setAttribute(constants.Name, constants.AfterCleanTarget);
+ this.projFileXmlDoc.documentElement.appendChild(afterCleanNode);
+ await this.createCleanFileNode(afterCleanNode);
+ }
+
+ private async createCleanFileNode(parentNode: any): Promise {
+ const deleteFileNode = this.projFileXmlDoc.createElement(constants.Delete);
+ deleteFileNode.setAttribute(constants.Files, constants.ProjJsonToClean);
+ parentNode.appendChild(deleteFileNode);
+ await this.serializeToProjFile(this.projFileXmlDoc);
+ }
+
/**
* Adds a folder to the project, and saves the project file
* @param relativeFolderPath Relative path of the folder
diff --git a/extensions/sql-database-projects/src/test/baselines/SSDTProjectAfterUpdateBaseline.xml b/extensions/sql-database-projects/src/test/baselines/SSDTProjectAfterUpdateBaseline.xml
index 9728cd79ab..f3bf53f0b5 100644
--- a/extensions/sql-database-projects/src/test/baselines/SSDTProjectAfterUpdateBaseline.xml
+++ b/extensions/sql-database-projects/src/test/baselines/SSDTProjectAfterUpdateBaseline.xml
@@ -73,4 +73,7 @@
+
+
+
diff --git a/extensions/sql-database-projects/src/test/baselines/SSDTProjectBaselineWithCleanTarget.xml b/extensions/sql-database-projects/src/test/baselines/SSDTProjectBaselineWithCleanTarget.xml
new file mode 100644
index 0000000000..c03b6dfd1b
--- /dev/null
+++ b/extensions/sql-database-projects/src/test/baselines/SSDTProjectBaselineWithCleanTarget.xml
@@ -0,0 +1,75 @@
+
+
+
+ Debug
+ AnyCPU
+ TestProjectName
+ 2.0
+ 4.1
+ {BA5EBA11-C0DE-5EA7-ACED-BABB1E70A575}
+ Microsoft.Data.Tools.Schema.Sql.Sql130DatabaseSchemaProvider
+ Database
+
+
+ TestProjectName
+ TestProjectName
+ 1033, CI
+ BySchemaAndSchemaType
+ True
+ v4.5
+ CS
+ Properties
+ False
+ True
+ True
+
+
+ bin\Release\
+ $(MSBuildProjectName).sql
+ False
+ pdbonly
+ true
+ false
+ true
+ prompt
+ 4
+
+
+ bin\Debug\
+ $(MSBuildProjectName).sql
+ false
+ true
+ full
+ false
+ true
+ true
+ prompt
+ 4
+
+
+ 11.0
+
+ True
+ 11.0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/extensions/sql-database-projects/src/test/baselines/SSDTProjectBaselineWithCleanTargetAfterUpdate.xml b/extensions/sql-database-projects/src/test/baselines/SSDTProjectBaselineWithCleanTargetAfterUpdate.xml
new file mode 100644
index 0000000000..c39272fd87
--- /dev/null
+++ b/extensions/sql-database-projects/src/test/baselines/SSDTProjectBaselineWithCleanTargetAfterUpdate.xml
@@ -0,0 +1,80 @@
+
+
+
+ Debug
+ AnyCPU
+ TestProjectName
+ 2.0
+ 4.1
+ {BA5EBA11-C0DE-5EA7-ACED-BABB1E70A575}
+ Microsoft.Data.Tools.Schema.Sql.Sql130DatabaseSchemaProvider
+ Database
+
+
+ TestProjectName
+ TestProjectName
+ 1033, CI
+ BySchemaAndSchemaType
+ True
+ v4.5
+ CS
+ Properties
+ False
+ True
+ True
+
+
+ bin\Release\
+ $(MSBuildProjectName).sql
+ False
+ pdbonly
+ true
+ false
+ true
+ prompt
+ 4
+
+
+ bin\Debug\
+ $(MSBuildProjectName).sql
+ false
+ true
+ full
+ false
+ true
+ true
+ prompt
+ 4
+
+
+ 11.0
+
+ True
+ 11.0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/extensions/sql-database-projects/src/test/baselines/baselines.ts b/extensions/sql-database-projects/src/test/baselines/baselines.ts
index b233850422..8a2872bcb9 100644
--- a/extensions/sql-database-projects/src/test/baselines/baselines.ts
+++ b/extensions/sql-database-projects/src/test/baselines/baselines.ts
@@ -12,6 +12,8 @@ export let openProjectFileBaseline: string;
export let openDataSourcesBaseline: string;
export let SSDTProjectFileBaseline: string;
export let SSDTProjectAfterUpdateBaseline: string;
+export let SSDTProjectBaselineWithCleanTarget: string;
+export let SSDTProjectBaselineWithCleanTargetAfterUpdate: string;
const baselineFolderPath = __dirname;
@@ -21,6 +23,8 @@ export async function loadBaselines() {
openDataSourcesBaseline = await loadBaseline(baselineFolderPath, 'openDataSourcesBaseline.json');
SSDTProjectFileBaseline = await loadBaseline(baselineFolderPath, 'SSDTProjectBaseline.xml');
SSDTProjectAfterUpdateBaseline = await loadBaseline(baselineFolderPath, 'SSDTProjectAfterUpdateBaseline.xml');
+ SSDTProjectBaselineWithCleanTarget = await loadBaseline(baselineFolderPath, 'SSDTProjectBaselineWithCleanTarget.xml');
+ SSDTProjectBaselineWithCleanTargetAfterUpdate = await loadBaseline(baselineFolderPath, 'SSDTProjectBaselineWithCleanTargetAfterUpdate.xml');
}
async function loadBaseline(baselineFolderPath: string, fileName: string): Promise {
diff --git a/extensions/sql-database-projects/src/test/baselines/newSqlProjectBaseline.xml b/extensions/sql-database-projects/src/test/baselines/newSqlProjectBaseline.xml
index 7f2fb66c3e..7521477225 100644
--- a/extensions/sql-database-projects/src/test/baselines/newSqlProjectBaseline.xml
+++ b/extensions/sql-database-projects/src/test/baselines/newSqlProjectBaseline.xml
@@ -61,4 +61,7 @@
+
+
+
diff --git a/extensions/sql-database-projects/src/test/baselines/openSqlProjectBaseline.xml b/extensions/sql-database-projects/src/test/baselines/openSqlProjectBaseline.xml
index 86b4eeaeb0..a2c072f2d5 100644
--- a/extensions/sql-database-projects/src/test/baselines/openSqlProjectBaseline.xml
+++ b/extensions/sql-database-projects/src/test/baselines/openSqlProjectBaseline.xml
@@ -79,4 +79,7 @@
master
+
+
+
diff --git a/extensions/sql-database-projects/src/test/project.test.ts b/extensions/sql-database-projects/src/test/project.test.ts
index a1cdd69664..789afed671 100644
--- a/extensions/sql-database-projects/src/test/project.test.ts
+++ b/extensions/sql-database-projects/src/test/project.test.ts
@@ -157,16 +157,24 @@ describe('Project: round trip updates', function (): void {
});
it('Should update SSDT project to work in ADS', async function (): Promise {
- projFilePath = await testUtils.createTestSqlProjFile(baselines.SSDTProjectFileBaseline);
- const project: Project = new Project(projFilePath);
- await project.readProjFile();
+ await testUpdateInRoundTrip(baselines.SSDTProjectFileBaseline, baselines.SSDTProjectAfterUpdateBaseline);
+ });
- await project.updateProjectForRoundTrip();
-
- should(await exists(projFilePath + '_backup')).equal(true); // backup file should be generated before the project is updated
- should(project.importedTargets.length).equal(3); // additional target added by updateProjectForRoundTrip method
-
- let projFileText = (await fs.readFile(projFilePath)).toString();
- should(projFileText).equal(baselines.SSDTProjectAfterUpdateBaseline.trim());
+ it('Should update SSDT project to work in ADS handling pre-exsiting targets', async function (): Promise {
+ await testUpdateInRoundTrip(baselines.SSDTProjectBaselineWithCleanTarget, baselines.SSDTProjectBaselineWithCleanTargetAfterUpdate);
});
});
+
+async function testUpdateInRoundTrip(fileBeforeupdate: string, fileAfterUpdate:string) : Promise {
+ projFilePath = await testUtils.createTestSqlProjFile(fileBeforeupdate);
+ const project: Project = new Project(projFilePath);
+ await project.readProjFile();
+
+ await project.updateProjectForRoundTrip();
+
+ should(await exists(projFilePath + '_backup')).equal(true); // backup file should be generated before the project is updated
+ should(project.importedTargets.length).equal(3); // additional target added by updateProjectForRoundTrip method
+
+ let projFileText = (await fs.readFile(projFilePath)).toString();
+ should(projFileText).equal(fileAfterUpdate.trim());
+}