Add dacpac references to sqlproj with relative path (#14877)

* relative paths written to sqlproj, but can't delete yet

* only keep track of relative path

* remove leading slash

* add test

* use path.relative

* Add error message if dacpac reference is located on a different drive
This commit is contained in:
Kim Santiago
2021-03-30 17:06:04 -07:00
committed by GitHub
parent af4ad1fcb1
commit f4e1f85e0f
5 changed files with 87 additions and 1 deletions

View File

@@ -111,6 +111,7 @@ export const databaseNameServerNameVariableRequired = localize('databaseNameServ
export const otherServer = 'OtherServer';
export const otherSeverVariable = 'OtherServer';
export const databaseProject = localize('databaseProject', "Database project");
export const dacpacNotOnSameDrive = (projectLocation: string): string => { return localize('dacpacNotOnSameDrive', "Dacpac references need to be located on the same drive as the project file. The project file is located at {0}", projectLocation); };
// Create Project From Database dialog strings

View File

@@ -580,7 +580,10 @@ export class ProjectsController {
} else if ((<ISystemDatabaseReferenceSettings>settings).systemDb !== undefined) {
await project.addSystemDatabaseReference(<ISystemDatabaseReferenceSettings>settings);
} else {
await project.addDatabaseReference(<IDacpacReferenceSettings>settings);
// update dacpacFileLocation to relative path to project file
const dacpacRefSettings = settings as IDacpacReferenceSettings;
dacpacRefSettings.dacpacFileLocation = vscode.Uri.file(path.relative(project.projectFolderPath, dacpacRefSettings.dacpacFileLocation.fsPath));
await project.addDatabaseReference(dacpacRefSettings);
}
this.refreshProjectsTree(context);

View File

@@ -54,6 +54,27 @@ export class AddDatabaseReferenceDialog {
constructor(private project: Project) {
this.dialog = azdata.window.createModelViewDialog(constants.addDatabaseReferenceDialogName, 'addDatabaseReferencesDialog');
this.addDatabaseReferenceTab = azdata.window.createTab(constants.addDatabaseReferenceDialogName);
this.dialog.registerCloseValidator(async () => {
return this.validate();
});
}
validate(): boolean {
// only support adding dacpacs that are on the same drive as the sqlproj
if (this.currentReferenceType === ReferenceType.dacpac) {
const projectDrive = path.parse(this.project.projectFilePath).root;
const dacpacDrive = path.parse(this.dacpacTextbox!.value!).root;
if (projectDrive !== dacpacDrive) {
this.dialog.message = {
text: constants.dacpacNotOnSameDrive(this.project.projectFilePath),
level: azdata.window.MessageLevel.Error
};
return false;
}
}
return true;
}
public async openDialog(): Promise<void> {

View File

@@ -1020,6 +1020,11 @@ export class DacpacReferenceProjectEntry extends FileProjectEntry implements IDa
public get databaseName(): string {
return path.parse(utils.getPlatformSafeFileEntryPath(this.fsUri.fsPath)).name;
}
public pathForSqlProj(): string {
// need to remove the leading slash from path for build to work
return utils.convertSlashesForSqlProj(this.fsUri.path.substring(1));
}
}
export class SystemDatabaseReferenceProjectEntry extends FileProjectEntry implements IDatabaseReferenceProjectEntry {

View File

@@ -601,6 +601,62 @@ describe('ProjectsController', function (): void {
should(showErrorMessageSpy.called).be.true('showErrorMessage should have been called');
});
it('Should add dacpac references as relative paths', async function (): Promise<void> {
const projFilePath = await testUtils.createTestSqlProjFile(baselines.newProjectFileBaseline);
const projController = new ProjectsController();
const project1 = await Project.openProject(vscode.Uri.file(projFilePath).fsPath);
const showErrorMessageSpy = sinon.spy(vscode.window, 'showErrorMessage');
const dataWorkspaceMock = TypeMoq.Mock.ofType<dataworkspace.IExtension>();
sinon.stub(vscode.extensions, 'getExtension').returns(<any>{ exports: dataWorkspaceMock.object });
// add dacpac reference to something in the same folder
should(project1.databaseReferences.length).equal(0, 'There should not be any database references to start with');
await projController.addDatabaseReferenceCallback(project1, {
databaseName: <string>this.databaseNameTextbox?.value,
dacpacFileLocation: vscode.Uri.file(path.join(path.dirname(projFilePath), 'sameFolderTest.dacpac')),
suppressMissingDependenciesErrors: false
},
{ treeDataProvider: new SqlDatabaseProjectTreeViewProvider(), element: undefined });
should(showErrorMessageSpy.notCalled).be.true('showErrorMessage should not have been called');
should(project1.databaseReferences.length).equal(1, 'Dacpac reference should have been added');
should(project1.databaseReferences[0].databaseName).equal('sameFolderTest');
should(project1.databaseReferences[0].pathForSqlProj()).equal('sameFolderTest.dacpac');
// make sure reference to sameFolderTest.dacpac was added to project file
let projFileText = (await fs.readFile(projFilePath)).toString();
should(projFileText).containEql('sameFolderTest.dacpac');
// add dacpac reference to something in the a nested folder
await projController.addDatabaseReferenceCallback(project1, {
databaseName: <string>this.databaseNameTextbox?.value,
dacpacFileLocation: vscode.Uri.file(path.join(path.dirname(projFilePath), 'refs', 'nestedFolderTest.dacpac')),
suppressMissingDependenciesErrors: false
},
{ treeDataProvider: new SqlDatabaseProjectTreeViewProvider(), element: undefined });
should(showErrorMessageSpy.notCalled).be.true('showErrorMessage should not have been called');
should(project1.databaseReferences.length).equal(2, 'Another dacpac reference should have been added');
should(project1.databaseReferences[1].databaseName).equal('nestedFolderTest');
should(project1.databaseReferences[1].pathForSqlProj()).equal('refs\\nestedFolderTest.dacpac');
// make sure reference to nestedFolderTest.dacpac was added to project file
projFileText = (await fs.readFile(projFilePath)).toString();
should(projFileText).containEql('refs\\nestedFolderTest.dacpac');
// add dacpac reference to something in the a folder outside of the project
await projController.addDatabaseReferenceCallback(project1, {
databaseName: <string>this.databaseNameTextbox?.value,
dacpacFileLocation: vscode.Uri.file(path.join(path.dirname(projFilePath), '..','someFolder', 'outsideFolderTest.dacpac')),
suppressMissingDependenciesErrors: false
},
{ treeDataProvider: new SqlDatabaseProjectTreeViewProvider(), element: undefined });
should(showErrorMessageSpy.notCalled).be.true('showErrorMessage should not have been called');
should(project1.databaseReferences.length).equal(3, 'Another dacpac reference should have been added');
should(project1.databaseReferences[2].databaseName).equal('outsideFolderTest');
should(project1.databaseReferences[2].pathForSqlProj()).equal('..\\someFolder\\outsideFolderTest.dacpac');
// make sure reference to outsideFolderTest.dacpac was added to project file
projFileText = (await fs.readFile(projFilePath)).toString();
should(projFileText).containEql('..\\someFolder\\outsideFolderTest.dacpac');
});
});
});