mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-17 01:25:36 -05:00
SQL Database Projects backend swap to DacFx/Tools Service (#22451)
* Move call to STS move api into project.ts (#22071) * move call to STS move api into project.ts * remove undefined * Remove convert to sdk style code (#22081) * remove convert to sdk style code * remove from package.json * Merging latest from main (#22097) * [SQL-Migration] Login migrations telemetry (#22038) This PR enhances telemetry for login migrations (and in the following ways: Add details for starting migration (number of logins migrating, type of logins) Log Migration result (number of errors per step, duration of each step, type of logins, if system error occurred) Add sql-migration extension to our telemetry Adds details when trying to connect to target Tracks clicking "done" from the wizard Fixes bucketizing for navigating telemetry in the login migration wizard Sample usage of kusto query for new telemetry: RawEventsADS | where EventName contains 'sql-migration' | extend view = tostring(Properties['view']) | extend action = tostring(Properties['action']) | extend buttonPressed = tostring(Properties['buttonpressed']) | extend pageTitle = tostring(Properties['pagetitle']) | extend adsVersion = tostring(Properties['common.adsversion']) | extend targetType = tostring(Properties['targettype']) | extend tenantId = tostring(Properties['tenantid']) | extend subscriptionId = tostring(Properties['subscriptionid']) | where view contains "login" //| where adsVersion contains "1.42.0-insider" | where ClientTimestamp >= ago(18h) | project EventName, ClientTimestamp, SessionId, view, pageTitle, action, buttonPressed, targetType , tenantId, subscriptionId , adsVersion, OSVersion, Properties * Add Secure Enclaves dropdown with customizable Advanced options (#22019) * Update extension READMEs (#22079) * Fix query-history README images (#22084) * [Loc] update to mssql and sql-migration xlf files (#22087) * [Loc] small fix to Portuguese lcl file (#22088) * [Loc] small fix to Portuguese lcl file * remove newline * Adding None bindings to the sqlProjects service (#22085) * Adding None bindings * updating names of None bindings --------- Co-authored-by: AkshayMata <akam520@gmail.com> Co-authored-by: Cheena Malhotra <13396919+cheenamalhotra@users.noreply.github.com> Co-authored-by: Charles Gagnon <chgagnon@microsoft.com> Co-authored-by: Alex Ma <alma1@microsoft.com> * Swap add and update sqlcmd variables in sql projects to use STS apis (#22086) * delete sqlcmd variable working * undo add * remove variable from add and update sqlcmd variable apis * hookup add and edit sqlcmd variable * update vscode-mssql.d.ts * move add and edit to project.ts * update STS and tests * move delete sqlcmd variable to project.ts (#22104) * add test for add and edit sqlcmd variable (#22107) * Swapping property access to STS (#22115) * checkpoint * Adding sqlproj property bindings * Swapping out property loading and setting * consolidating to this.sqlProjService * Update dacpac reference to use STS api (#22116) * Update add dacpac reference to use STS api * remove changes for project ref * validate unset settings from add database reference dialog * update one more place getting sqlprojservice * addressing comments * fix path for dacpac reference (#22143) * Swap add project reference to call STS (#22148) * initial changes for swapping add project reference * fix include path * move common logic to helper function * read sqlcmd variables from STS (#22147) * Swapping .sqlproj- and crossplat compatibility-related functions to use STS (#22146) * Supporting roundtrip * Updating sqlproj style checks and cross-platform compatibility to use STS * removing unnecessary awaits * Fixing assertions * Adding roundtrip update confirmations * test cleanup * cleaning up comment; localizing error * Swap add system db reference (#22171) * swap adding system database references * fix tests * remove only in test * Read database references from STS (#22179) * Read database references from STS * fix system dacpac names * fix project reference name * Swap changeTargetPlatform to call STS (#22172) * swap changeTargetPlatform to call STS * Address comments * De-duplicating enum for SystemDatabase (#22196) * Deudping SystemDatabase enum * simplifying enum refs * Removing the now-unused imports code from SqlProjects (#22199) * Removing unused importTargets entries * whitespace; also to retrigger github checks on correct branch * Hooking in Move() for Nones and PublishProfiles (#22200) * Swap delete database reference to call STS (#22215) * initial changes * update contracts * remove unnecessary info from SystemDatabaseReferenceProjectEntry * uppercase master and msdb * cleanup * update test * update comment * undo change in projectController.ts * remove unused system dacpac helper functions (#22204) * more cleanup of project.ts (#22242) * fix a couple database reference tests (#22248) * Organizing sqlcmd variable and db reference code (#22284) * organize database references and sqlcmd variable functions * separate database reference tests * Script and folder get + add support (#22166) * Initial sqlobjectscripts * adding mock filter * test fixing * another test passing * swapping pre/post/none checkpoint * awaiters * convert addExistingItem * swapping folders * removing print * stripping out project folder and file readers * adding some regions * Updating sqlproj style checks and cross-platform compatibility to use STS * Updating sqlproj style checks and cross-platform compatibility to use STS * added type property to tree items * projectController swapovers * removing imported targets * Deleting the last of the TS XML parsing! * Removing old functions * renamed readNoneScripts to readNoneItems * fixing path passed to STS calls * remove system dacpac tests that were moved to DacFx (#22299) * fix error when opening file after adding a file to sql project (#22309) * fix error when opening file after adding a file to sql project * remove unused import * fix exclude for table and externalStreamingJob (#22310) * add reload project (#22313) * set DSP from STS (#22320) * fix adding post-deployment script and existing item (#22317) * Test cleanup for .sqlproj content operations (#22330) * Fixing up tests * sqlproj content operations tests * remove only * Cleanup * Correcting collation * cleanup constants.ts (#22336) * fix folders not showing in project tree (#22319) * Fix project controller tests (#22327) * fixing ProjectController tests after swap * remove only from database reference tests * change system dbs back to lowercase in sql projects (#22353) * Bump tools service * Updated yarn.lock file * pass SystemDacpacsLocation when building legacy style sql projects (#22329) * Benjin/fix types (#22365) * Updated yarn.lock file * Fixing types * fix projectController tests (#22375) * Fixing the deletion flow for files and folders (#22366) * checkpoint * PR feedback * Fixing up SDK-style operations project test group (#22377) * Fixing up SDK-style project test group * Removing .only * Fixing up database reference tests (#22380) * Fixing DB reference test group * Extra cleanup * removing only * Consolidating None and PublishProfile; lighting up test (#22382) * Lighting up project property tests (#22395) * Checkpoint * Lighting up project property tests * removing timeout * Fixing buildHelper test (#22400) * Unskipping up roundtrip test (#22397) * Refactoring database references to split literalVariable from databaseName (#22412) * refactoring database references to split databaseVariableLiteralValue out from databaseName * renaming more properties * Removing branch in entry population * removing only * Fixing baselines for delete test * PR feedback * Fixing up ProjectTree tests (#22419) * Fixing up projectTree tests * remove only * Updating projectController exclude test (#22413) * Updating test * moving filtering for external folders to readFolders() method * Removing EntryType import * fix ups (#22435) * adding extra info for test failure * hide exclude folder from context menu until it's supported (#22454) * Adding current test name to generated folder to avoid conflicts (#22478) * Adding current test name to generated folder to avoid conflicts * passing correct test parameter in * Adding trimming and entropy * Deleting unused baselines (#22497) * Replacing addToProject() with addSqlObjectScripts() (#22489) * checkpoint * Fixing test * Updating file scraper function to filter only to .sql files (no folders, no txt) * changing var names to reflect that the lists only contain .sql scripts --------- Co-authored-by: Kim Santiago <31145923+kisantia@users.noreply.github.com> Co-authored-by: AkshayMata <akam520@gmail.com> Co-authored-by: Cheena Malhotra <13396919+cheenamalhotra@users.noreply.github.com> Co-authored-by: Charles Gagnon <chgagnon@microsoft.com> Co-authored-by: Alex Ma <alma1@microsoft.com>
This commit is contained in:
@@ -17,9 +17,9 @@ import * as mssqlVscode from 'vscode-mssql';
|
||||
|
||||
import { promises as fs } from 'fs';
|
||||
import { PublishDatabaseDialog } from '../dialogs/publishDatabaseDialog';
|
||||
import { Project, reservedProjectFolders } from '../models/project';
|
||||
import { Project } from '../models/project';
|
||||
import { SqlDatabaseProjectTreeViewProvider } from './databaseProjectTreeViewProvider';
|
||||
import { FolderNode, FileNode, SqlObjectFileNode, PreDeployNode, PostDeployNode } from '../models/tree/fileFolderTreeItem';
|
||||
import { FolderNode, FileNode } from '../models/tree/fileFolderTreeItem';
|
||||
import { BaseProjectTreeItem } from '../models/tree/baseTreeItem';
|
||||
import { ImportDataModel } from '../models/api/import';
|
||||
import { NetCoreTool, DotNetError } from '../tools/netcoreTool';
|
||||
@@ -201,8 +201,9 @@ export class ProjectsController {
|
||||
const projectStyle = creationParams.sdkStyle ? mssql.ProjectType.SdkStyle : mssql.ProjectType.LegacyStyle;
|
||||
await (sqlProjectsService as mssql.ISqlProjectsService).createProject(newProjFilePath, projectStyle, targetPlatform);
|
||||
} else {
|
||||
const projectStyle = creationParams.sdkStyle ? mssqlVscode.ProjectType.SdkStyle : mssqlVscode.ProjectType.LegacyStyle;
|
||||
await (sqlProjectsService as mssqlVscode.ISqlProjectsService).createProject(newProjFilePath, projectStyle, targetPlatform);
|
||||
throw new Error(constants.errorNotSupportedInVsCode('createProject'));
|
||||
//const projectStyle = creationParams.sdkStyle ? mssqlVscode.ProjectType.SdkStyle : mssqlVscode.ProjectType.LegacyStyle;
|
||||
//await (sqlProjectsService as mssqlVscode.ISqlProjectsService).createProject(newProjFilePath, projectStyle, targetPlatform);
|
||||
}
|
||||
|
||||
await this.addTemplateFiles(newProjFilePath, creationParams.projectTypeId);
|
||||
@@ -223,19 +224,34 @@ export class ProjectsController {
|
||||
if (projectTypeId === constants.edgeSqlDatabaseProjectTypeId) {
|
||||
const project = await Project.openProject(newProjFilePath);
|
||||
|
||||
await this.createFileFromTemplate(project, templates.get(ItemType.table), 'DataTable.sql', { 'OBJECT_NAME': 'DataTable' });
|
||||
await this.createFileFromTemplate(project, templates.get(ItemType.dataSource), 'EdgeHubInputDataSource.sql', { 'OBJECT_NAME': 'EdgeHubInputDataSource', 'LOCATION': 'edgehub://' });
|
||||
await this.createFileFromTemplate(project, templates.get(ItemType.dataSource), 'SqlOutputDataSource.sql', { 'OBJECT_NAME': 'SqlOutputDataSource', 'LOCATION': 'sqlserver://tcp:.,1433' });
|
||||
await this.createFileFromTemplate(project, templates.get(ItemType.fileFormat), 'StreamFileFormat.sql', { 'OBJECT_NAME': 'StreamFileFormat' });
|
||||
await this.createFileFromTemplate(project, templates.get(ItemType.externalStream), 'EdgeHubInputStream.sql', { 'OBJECT_NAME': 'EdgeHubInputStream', 'DATA_SOURCE_NAME': 'EdgeHubInputDataSource', 'LOCATION': 'input', 'OPTIONS': ',\n\tFILE_FORMAT = StreamFileFormat' });
|
||||
await this.createFileFromTemplate(project, templates.get(ItemType.externalStream), 'SqlOutputStream.sql', { 'OBJECT_NAME': 'SqlOutputStream', 'DATA_SOURCE_NAME': 'SqlOutputDataSource', 'LOCATION': 'TSQLStreaming.dbo.DataTable', 'OPTIONS': '' });
|
||||
await this.createFileFromTemplate(project, templates.get(ItemType.externalStreamingJob), 'EdgeStreamingJob.sql', { 'OBJECT_NAME': 'EdgeStreamingJob' });
|
||||
await this.addFileToProjectFromTemplate(project, templates.get(ItemType.table), 'DataTable.sql', { 'OBJECT_NAME': 'DataTable' });
|
||||
await this.addFileToProjectFromTemplate(project, templates.get(ItemType.dataSource), 'EdgeHubInputDataSource.sql', { 'OBJECT_NAME': 'EdgeHubInputDataSource', 'LOCATION': 'edgehub://' });
|
||||
await this.addFileToProjectFromTemplate(project, templates.get(ItemType.dataSource), 'SqlOutputDataSource.sql', { 'OBJECT_NAME': 'SqlOutputDataSource', 'LOCATION': 'sqlserver://tcp:.,1433' });
|
||||
await this.addFileToProjectFromTemplate(project, templates.get(ItemType.fileFormat), 'StreamFileFormat.sql', { 'OBJECT_NAME': 'StreamFileFormat' });
|
||||
await this.addFileToProjectFromTemplate(project, templates.get(ItemType.externalStream), 'EdgeHubInputStream.sql', { 'OBJECT_NAME': 'EdgeHubInputStream', 'DATA_SOURCE_NAME': 'EdgeHubInputDataSource', 'LOCATION': 'input', 'OPTIONS': ',\n\tFILE_FORMAT = StreamFileFormat' });
|
||||
await this.addFileToProjectFromTemplate(project, templates.get(ItemType.externalStream), 'SqlOutputStream.sql', { 'OBJECT_NAME': 'SqlOutputStream', 'DATA_SOURCE_NAME': 'SqlOutputDataSource', 'LOCATION': 'TSQLStreaming.dbo.DataTable', 'OPTIONS': '' });
|
||||
await this.addFileToProjectFromTemplate(project, templates.get(ItemType.externalStreamingJob), 'EdgeStreamingJob.sql', { 'OBJECT_NAME': 'EdgeStreamingJob' });
|
||||
}
|
||||
}
|
||||
|
||||
private async createFileFromTemplate(project: Project, itemType: templates.ProjectScriptType, relativePath: string, expansionMacros: Record<string, string>): Promise<void> {
|
||||
private async addFileToProjectFromTemplate(project: ISqlProject, itemType: templates.ProjectScriptType, relativePath: string, expansionMacros: Record<string, string>): Promise<string> {
|
||||
const newFileText = templates.macroExpansion(itemType.templateScript, expansionMacros);
|
||||
await project.addScriptItem(relativePath, newFileText, itemType.type);
|
||||
const absolutePath = path.join(project.projectFolderPath, relativePath)
|
||||
await utils.ensureFileExists(absolutePath, newFileText);
|
||||
|
||||
switch (itemType.type) {
|
||||
case ItemType.preDeployScript:
|
||||
await project.addPreDeploymentScript(relativePath);
|
||||
break;
|
||||
case ItemType.postDeployScript:
|
||||
await project.addPostDeploymentScript(relativePath);
|
||||
break;
|
||||
default: // a normal SQL object script
|
||||
await project.addSqlObjectScript(relativePath);
|
||||
break;
|
||||
}
|
||||
|
||||
return absolutePath;
|
||||
}
|
||||
|
||||
//#endregion
|
||||
@@ -266,7 +282,7 @@ export class ProjectsController {
|
||||
}
|
||||
|
||||
// get dlls and targets file needed for building for legacy style projects
|
||||
if (!project.isSdkStyleProject) {
|
||||
if (project.sqlProjStyle === mssql.ProjectType.LegacyStyle) {
|
||||
const result = await this.buildHelper.createBuildDirFolder(this._outputChannel);
|
||||
|
||||
if (!result) {
|
||||
@@ -278,7 +294,7 @@ export class ProjectsController {
|
||||
const options: ShellCommandOptions = {
|
||||
commandTitle: 'Build',
|
||||
workingDirectory: project.projectFolderPath,
|
||||
argument: this.buildHelper.constructBuildArguments(project.projectFilePath, this.buildHelper.extensionBuildDirPath, project.isSdkStyleProject)
|
||||
argument: this.buildHelper.constructBuildArguments(project.projectFilePath, this.buildHelper.extensionBuildDirPath, project.sqlProjStyle)
|
||||
};
|
||||
|
||||
try {
|
||||
@@ -640,7 +656,7 @@ export class ProjectsController {
|
||||
throw new Error(constants.folderAlreadyExists(path.parse(absoluteFolderPath).name));
|
||||
}
|
||||
|
||||
await project.addFolderItem(relativeFolderPath);
|
||||
await project.addFolder(relativeFolderPath);
|
||||
this.refreshProjectsTree(treeNode);
|
||||
} catch (err) {
|
||||
void vscode.window.showErrorMessage(utils.getErrorMessage(err));
|
||||
@@ -669,7 +685,7 @@ export class ProjectsController {
|
||||
}
|
||||
|
||||
public isReservedFolder(absoluteFolderPath: string, projectFolderPath: string): boolean {
|
||||
const sameName = reservedProjectFolders.find(f => f === path.parse(absoluteFolderPath).name) !== undefined;
|
||||
const sameName = constants.reservedProjectFolders.find(f => f === path.parse(absoluteFolderPath).name) !== undefined;
|
||||
const sameLocation = path.parse(absoluteFolderPath).dir === projectFolderPath;
|
||||
return sameName && sameLocation;
|
||||
}
|
||||
@@ -707,7 +723,6 @@ export class ProjectsController {
|
||||
return; // user cancelled
|
||||
}
|
||||
|
||||
const newFileText = templates.macroExpansion(itemType.templateScript, { 'OBJECT_NAME': itemObjectName });
|
||||
const relativeFilePath = path.join(relativePath, itemObjectName + constants.sqlFileExtension);
|
||||
|
||||
const telemetryProps: Record<string, string> = { itemType: itemType.type };
|
||||
@@ -720,14 +735,14 @@ export class ProjectsController {
|
||||
}
|
||||
|
||||
try {
|
||||
const newEntry = await project.addScriptItem(relativeFilePath, newFileText, itemType.type);
|
||||
const absolutePath = await this.addFileToProjectFromTemplate(project, itemType, relativeFilePath, { 'OBJECT_NAME': itemObjectName });
|
||||
|
||||
TelemetryReporter.createActionEvent(TelemetryViews.ProjectTree, TelemetryActions.addItemFromTree)
|
||||
.withAdditionalProperties(telemetryProps)
|
||||
.withAdditionalMeasurements(telemetryMeasurements)
|
||||
.send();
|
||||
|
||||
await vscode.commands.executeCommand(constants.vscodeOpenCommand, newEntry.fsUri);
|
||||
await vscode.commands.executeCommand(constants.vscodeOpenCommand, vscode.Uri.file(absolutePath));
|
||||
treeDataProvider?.notifyTreeDataChanged();
|
||||
} catch (err) {
|
||||
void vscode.window.showErrorMessage(utils.getErrorMessage(err));
|
||||
@@ -772,7 +787,30 @@ export class ProjectsController {
|
||||
|
||||
if (fileEntry) {
|
||||
TelemetryReporter.sendActionEvent(TelemetryViews.ProjectTree, TelemetryActions.excludeFromProject);
|
||||
await project.exclude(fileEntry);
|
||||
|
||||
switch (node.type) {
|
||||
case constants.DatabaseProjectItemType.sqlObjectScript:
|
||||
case constants.DatabaseProjectItemType.table:
|
||||
case constants.DatabaseProjectItemType.externalStreamingJob:
|
||||
await project.excludeSqlObjectScript(fileEntry.relativePath);
|
||||
break;
|
||||
case constants.DatabaseProjectItemType.folder:
|
||||
// TODO: not yet supported in DacFx
|
||||
//await project.excludeFolder(fileEntry.relativePath);
|
||||
void vscode.window.showErrorMessage(constants.excludeFolderNotSupported);
|
||||
break;
|
||||
case constants.DatabaseProjectItemType.preDeploymentScript:
|
||||
await project.excludePreDeploymentScript(fileEntry.relativePath);
|
||||
break;
|
||||
case constants.DatabaseProjectItemType.postDeploymentScript:
|
||||
await project.excludePostDeploymentScript(fileEntry.relativePath);
|
||||
break;
|
||||
case constants.DatabaseProjectItemType.noneFile:
|
||||
await project.excludeNoneItem(fileEntry.relativePath);
|
||||
break;
|
||||
default:
|
||||
throw new Error(constants.unhandledExcludeType(node.type));
|
||||
}
|
||||
} else {
|
||||
TelemetryReporter.sendErrorEvent2(TelemetryViews.ProjectTree, TelemetryActions.excludeFromProject);
|
||||
void vscode.window.showErrorMessage(constants.unableToPerformAction(constants.excludeAction, node.relativeProjectUri.path));
|
||||
@@ -802,35 +840,43 @@ export class ProjectsController {
|
||||
return;
|
||||
}
|
||||
|
||||
let success = false;
|
||||
try {
|
||||
if (node instanceof DatabaseReferenceTreeItem) {
|
||||
const databaseReference = this.getDatabaseReference(project, node);
|
||||
|
||||
if (node instanceof DatabaseReferenceTreeItem) {
|
||||
const databaseReference = this.getDatabaseReference(project, node);
|
||||
|
||||
if (databaseReference) {
|
||||
await project.deleteDatabaseReference(databaseReference);
|
||||
success = true;
|
||||
if (databaseReference) {
|
||||
await project.deleteDatabaseReferenceByEntry(databaseReference);
|
||||
}
|
||||
} else if (node instanceof SqlCmdVariableTreeItem) {
|
||||
await project.deleteSqlCmdVariable(node.friendlyName);
|
||||
} else if (node instanceof FolderNode) {
|
||||
await project.deleteFolder(node.entryKey);
|
||||
} else if (node instanceof FileNode) {
|
||||
switch (node.type) {
|
||||
case constants.DatabaseProjectItemType.sqlObjectScript:
|
||||
case constants.DatabaseProjectItemType.table:
|
||||
case constants.DatabaseProjectItemType.externalStreamingJob:
|
||||
await project.deleteSqlObjectScript(node.entryKey);
|
||||
break;
|
||||
case constants.DatabaseProjectItemType.preDeploymentScript:
|
||||
await project.deletePreDeploymentScript(node.entryKey);
|
||||
break;
|
||||
case constants.DatabaseProjectItemType.postDeploymentScript:
|
||||
await project.deletePostDeploymentScript(node.entryKey);
|
||||
break;
|
||||
case constants.DatabaseProjectItemType.noneFile:
|
||||
await project.deleteNoneItem(node.entryKey);
|
||||
break;
|
||||
default:
|
||||
throw new Error(constants.unhandledDeleteType(node.type));
|
||||
}
|
||||
}
|
||||
} else if (node instanceof SqlCmdVariableTreeItem) {
|
||||
const sqlProjectsService = await utils.getSqlProjectsService();
|
||||
const result = await sqlProjectsService.deleteSqlCmdVariable(project.projectFilePath, node.friendlyName);
|
||||
success = result.success;
|
||||
} else if (node instanceof FileNode || FolderNode) {
|
||||
const fileEntry = this.getFileProjectEntry(project, node);
|
||||
|
||||
if (fileEntry) {
|
||||
await project.deleteFileFolder(fileEntry);
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (success) {
|
||||
TelemetryReporter.createActionEvent(TelemetryViews.ProjectTree, TelemetryActions.deleteObjectFromProject)
|
||||
.withAdditionalProperties({ objectType: node.constructor.name })
|
||||
.send();
|
||||
|
||||
this.refreshProjectsTree(context);
|
||||
} else {
|
||||
} catch {
|
||||
TelemetryReporter.createErrorEvent2(TelemetryViews.ProjectTree, TelemetryActions.deleteObjectFromProject)
|
||||
.withAdditionalProperties({ objectType: node.constructor.name })
|
||||
.send();
|
||||
@@ -862,7 +908,7 @@ export class ProjectsController {
|
||||
|
||||
const newFilePath = path.join(path.dirname(utils.getPlatformSafeFileEntryPath(file?.relativePath!)), `${newFileName}.sql`);
|
||||
|
||||
const renameResult = await this.move(node, node.projectFileUri.fsPath, newFilePath);
|
||||
const renameResult = await project.move(node, newFilePath);
|
||||
|
||||
if (renameResult?.success) {
|
||||
TelemetryReporter.sendActionEvent(TelemetryViews.ProjectTree, TelemetryActions.rename);
|
||||
@@ -885,11 +931,12 @@ export class ProjectsController {
|
||||
public async editSqlCmdVariable(context: dataworkspace.WorkspaceTreeItem): Promise<void> {
|
||||
const node = context.element as SqlCmdVariableTreeItem;
|
||||
const project = await this.getProjectFromContext(node);
|
||||
const originalValue = project.sqlCmdVariables[node.friendlyName]; // TODO: update to hookup with however sqlcmd vars work after swap
|
||||
const variableName = node.friendlyName;
|
||||
const originalValue = project.sqlCmdVariables[variableName];
|
||||
|
||||
const newValue = await vscode.window.showInputBox(
|
||||
{
|
||||
title: constants.enterNewValueForVar(node.friendlyName),
|
||||
title: constants.enterNewValueForVar(variableName),
|
||||
value: originalValue,
|
||||
ignoreFocusOut: true
|
||||
});
|
||||
@@ -898,7 +945,8 @@ export class ProjectsController {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: update value in sqlcmd variables after swap
|
||||
await project.updateSqlCmdVariable(variableName, newValue)
|
||||
this.refreshProjectsTree(context);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -931,9 +979,7 @@ export class ProjectsController {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: update after swap
|
||||
await project.addSqlCmdVariable(variableName, defaultValue);
|
||||
|
||||
this.refreshProjectsTree(context);
|
||||
}
|
||||
|
||||
@@ -945,7 +991,7 @@ export class ProjectsController {
|
||||
const databaseReference = context as DatabaseReferenceTreeItem;
|
||||
|
||||
if (databaseReference) {
|
||||
return project.databaseReferences.find(r => r.databaseName === databaseReference.treeItem.label);
|
||||
return project.databaseReferences.find(r => r.referenceName === databaseReference.treeItem.label);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
@@ -1068,35 +1114,6 @@ export class ProjectsController {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a legacy style project to an SDK-style project
|
||||
* @param context a treeItem in a project's hierarchy, to be used to obtain a Project
|
||||
*/
|
||||
public async convertToSdkStyleProject(context: dataworkspace.WorkspaceTreeItem): Promise<void> {
|
||||
const project = await this.getProjectFromContext(context);
|
||||
|
||||
// confirm that user wants to update the project and knows the SSDT doesn't have support for displaying glob files yet
|
||||
await vscode.window.showWarningMessage(constants.convertToSdkStyleConfirmation(project.projectFileName), { modal: true }, constants.yesString).then(async (result) => {
|
||||
if (result === constants.yesString) {
|
||||
const updateResult = await project.convertProjectToSdkStyle();
|
||||
void this.reloadProject(context);
|
||||
|
||||
if (!updateResult) {
|
||||
void vscode.window.showErrorMessage(constants.updatedToSdkStyleError(project.projectFileName));
|
||||
} else {
|
||||
void this.reloadProject(context);
|
||||
|
||||
// show message that project file can be simplified
|
||||
const result = await vscode.window.showInformationMessage(constants.projectUpdatedToSdkStyle(project.projectFileName), constants.learnMore);
|
||||
|
||||
if (result === constants.learnMore) {
|
||||
void vscode.env.openExternal(vscode.Uri.parse(constants.sdkLearnMoreUrl!));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//#region database references
|
||||
|
||||
/**
|
||||
@@ -1367,9 +1384,9 @@ export class ProjectsController {
|
||||
return;
|
||||
}
|
||||
|
||||
const fileFolderList: vscode.Uri[] | undefined = await this.getSqlFileList(projectInfo.newProjectFolder);
|
||||
const scriptList: vscode.Uri[] | undefined = await this.getSqlFileList(projectInfo.newProjectFolder);
|
||||
|
||||
if (!fileFolderList || fileFolderList.length === 0) {
|
||||
if (!scriptList || scriptList.length === 0) {
|
||||
void vscode.window.showInformationMessage(constants.noSqlFilesGenerated);
|
||||
this._outputChannel.show();
|
||||
return;
|
||||
@@ -1386,12 +1403,15 @@ export class ProjectsController {
|
||||
const project = await Project.openProject(newProjFilePath);
|
||||
|
||||
// 6. add generated files to SQL project
|
||||
await project.addToProject(fileFolderList.filter(f => !f.fsPath.endsWith(constants.autorestPostDeploymentScriptName))); // Add generated file structure to the project
|
||||
|
||||
const postDeploymentScript: vscode.Uri | undefined = this.findPostDeploymentScript(fileFolderList);
|
||||
const uriList = scriptList.filter(f => !f.fsPath.endsWith(constants.autorestPostDeploymentScriptName))
|
||||
const relativePaths = uriList.map(f => path.relative(project.projectFolderPath, f.path));
|
||||
await project.addSqlObjectScripts(relativePaths); // Add generated file structure to the project
|
||||
|
||||
const postDeploymentScript: vscode.Uri | undefined = this.findPostDeploymentScript(scriptList);
|
||||
|
||||
if (postDeploymentScript) {
|
||||
await project.addScriptItem(path.relative(project.projectFolderPath, postDeploymentScript.fsPath), undefined, ItemType.postDeployScript);
|
||||
await project.addPostDeploymentScript(path.relative(project.projectFolderPath, postDeploymentScript.fsPath));
|
||||
}
|
||||
|
||||
if (options?.doNotOpenInWorkspace !== true) {
|
||||
@@ -1576,10 +1596,12 @@ export class ProjectsController {
|
||||
.withAdditionalMeasurements({ durationMs: timeToExtract })
|
||||
.send();
|
||||
|
||||
let fileFolderList: vscode.Uri[] = model.extractTarget === mssql.ExtractTarget.file ? [vscode.Uri.file(model.filePath)] : await this.generateList(model.filePath); // Create a list of all the files and directories to be added to project
|
||||
const scriptList: vscode.Uri[] = model.extractTarget === mssql.ExtractTarget.file ? [vscode.Uri.file(model.filePath)] : await this.generateScriptList(model.filePath); // Create a list of all the files to be added to project
|
||||
|
||||
const relativePaths = scriptList.map(f => path.relative(project.projectFolderPath, f.path));
|
||||
|
||||
if (!model.sdkStyle) {
|
||||
await project.addToProject(fileFolderList); // Add generated file structure to the project
|
||||
await project.addSqlObjectScripts(relativePaths); // Add generated file structure to the project
|
||||
}
|
||||
|
||||
// add project to workspace
|
||||
@@ -1611,19 +1633,19 @@ export class ProjectsController {
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a flat list of all files and folder under a folder.
|
||||
* Generate a flat list of all scripts under a folder.
|
||||
* @param absolutePath absolute path to folder to generate the list of files from
|
||||
* @returns array of uris of files and folders under the provided folder
|
||||
* @returns array of uris of files under the provided folder
|
||||
*/
|
||||
public async generateList(absolutePath: string): Promise<vscode.Uri[]> {
|
||||
let fileFolderList: vscode.Uri[] = [];
|
||||
public async generateScriptList(absolutePath: string): Promise<vscode.Uri[]> {
|
||||
let fileList: vscode.Uri[] = [];
|
||||
|
||||
if (!await utils.exists(absolutePath)) {
|
||||
if (await utils.exists(absolutePath + constants.sqlFileExtension)) {
|
||||
absolutePath += constants.sqlFileExtension;
|
||||
} else {
|
||||
void vscode.window.showErrorMessage(constants.cannotResolvePath(absolutePath));
|
||||
return fileFolderList;
|
||||
return fileList;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1635,19 +1657,18 @@ export class ProjectsController {
|
||||
const stat = await fs.stat(filepath);
|
||||
|
||||
if (stat.isDirectory()) {
|
||||
fileFolderList.push(vscode.Uri.file(filepath));
|
||||
(await fs
|
||||
.readdir(filepath))
|
||||
.forEach((f: string) => files.push(path.join(filepath, f)));
|
||||
}
|
||||
else if (stat.isFile()) {
|
||||
fileFolderList.push(vscode.Uri.file(filepath));
|
||||
else if (stat.isFile() && path.extname(filepath) === constants.sqlFileExtension) {
|
||||
fileList.push(vscode.Uri.file(filepath));
|
||||
}
|
||||
}
|
||||
|
||||
} while (files.length !== 0);
|
||||
|
||||
return fileFolderList;
|
||||
return fileList;
|
||||
}
|
||||
|
||||
//#endregion
|
||||
@@ -1817,7 +1838,9 @@ export class ProjectsController {
|
||||
|
||||
let toAdd: vscode.Uri[] = [];
|
||||
result.addedFiles.forEach((f: any) => toAdd.push(vscode.Uri.file(f)));
|
||||
await project.addToProject(toAdd);
|
||||
const relativePaths = toAdd.map(f => path.relative(project.projectFolderPath, f.path));
|
||||
|
||||
await project.addSqlObjectScripts(relativePaths);
|
||||
|
||||
let toRemove: vscode.Uri[] = [];
|
||||
result.deletedFiles.forEach((f: any) => toRemove.push(vscode.Uri.file(f)));
|
||||
@@ -1825,7 +1848,7 @@ export class ProjectsController {
|
||||
let toRemoveEntries: FileProjectEntry[] = [];
|
||||
toRemove.forEach(f => toRemoveEntries.push(new FileProjectEntry(f, f.path.replace(projectPath + '\\', ''), EntryType.File)));
|
||||
|
||||
toRemoveEntries.forEach(async f => await project.exclude(f));
|
||||
toRemoveEntries.forEach(async f => await project.excludeSqlObjectScript(f.fsUri.fsPath));
|
||||
|
||||
await this.buildProject(project);
|
||||
}
|
||||
@@ -1843,6 +1866,7 @@ export class ProjectsController {
|
||||
*/
|
||||
public async moveFile(projectUri: vscode.Uri, source: any, target: dataworkspace.WorkspaceTreeItem): Promise<void> {
|
||||
const sourceFileNode = source as FileNode;
|
||||
const project = await this.getProjectFromContext(sourceFileNode);
|
||||
|
||||
// only moving files is supported
|
||||
if (!sourceFileNode || !(sourceFileNode instanceof FileNode)) {
|
||||
@@ -1885,7 +1909,7 @@ export class ProjectsController {
|
||||
}
|
||||
|
||||
// Move the file
|
||||
const moveResult = await this.move(sourceFileNode, projectUri.fsPath, newPath);
|
||||
const moveResult = await project.move(sourceFileNode, newPath);
|
||||
|
||||
if (moveResult?.success) {
|
||||
TelemetryReporter.sendActionEvent(TelemetryViews.ProjectTree, TelemetryActions.move);
|
||||
@@ -1894,38 +1918,6 @@ export class ProjectsController {
|
||||
void vscode.window.showErrorMessage(constants.errorMovingFile(sourceFileNode.fileSystemUri.fsPath, newPath, utils.getErrorMessage(moveResult?.errorMessage)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves a file to a different location
|
||||
* @param node Node being moved
|
||||
* @param projectFilePath Full file path to .sqlproj
|
||||
* @param destinationRelativePath path of the destination, relative to .sqlproj
|
||||
*/
|
||||
private async move(node: BaseProjectTreeItem, projectFilePath: string, destinationRelativePath: string): Promise<azdataType.ResultStatus | undefined> {
|
||||
// trim off the project folder at the beginning of the relative path stored in the tree
|
||||
const projectRelativeUri = vscode.Uri.file(path.basename(projectFilePath, constants.sqlprojExtension));
|
||||
const originalRelativePath = utils.trimUri(projectRelativeUri, node.relativeProjectUri);
|
||||
destinationRelativePath = utils.trimUri(projectRelativeUri, vscode.Uri.file(destinationRelativePath));
|
||||
|
||||
if (originalRelativePath === destinationRelativePath) {
|
||||
return;
|
||||
}
|
||||
|
||||
const sqlProjectsService = await utils.getSqlProjectsService();
|
||||
|
||||
let result;
|
||||
if (node instanceof SqlObjectFileNode) {
|
||||
result = await sqlProjectsService.moveSqlObjectScript(projectFilePath, destinationRelativePath, originalRelativePath)
|
||||
} else if (node instanceof PreDeployNode) {
|
||||
result = await sqlProjectsService.movePreDeploymentScript(projectFilePath, destinationRelativePath, originalRelativePath)
|
||||
} else if (node instanceof PostDeployNode) {
|
||||
result = await sqlProjectsService.movePostDeploymentScript(projectFilePath, destinationRelativePath, originalRelativePath)
|
||||
}
|
||||
// TODO add support for renaming none scripts after those are added in STS
|
||||
// TODO add support for renaming publish profiles when support is added in DacFx
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
export interface NewProjectParams {
|
||||
|
||||
Reference in New Issue
Block a user