mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-19 17:22:48 -05:00
Allow edit of sqlproj in place and reload (#11980)
* edit sql proj file * bug fix * updating reload project method * adding test for reload * formatting
This commit is contained in:
@@ -61,6 +61,7 @@ export const newDefaultProjectSaveLocation = localize('newDefaultProjectSaveLoca
|
||||
export const invalidDefaultProjectSaveLocation = localize('invalidDefaultProjectSaveLocation', "Default location to save new database projects is invalid. Would you like to update it?");
|
||||
export const openWorkspaceSettings = localize('openWorkspaceSettings', "Yes, open Settings");
|
||||
export const doNotPromptAgain = localize('doNotPromptAgain', "Don't ask again");
|
||||
export const reloadProject = localize('reloadProject', "Would you like to reload your database project?");
|
||||
export function newObjectNamePrompt(objectType: string) { return localize('newObjectNamePrompt', 'New {0} name:', objectType); }
|
||||
export function deleteConfirmation(toDelete: string) { return localize('deleteConfirmation', "Are you sure you want to delete {0}?", toDelete); }
|
||||
export function deleteConfirmationContents(toDelete: string) { return localize('deleteConfirmationContents', "Are you sure you want to delete {0} and all of its contents?", toDelete); }
|
||||
@@ -139,6 +140,7 @@ export const databaseReferenceAlreadyExists = localize('databaseReferenceAlready
|
||||
export const ousiderFolderPath = localize('outsideFolderPath', "Items with absolute path outside project folder are not supported. Please make sure the paths in the project file are relative to project folder.");
|
||||
export const parentTreeItemUnknown = localize('parentTreeItemUnknown', "Cannot access parent of provided tree item");
|
||||
export const prePostDeployCount = localize('prePostDeployCount', "To successfully build, update the project to have one pre-deployment script and/or one post-deployment script");
|
||||
export const invalidProjectReload = localize('invalidProjectReload', "Cannot access provided database project. Only valid, open database projects can be reloaded.");
|
||||
export function projectAlreadyOpened(path: string) { return localize('projectAlreadyOpened', "Project '{0}' is already opened.", path); }
|
||||
export function projectAlreadyExists(name: string, path: string) { return localize('projectAlreadyExists', "A project named {0} already exists in {1}.", name, path); }
|
||||
export function noFileExist(fileName: string) { return localize('noFileExist', "File {0} doesn't exist", fileName); }
|
||||
|
||||
@@ -73,6 +73,7 @@ export default class MainController implements vscode.Disposable {
|
||||
|
||||
vscode.commands.registerCommand('sqlDatabaseProjects.addDatabaseReference', async (node: BaseProjectTreeItem) => { await this.projectsController.addDatabaseReference(node); });
|
||||
vscode.commands.registerCommand('sqlDatabaseProjects.openContainingFolder', async (node: BaseProjectTreeItem) => { await this.projectsController.openContainingFolder(node); });
|
||||
vscode.commands.registerCommand('sqlDatabaseProjects.editProjectFile', async (node: BaseProjectTreeItem) => { await this.projectsController.editProjectFile(node); });
|
||||
vscode.commands.registerCommand('sqlDatabaseProjects.delete', async (node: BaseProjectTreeItem) => { await this.projectsController.delete(node); });
|
||||
vscode.commands.registerCommand('sqlDatabaseProjects.exclude', async (node: FileNode | FolderNode) => { await this.projectsController.exclude(node); });
|
||||
|
||||
|
||||
@@ -431,6 +431,45 @@ export class ProjectsController {
|
||||
await vscode.commands.executeCommand(constants.revealFileInOsCommand, vscode.Uri.file(project.projectFilePath));
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the .sqlproj file for the given project. Upon update of file, prompts user to
|
||||
* reload their project.
|
||||
* @param context a treeItem in a project's hierarchy, to be used to obtain a Project
|
||||
*/
|
||||
public async editProjectFile(context: BaseProjectTreeItem): Promise<void> {
|
||||
const project = this.getProjectFromContext(context);
|
||||
|
||||
try {
|
||||
await vscode.commands.executeCommand(constants.vscodeOpenCommand, vscode.Uri.file(project.projectFilePath));
|
||||
const projFileWatcher: vscode.FileSystemWatcher = vscode.workspace.createFileSystemWatcher(project.projectFilePath);
|
||||
|
||||
projFileWatcher.onDidChange(async (projectFileUri: vscode.Uri) => {
|
||||
const result = await vscode.window.showInformationMessage(constants.reloadProject, constants.yesString, constants.noString);
|
||||
|
||||
if (result === constants.yesString) {
|
||||
this.reloadProject(projectFileUri);
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
vscode.window.showErrorMessage(utils.getErrorMessage(err));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reloads the given project. Throws an error if given project is not a valid open project.
|
||||
* @param projectFileUri the uri of the project to be reloaded
|
||||
*/
|
||||
public async reloadProject(projectFileUri: vscode.Uri) {
|
||||
const project = this.projects.find((e) => e.projectFilePath === projectFileUri.fsPath);
|
||||
if (project) {
|
||||
// won't open any newly referenced projects, but otherwise matches the behavior of reopening the project
|
||||
await project.readProjFile();
|
||||
this.refreshProjectsTree();
|
||||
} else {
|
||||
throw new Error(constants.invalidProjectReload);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a database reference to the project
|
||||
* @param context a treeItem in a project's hierarchy, to be used to obtain a Project
|
||||
|
||||
@@ -56,6 +56,8 @@ export class Project {
|
||||
* Reads the project setting and contents from the file
|
||||
*/
|
||||
public async readProjFile() {
|
||||
this.resetProject();
|
||||
|
||||
const projFileText = await fs.readFile(this.projectFilePath);
|
||||
this.projFileXmlDoc = new xmldom.DOMParser().parseFromString(projFileText.toString());
|
||||
|
||||
@@ -147,6 +149,17 @@ export class Project {
|
||||
}
|
||||
}
|
||||
|
||||
private resetProject() {
|
||||
this.files = [];
|
||||
this.importedTargets = [];
|
||||
this.databaseReferences = [];
|
||||
this.sqlCmdVariables = {};
|
||||
this.preDeployScripts = [];
|
||||
this.postDeployScripts = [];
|
||||
this.noneDeployScripts = [];
|
||||
this.projFileXmlDoc = undefined;
|
||||
}
|
||||
|
||||
public async updateProjectForRoundTrip() {
|
||||
await fs.copyFile(this.projectFilePath, this.projectFilePath + '_backup');
|
||||
await this.updateImportToSupportRoundTrip();
|
||||
|
||||
@@ -8,6 +8,7 @@ import { promises as fs } from 'fs';
|
||||
|
||||
// Project baselines
|
||||
export let newProjectFileBaseline: string;
|
||||
export let newProjectFileWithScriptBaseline: string;
|
||||
export let openProjectFileBaseline: string;
|
||||
export let openDataSourcesBaseline: string;
|
||||
export let SSDTProjectFileBaseline: string;
|
||||
@@ -26,6 +27,7 @@ const baselineFolderPath = __dirname;
|
||||
|
||||
export async function loadBaselines() {
|
||||
newProjectFileBaseline = await loadBaseline(baselineFolderPath, 'newSqlProjectBaseline.xml');
|
||||
newProjectFileWithScriptBaseline = await loadBaseline(baselineFolderPath, 'newSqlProjectWithScriptBaseline.xml');
|
||||
openProjectFileBaseline = await loadBaseline(baselineFolderPath, 'openSqlProjectBaseline.xml');
|
||||
openDataSourcesBaseline = await loadBaseline(baselineFolderPath, 'openDataSourcesBaseline.json');
|
||||
SSDTProjectFileBaseline = await loadBaseline(baselineFolderPath, 'SSDTProjectBaseline.xml');
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<Name>TestProjectName</Name>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectVersion>4.1</ProjectVersion>
|
||||
<ProjectGuid>{BA5EBA11-C0DE-5EA7-ACED-BABB1E70A575}</ProjectGuid>
|
||||
<DSP>Microsoft.Data.Tools.Schema.Sql.Sql130DatabaseSchemaProvider</DSP>
|
||||
<OutputType>Database</OutputType>
|
||||
<RootPath>
|
||||
</RootPath>
|
||||
<RootNamespace>TestProjectName</RootNamespace>
|
||||
<AssemblyName>TestProjectName</AssemblyName>
|
||||
<ModelCollation>1033, CI</ModelCollation>
|
||||
<DefaultFileStructure>BySchemaAndSchemaType</DefaultFileStructure>
|
||||
<DeployToDatabase>True</DeployToDatabase>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<TargetLanguage>CS</TargetLanguage>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<SqlServerVerification>False</SqlServerVerification>
|
||||
<IncludeCompositeObjects>True</IncludeCompositeObjects>
|
||||
<TargetDatabaseSet>True</TargetDatabaseSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<BuildScriptName>$(MSBuildProjectName).sql</BuildScriptName>
|
||||
<TreatWarningsAsErrors>False</TreatWarningsAsErrors>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<DefineDebug>false</DefineDebug>
|
||||
<DefineTrace>true</DefineTrace>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<BuildScriptName>$(MSBuildProjectName).sql</BuildScriptName>
|
||||
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<DefineDebug>true</DefineDebug>
|
||||
<DefineTrace>true</DefineTrace>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">11.0</VisualStudioVersion>
|
||||
<!-- Default to the v11.0 targets path if the targets file for the current VS version is not found -->
|
||||
<SSDTExists Condition="Exists('$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v$(VisualStudioVersion)\SSDT\Microsoft.Data.Tools.Schema.SqlTasks.targets')">True</SSDTExists>
|
||||
<VisualStudioVersion Condition="'$(SSDTExists)' == ''">11.0</VisualStudioVersion>
|
||||
</PropertyGroup>
|
||||
<Import Condition="'$(NetCoreBuild)' == 'true'" Project="$(NETCoreTargetsPath)\Microsoft.Data.Tools.Schema.SqlTasks.targets"/>
|
||||
<Import Condition="'$(NetCoreBuild)' != 'true' AND '$(SQLDBExtensionsRefPath)' != ''" Project="$(SQLDBExtensionsRefPath)\Microsoft.Data.Tools.Schema.SqlTasks.targets" />
|
||||
<Import Condition="'$(NetCoreBuild)' != 'true' AND '$(SQLDBExtensionsRefPath)' == ''" Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v$(VisualStudioVersion)\SSDT\Microsoft.Data.Tools.Schema.SqlTasks.targets" />
|
||||
<ItemGroup>
|
||||
<PackageReference Condition="'$(NetCoreBuild)' == 'true'" Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.0" PrivateAssets="All" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Properties" />
|
||||
</ItemGroup>
|
||||
<Target Name="AfterClean">
|
||||
<Delete Files="$(BaseIntermediateOutputPath)\project.assets.json" />
|
||||
</Target>
|
||||
<ItemGroup>
|
||||
<Build Include="Script1.sql"/>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -246,6 +246,26 @@ describe('ProjectsController', function (): void {
|
||||
should(await exists(scriptEntry.fsUri.fsPath)).equal(true, 'script is supposed to still exist on disk');
|
||||
});
|
||||
|
||||
it('Should reload correctly after changing sqlproj file', async function (): Promise<void> {
|
||||
// create project
|
||||
const folderPath = await testUtils.generateTestFolderPath();
|
||||
const sqlProjPath = await testUtils.createTestSqlProjFile(baselines.newProjectFileBaseline, folderPath);
|
||||
const treeProvider = new SqlDatabaseProjectTreeViewProvider();
|
||||
const projController = new ProjectsController(treeProvider);
|
||||
const project = await projController.openProject(vscode.Uri.file(sqlProjPath));
|
||||
|
||||
// change the sql project file
|
||||
await fs.writeFile(sqlProjPath, baselines.newProjectFileWithScriptBaseline);
|
||||
should(project.files.length).equal(0);
|
||||
|
||||
// call reload project
|
||||
await projController.reloadProject(vscode.Uri.file(project.projectFilePath));
|
||||
should(project.files.length).equal(1);
|
||||
|
||||
// check that the new project is in the tree
|
||||
should(treeProvider.getChildren()[0].children.find(c => c.friendlyName === 'Script1.sql')).not.equal(undefined);
|
||||
});
|
||||
|
||||
it('Should be able to add pre deploy and post deploy script', async function (): Promise<void> {
|
||||
const preDeployScriptName = 'PreDeployScript1.sql';
|
||||
const postDeployScriptName = 'PostDeployScript1.sql';
|
||||
|
||||
Reference in New Issue
Block a user