mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-17 02:51:36 -05:00
fix excluding pre/post/none deploy scripts in sdk style projects (#18117)
This commit is contained in:
@@ -238,6 +238,10 @@ export class Project implements ISqlProject {
|
|||||||
this.preDeployScripts.forEach(f => filesSet.delete(f.relativePath));
|
this.preDeployScripts.forEach(f => filesSet.delete(f.relativePath));
|
||||||
this.postDeployScripts.forEach(f => filesSet.delete(f.relativePath));
|
this.postDeployScripts.forEach(f => filesSet.delete(f.relativePath));
|
||||||
this.noneDeployScripts.forEach(f => filesSet.delete(f.relativePath));
|
this.noneDeployScripts.forEach(f => filesSet.delete(f.relativePath));
|
||||||
|
|
||||||
|
// remove any none remove scripts (these would be pre/post/none deploy scripts that were excluded)
|
||||||
|
const noneRemoveScripts = this.readNoneRemoveScripts();
|
||||||
|
noneRemoveScripts.forEach(f => filesSet.delete(f.relativePath));
|
||||||
}
|
}
|
||||||
|
|
||||||
// create a FileProjectEntry for each file
|
// create a FileProjectEntry for each file
|
||||||
@@ -379,7 +383,10 @@ export class Project implements ISqlProject {
|
|||||||
try {
|
try {
|
||||||
const noneItems = itemGroup.getElementsByTagName(constants.None);
|
const noneItems = itemGroup.getElementsByTagName(constants.None);
|
||||||
for (let n = 0; n < noneItems.length; n++) {
|
for (let n = 0; n < noneItems.length; n++) {
|
||||||
noneDeployScripts.push(this.createFileProjectEntry(noneItems[n].getAttribute(constants.Include)!, EntryType.File));
|
const includeAttribute = noneItems[n].getAttribute(constants.Include);
|
||||||
|
if (includeAttribute) {
|
||||||
|
noneDeployScripts.push(this.createFileProjectEntry(includeAttribute, EntryType.File));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
void window.showErrorMessage(constants.errorReadingProject(constants.NoneElements, this.projectFilePath));
|
void window.showErrorMessage(constants.errorReadingProject(constants.NoneElements, this.projectFilePath));
|
||||||
@@ -390,6 +397,30 @@ export class Project implements ISqlProject {
|
|||||||
return noneDeployScripts;
|
return noneDeployScripts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns all the files specified as <None Remove="file.sql" /> in the sqlproj
|
||||||
|
*/
|
||||||
|
private readNoneRemoveScripts(): FileProjectEntry[] {
|
||||||
|
const noneRemoveScripts: FileProjectEntry[] = [];
|
||||||
|
|
||||||
|
for (let ig = 0; ig < this.projFileXmlDoc!.documentElement.getElementsByTagName(constants.ItemGroup).length; ig++) {
|
||||||
|
const itemGroup = this.projFileXmlDoc!.documentElement.getElementsByTagName(constants.ItemGroup)[ig];
|
||||||
|
|
||||||
|
// find all none remove scripts to specified in the sqlproj
|
||||||
|
try {
|
||||||
|
const noneItems = itemGroup.getElementsByTagName(constants.None);
|
||||||
|
for (let n = 0; n < noneItems.length; n++) {
|
||||||
|
noneRemoveScripts.push(this.createFileProjectEntry(noneItems[n].getAttribute(constants.Remove)!, EntryType.File));
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
void window.showErrorMessage(constants.errorReadingProject(constants.NoneElements, this.projectFilePath));
|
||||||
|
console.error(utils.getErrorMessage(e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return noneRemoveScripts;
|
||||||
|
}
|
||||||
|
|
||||||
private readDatabaseReferences(): IDatabaseReferenceProjectEntry[] {
|
private readDatabaseReferences(): IDatabaseReferenceProjectEntry[] {
|
||||||
const databaseReferenceEntries: IDatabaseReferenceProjectEntry[] = [];
|
const databaseReferenceEntries: IDatabaseReferenceProjectEntry[] = [];
|
||||||
|
|
||||||
@@ -969,6 +1000,8 @@ export class Project implements ISqlProject {
|
|||||||
const noneNodes = this.projFileXmlDoc!.documentElement.getElementsByTagName(constants.None);
|
const noneNodes = this.projFileXmlDoc!.documentElement.getElementsByTagName(constants.None);
|
||||||
const nodes = [fileNodes, preDeployNodes, postDeployNodes, noneNodes];
|
const nodes = [fileNodes, preDeployNodes, postDeployNodes, noneNodes];
|
||||||
|
|
||||||
|
const isBuildElement = this.files.find(f => f.relativePath === path);
|
||||||
|
|
||||||
let deleted = false;
|
let deleted = false;
|
||||||
|
|
||||||
// remove the <Build Include="..."> entry if there is one
|
// remove the <Build Include="..."> entry if there is one
|
||||||
@@ -992,13 +1025,17 @@ export class Project implements ISqlProject {
|
|||||||
if (deleted) {
|
if (deleted) {
|
||||||
await this.serializeToProjFile(this.projFileXmlDoc!);
|
await this.serializeToProjFile(this.projFileXmlDoc!);
|
||||||
}
|
}
|
||||||
|
this._preDeployScripts = this.readPreDeployScripts();
|
||||||
|
this._postDeployScripts = this.readPostDeployScripts();
|
||||||
|
this._noneDeployScripts = this.readNoneDeployScripts();
|
||||||
const currentFiles = await this.readFilesInProject();
|
const currentFiles = await this.readFilesInProject();
|
||||||
|
|
||||||
// only add a node to exclude the file if it's still included by a glob
|
// only add a Remove node to exclude the file if it's still included by a glob
|
||||||
if (currentFiles.find(f => f.relativePath === utils.convertSlashesForSqlProj(path))) {
|
if (currentFiles.find(f => f.relativePath === utils.convertSlashesForSqlProj(path))) {
|
||||||
const removeFileNode = this.projFileXmlDoc!.createElement(constants.Build);
|
const removeFileNode = isBuildElement ? this.projFileXmlDoc!.createElement(constants.Build) : this.projFileXmlDoc!.createElement(constants.None);
|
||||||
removeFileNode.setAttribute(constants.Remove, utils.convertSlashesForSqlProj(path));
|
removeFileNode.setAttribute(constants.Remove, utils.convertSlashesForSqlProj(path));
|
||||||
this.findOrCreateItemGroup(constants.Build).appendChild(removeFileNode);
|
this.findOrCreateItemGroup(constants.Build).appendChild(removeFileNode);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@@ -1503,6 +1540,10 @@ export class Project implements ISqlProject {
|
|||||||
* @returns Project entry for the last folder in the path, if path is under the project folder; otherwise `undefined`.
|
* @returns Project entry for the last folder in the path, if path is under the project folder; otherwise `undefined`.
|
||||||
*/
|
*/
|
||||||
private async ensureFolderItems(relativeFolderPath: string): Promise<FileProjectEntry | undefined> {
|
private async ensureFolderItems(relativeFolderPath: string): Promise<FileProjectEntry | undefined> {
|
||||||
|
if (!relativeFolderPath) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const absoluteFolderPath = path.join(this.projectFolderPath, relativeFolderPath);
|
const absoluteFolderPath = path.join(this.projectFolderPath, relativeFolderPath);
|
||||||
const normalizedProjectFolderPath = path.normalize(this.projectFolderPath);
|
const normalizedProjectFolderPath = path.normalize(this.projectFolderPath);
|
||||||
|
|
||||||
|
|||||||
@@ -988,6 +988,45 @@ describe('Project: sdk style project content operations', function (): void {
|
|||||||
should(project.files.filter(f => f.relativePath === 'file1.sql').length).equal(0);
|
should(project.files.filter(f => f.relativePath === 'file1.sql').length).equal(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Should exclude pre/post/none deploy scripts correctly', async function (): Promise<void> {
|
||||||
|
const folderPath = await testUtils.generateTestFolderPath();
|
||||||
|
projFilePath = await testUtils.createTestSqlProjFile(baselines.newSdkStyleProjectSdkNodeBaseline, folderPath);
|
||||||
|
|
||||||
|
const project: Project = await Project.openProject(projFilePath);
|
||||||
|
await project.addScriptItem('Script.PreDeployment1.sql', 'fake contents', templates.preDeployScript);
|
||||||
|
await project.addScriptItem('Script.PreDeployment2.sql', 'fake contents', templates.preDeployScript);
|
||||||
|
await project.addScriptItem('Script.PostDeployment1.sql', 'fake contents', templates.postDeployScript);
|
||||||
|
|
||||||
|
// verify they were added to the sqlproj
|
||||||
|
let projFileText = (await fs.readFile(projFilePath)).toString();
|
||||||
|
should(projFileText.includes('<PreDeploy Include="Script.PreDeployment1.sql" />')).equal(true);
|
||||||
|
should(projFileText.includes('<None Include="Script.PreDeployment2.sql" />')).equal(true);
|
||||||
|
should(projFileText.includes('<PostDeploy Include="Script.PostDeployment1.sql" />')).equal(true);
|
||||||
|
should(project.preDeployScripts.length).equal(1, 'Script.PreDeployment1.sql should have been added');
|
||||||
|
should(project.noneDeployScripts.length).equal(1, 'Script.PreDeployment2.sql should have been added');
|
||||||
|
should(project.preDeployScripts.length).equal(1, 'Script.PostDeployment1.sql should have been added');
|
||||||
|
should(project.files.length).equal(0, 'There should not be any files');
|
||||||
|
|
||||||
|
// exclude the pre/post/none deploy script
|
||||||
|
await project.exclude(project.preDeployScripts.find(f => f.relativePath === 'Script.PreDeployment1.sql')!);
|
||||||
|
await project.exclude(project.noneDeployScripts.find(f => f.relativePath === 'Script.PreDeployment2.sql')!);
|
||||||
|
await project.exclude(project.postDeployScripts.find(f => f.relativePath === 'Script.PostDeployment1.sql')!);
|
||||||
|
|
||||||
|
// verify they are excluded in the sqlproj
|
||||||
|
projFileText = (await fs.readFile(projFilePath)).toString();
|
||||||
|
should(projFileText.includes('<PreDeploy Include="Script.PreDeployment1.sql" />')).equal(false);
|
||||||
|
should(projFileText.includes('<None Include="Script.PreDeployment2.sql" />')).equal(false);
|
||||||
|
should(projFileText.includes('<PostDeploy Include="Script.PostDeployment1.sql" />')).equal(false);
|
||||||
|
should(projFileText.includes('<None Remove="Script.PreDeployment1.sql" />')).equal(true);
|
||||||
|
should(projFileText.includes('<None Remove="Script.PreDeployment2.sql" />')).equal(true);
|
||||||
|
should(projFileText.includes('<None Remove="Script.PostDeployment1.sql" />')).equal(true);
|
||||||
|
|
||||||
|
should(project.preDeployScripts.length).equal(0, 'Script.PreDeployment1.sql should have been removed');
|
||||||
|
should(project.noneDeployScripts.length).equal(0, 'Script.PreDeployment2.sql should have been removed');
|
||||||
|
should(project.postDeployScripts.length).equal(0, 'Script.PostDeployment1.sql should have been removed');
|
||||||
|
should(project.files.length).equal(0, 'There should not be any files after the excludes');
|
||||||
|
});
|
||||||
|
|
||||||
it('Should handle excluding files included by glob patterns', async function (): Promise<void> {
|
it('Should handle excluding files included by glob patterns', async function (): Promise<void> {
|
||||||
const testFolderPath = await testUtils.generateTestFolderPath();
|
const testFolderPath = await testUtils.generateTestFolderPath();
|
||||||
const mainProjectPath = path.join(testFolderPath, 'project');
|
const mainProjectPath = path.join(testFolderPath, 'project');
|
||||||
|
|||||||
Reference in New Issue
Block a user