mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 18:46:40 -05:00
Update remove file for sdk style sql projects (#17688)
* add support for removing file in new style project * fix test * only load files, not whole project when checking if a <Build Remove> needs to be added * merge changes * fixes after merge
This commit is contained in:
@@ -899,7 +899,7 @@ export class Project implements ISqlProject {
|
|||||||
itemGroup.appendChild(newFileNode);
|
itemGroup.appendChild(newFileNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
private removeFileFromProjFile(path: string): void {
|
private async removeFileFromProjFile(path: string): Promise<void> {
|
||||||
const fileNodes = this.projFileXmlDoc!.documentElement.getElementsByTagName(constants.Build);
|
const fileNodes = this.projFileXmlDoc!.documentElement.getElementsByTagName(constants.Build);
|
||||||
const preDeployNodes = this.projFileXmlDoc!.documentElement.getElementsByTagName(constants.PreDeploy);
|
const preDeployNodes = this.projFileXmlDoc!.documentElement.getElementsByTagName(constants.PreDeploy);
|
||||||
const postDeployNodes = this.projFileXmlDoc!.documentElement.getElementsByTagName(constants.PostDeploy);
|
const postDeployNodes = this.projFileXmlDoc!.documentElement.getElementsByTagName(constants.PostDeploy);
|
||||||
@@ -907,14 +907,40 @@ export class Project implements ISqlProject {
|
|||||||
const nodes = [fileNodes, preDeployNodes, postDeployNodes, noneNodes];
|
const nodes = [fileNodes, preDeployNodes, postDeployNodes, noneNodes];
|
||||||
|
|
||||||
let deleted = false;
|
let deleted = false;
|
||||||
|
|
||||||
|
// remove the <Build Include="..."> entry if there is one
|
||||||
for (let i = 0; i < nodes.length; i++) {
|
for (let i = 0; i < nodes.length; i++) {
|
||||||
deleted = this.removeNode(path, nodes[i]);
|
deleted = this.removeNode(path, nodes[i]);
|
||||||
|
|
||||||
if (deleted) {
|
if (deleted) {
|
||||||
return;
|
// still might need to add a <Build Remove="..."> node if this is an sdk style project
|
||||||
|
if (this.isSdkStyleProject) {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if it's an sdk style project, we'll need to add a <Build Remove="..."> entry to remove this file if it's
|
||||||
|
// still included by a glob
|
||||||
|
if (this.isSdkStyleProject) {
|
||||||
|
// write any changes from removing an include node and get the current files included in the project
|
||||||
|
if (deleted) {
|
||||||
|
await this.serializeToProjFile(this.projFileXmlDoc);
|
||||||
|
}
|
||||||
|
const currentFiles = await this.readFilesInProject();
|
||||||
|
|
||||||
|
// only add a node to exclude the file if it's still included by a glob
|
||||||
|
if (currentFiles.find(f => f.relativePath === utils.convertSlashesForSqlProj(path))) {
|
||||||
|
const removeFileNode = this.projFileXmlDoc!.createElement(constants.Build);
|
||||||
|
removeFileNode.setAttribute(constants.Remove, utils.convertSlashesForSqlProj(path));
|
||||||
|
this.findOrCreateItemGroup(constants.Build).appendChild(removeFileNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
throw new Error(constants.unableToFindObject(path, constants.fileObject));
|
throw new Error(constants.unableToFindObject(path, constants.fileObject));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1233,7 +1259,7 @@ export class Project implements ISqlProject {
|
|||||||
for (const entry of entries) {
|
for (const entry of entries) {
|
||||||
switch (entry.type) {
|
switch (entry.type) {
|
||||||
case EntryType.File:
|
case EntryType.File:
|
||||||
this.removeFileFromProjFile((<FileProjectEntry>entry).relativePath);
|
await this.removeFileFromProjFile((<FileProjectEntry>entry).relativePath);
|
||||||
break;
|
break;
|
||||||
case EntryType.Folder:
|
case EntryType.Folder:
|
||||||
this.removeFolderFromProjFile((<FileProjectEntry>entry).relativePath);
|
this.removeFolderFromProjFile((<FileProjectEntry>entry).relativePath);
|
||||||
@@ -1260,6 +1286,9 @@ export class Project implements ISqlProject {
|
|||||||
}); // TODO: replace <any>
|
}); // TODO: replace <any>
|
||||||
|
|
||||||
await fs.writeFile(this._projectFilePath, xml);
|
await fs.writeFile(this._projectFilePath, xml);
|
||||||
|
|
||||||
|
// update projFileXmlDoc since the file was updated
|
||||||
|
this.projFileXmlDoc = new xmldom.DOMParser().parseFromString(xml);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
<Build Include="..\other\folder1\file*.sql" />
|
<Build Include="..\other\folder1\file*.sql" />
|
||||||
<Build Include="..\other\folder1\test?.sql" />
|
<Build Include="..\other\folder1\test?.sql" />
|
||||||
<Build Include="..\other\folder2\*.sql" />
|
<Build Include="..\other\folder2\*.sql" />
|
||||||
|
<Build Include="..\other\file1.sql" />
|
||||||
<Build Include="folder1\*.sql" />
|
<Build Include="folder1\*.sql" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -896,7 +896,7 @@ describe('Project: sdk style project content operations', function (): void {
|
|||||||
|
|
||||||
const project: Project = await Project.openProject(projFilePath);
|
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(18);
|
||||||
|
|
||||||
// make sure all the correct files from the globbing patterns were included
|
// make sure all the correct files from the globbing patterns were included
|
||||||
// ..\other\folder1\test?.sql
|
// ..\other\folder1\test?.sql
|
||||||
@@ -967,6 +967,48 @@ 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 handle excluding files included by glob patterns', async function (): Promise<void> {
|
||||||
|
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);
|
||||||
|
|
||||||
|
should(project.files.filter(f => f.type === EntryType.File).length).equal(18);
|
||||||
|
|
||||||
|
// exclude a file in the project's folder
|
||||||
|
should(project.files.filter(f => f.relativePath === 'folder1\\file1.sql').length).equal(1);
|
||||||
|
await project.exclude(project.files.find(f => f.relativePath === 'folder1\\file1.sql')!);
|
||||||
|
should(project.files.filter(f => f.relativePath === 'folder1\\file1.sql').length).equal(0);
|
||||||
|
|
||||||
|
// exclude explicitly included file from an outside folder
|
||||||
|
should(project.files.filter(f => f.relativePath === '..\\other\\file1.sql').length).equal(1);
|
||||||
|
await project.exclude(project.files.find(f => f.relativePath === '..\\other\\file1.sql')!);
|
||||||
|
should(project.files.filter(f => f.relativePath === '..\\other\\file1.sql').length).equal(0);
|
||||||
|
|
||||||
|
// exclude glob included file from an outside folder
|
||||||
|
should(project.files.filter(f => f.relativePath === '..\\other\\folder1\\test2.sql').length).equal(1);
|
||||||
|
await project.exclude(project.files.find(f => f.relativePath === '..\\other\\folder1\\test2.sql')!);
|
||||||
|
should(project.files.filter(f => f.relativePath === '..\\other\\folder1\\test2.sql').length).equal(0);
|
||||||
|
|
||||||
|
// make sure a <Build Remove="folder\file1.sql"> was added
|
||||||
|
const projFileText = (await fs.readFile(projFilePath)).toString();
|
||||||
|
should(projFileText.includes('<Build Remove="folder1\\file1.sql" />')).equal(true, projFileText);
|
||||||
|
|
||||||
|
// make sure <Build Include="..\other\file1.sql"> was removed and no <Build Remove"..."> was added for it
|
||||||
|
should(projFileText.includes('<Build Include="..\\other\\file1.sql" />')).equal(false, projFileText);
|
||||||
|
should(projFileText.includes('<Build Remove="..\\other\\file1.sql" />')).equal(false, projFileText);
|
||||||
|
|
||||||
|
// make sure a <Build Remove="..\other\folder1\test2.sql"> was added
|
||||||
|
should(projFileText.includes('<Build Remove="..\\other\\folder1\\test2.sql" />')).equal(true, projFileText);
|
||||||
|
});
|
||||||
|
|
||||||
it('Should only add Build entries to sqlproj for files not included by project folder glob and external streaming jobs', async function (): Promise<void> {
|
it('Should only add Build entries to sqlproj for files not included by project folder glob and external streaming jobs', async function (): Promise<void> {
|
||||||
projFilePath = await testUtils.createTestSqlProjFile(baselines.openSdkStyleSqlProjectBaseline);
|
projFilePath = await testUtils.createTestSqlProjFile(baselines.openSdkStyleSqlProjectBaseline);
|
||||||
const project = await Project.openProject(projFilePath);
|
const project = await Project.openProject(projFilePath);
|
||||||
|
|||||||
Reference in New Issue
Block a user