mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 10:58:30 -05:00
Support for adding new SQLCMD variables to a project (#12009)
This commit is contained in:
@@ -17,7 +17,7 @@ import * as azdata from 'azdata';
|
|||||||
|
|
||||||
import { promises as fs } from 'fs';
|
import { promises as fs } from 'fs';
|
||||||
import { PublishDatabaseDialog } from '../dialogs/publishDatabaseDialog';
|
import { PublishDatabaseDialog } from '../dialogs/publishDatabaseDialog';
|
||||||
import { Project, ProjectEntry, reservedProjectFolders, SqlProjectReferenceProjectEntry } from '../models/project';
|
import { Project, reservedProjectFolders, FileProjectEntry, SqlProjectReferenceProjectEntry } from '../models/project';
|
||||||
import { SqlDatabaseProjectTreeViewProvider } from './databaseProjectTreeViewProvider';
|
import { SqlDatabaseProjectTreeViewProvider } from './databaseProjectTreeViewProvider';
|
||||||
import { FolderNode, FileNode } from '../models/tree/fileFolderTreeItem';
|
import { FolderNode, FileNode } from '../models/tree/fileFolderTreeItem';
|
||||||
import { IPublishSettings, IGenerateScriptSettings } from '../models/IPublishSettings';
|
import { IPublishSettings, IGenerateScriptSettings } from '../models/IPublishSettings';
|
||||||
@@ -372,7 +372,7 @@ export class ProjectsController {
|
|||||||
public async exclude(context: FileNode | FolderNode): Promise<void> {
|
public async exclude(context: FileNode | FolderNode): Promise<void> {
|
||||||
const project = this.getProjectFromContext(context);
|
const project = this.getProjectFromContext(context);
|
||||||
|
|
||||||
const fileEntry = this.getProjectEntry(project, context);
|
const fileEntry = this.getFileProjectEntry(project, context);
|
||||||
|
|
||||||
if (fileEntry) {
|
if (fileEntry) {
|
||||||
await project.exclude(fileEntry);
|
await project.exclude(fileEntry);
|
||||||
@@ -396,7 +396,7 @@ export class ProjectsController {
|
|||||||
let success = false;
|
let success = false;
|
||||||
|
|
||||||
if (context instanceof FileNode || FolderNode) {
|
if (context instanceof FileNode || FolderNode) {
|
||||||
const fileEntry = this.getProjectEntry(project, context);
|
const fileEntry = this.getFileProjectEntry(project, context);
|
||||||
|
|
||||||
if (fileEntry) {
|
if (fileEntry) {
|
||||||
await project.deleteFileFolder(fileEntry);
|
await project.deleteFileFolder(fileEntry);
|
||||||
@@ -411,7 +411,7 @@ export class ProjectsController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private getProjectEntry(project: Project, context: BaseProjectTreeItem): ProjectEntry | undefined {
|
private getFileProjectEntry(project: Project, context: BaseProjectTreeItem): FileProjectEntry | undefined {
|
||||||
const root = context.root as ProjectRootTreeItem;
|
const root = context.root as ProjectRootTreeItem;
|
||||||
const fileOrFolder = context as FileNode ? context as FileNode : context as FolderNode;
|
const fileOrFolder = context as FileNode ? context as FileNode : context as FolderNode;
|
||||||
|
|
||||||
|
|||||||
@@ -22,14 +22,14 @@ import { ISystemDatabaseReferenceSettings, IDacpacReferenceSettings } from './ID
|
|||||||
export class Project {
|
export class Project {
|
||||||
public projectFilePath: string;
|
public projectFilePath: string;
|
||||||
public projectFileName: string;
|
public projectFileName: string;
|
||||||
public files: ProjectEntry[] = [];
|
public files: FileProjectEntry[] = [];
|
||||||
public dataSources: DataSource[] = [];
|
public dataSources: DataSource[] = [];
|
||||||
public importedTargets: string[] = [];
|
public importedTargets: string[] = [];
|
||||||
public databaseReferences: IDatabaseReferenceProjectEntry[] = [];
|
public databaseReferences: IDatabaseReferenceProjectEntry[] = [];
|
||||||
public sqlCmdVariables: Record<string, string> = {};
|
public sqlCmdVariables: Record<string, string> = {};
|
||||||
public preDeployScripts: ProjectEntry[] = [];
|
public preDeployScripts: FileProjectEntry[] = [];
|
||||||
public postDeployScripts: ProjectEntry[] = [];
|
public postDeployScripts: FileProjectEntry[] = [];
|
||||||
public noneDeployScripts: ProjectEntry[] = [];
|
public noneDeployScripts: FileProjectEntry[] = [];
|
||||||
|
|
||||||
public get projectFolderPath() {
|
public get projectFolderPath() {
|
||||||
return Uri.file(path.dirname(this.projectFilePath)).fsPath;
|
return Uri.file(path.dirname(this.projectFilePath)).fsPath;
|
||||||
@@ -65,14 +65,14 @@ export class Project {
|
|||||||
|
|
||||||
const buildElements = itemGroup.getElementsByTagName(constants.Build);
|
const buildElements = itemGroup.getElementsByTagName(constants.Build);
|
||||||
for (let b = 0; b < buildElements.length; b++) {
|
for (let b = 0; b < buildElements.length; b++) {
|
||||||
this.files.push(this.createProjectEntry(buildElements[b].getAttribute(constants.Include), EntryType.File));
|
this.files.push(this.createFileProjectEntry(buildElements[b].getAttribute(constants.Include), EntryType.File));
|
||||||
}
|
}
|
||||||
|
|
||||||
const folderElements = itemGroup.getElementsByTagName(constants.Folder);
|
const folderElements = itemGroup.getElementsByTagName(constants.Folder);
|
||||||
for (let f = 0; f < folderElements.length; f++) {
|
for (let f = 0; f < folderElements.length; f++) {
|
||||||
// don't add Properties folder since it isn't supported for now
|
// don't add Properties folder since it isn't supported for now
|
||||||
if (folderElements[f].getAttribute(constants.Include) !== constants.Properties) {
|
if (folderElements[f].getAttribute(constants.Include) !== constants.Properties) {
|
||||||
this.files.push(this.createProjectEntry(folderElements[f].getAttribute(constants.Include), EntryType.Folder));
|
this.files.push(this.createFileProjectEntry(folderElements[f].getAttribute(constants.Include), EntryType.Folder));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,7 +80,7 @@ export class Project {
|
|||||||
let preDeployScriptCount: number = 0;
|
let preDeployScriptCount: number = 0;
|
||||||
const preDeploy = itemGroup.getElementsByTagName(constants.PreDeploy);
|
const preDeploy = itemGroup.getElementsByTagName(constants.PreDeploy);
|
||||||
for (let pre = 0; pre < preDeploy.length; pre++) {
|
for (let pre = 0; pre < preDeploy.length; pre++) {
|
||||||
this.preDeployScripts.push(this.createProjectEntry(preDeploy[pre].getAttribute(constants.Include), EntryType.File));
|
this.preDeployScripts.push(this.createFileProjectEntry(preDeploy[pre].getAttribute(constants.Include), EntryType.File));
|
||||||
preDeployScriptCount++;
|
preDeployScriptCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,7 +88,7 @@ export class Project {
|
|||||||
let postDeployScriptCount: number = 0;
|
let postDeployScriptCount: number = 0;
|
||||||
const postDeploy = itemGroup.getElementsByTagName(constants.PostDeploy);
|
const postDeploy = itemGroup.getElementsByTagName(constants.PostDeploy);
|
||||||
for (let post = 0; post < postDeploy.length; post++) {
|
for (let post = 0; post < postDeploy.length; post++) {
|
||||||
this.postDeployScripts.push(this.createProjectEntry(postDeploy[post].getAttribute(constants.Include), EntryType.File));
|
this.postDeployScripts.push(this.createFileProjectEntry(postDeploy[post].getAttribute(constants.Include), EntryType.File));
|
||||||
postDeployScriptCount++;
|
postDeployScriptCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,7 +99,7 @@ export class Project {
|
|||||||
// find all none-deployment scripts to include
|
// find all none-deployment scripts to include
|
||||||
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++) {
|
||||||
this.noneDeployScripts.push(this.createProjectEntry(noneItems[n].getAttribute(constants.Include), EntryType.File));
|
this.noneDeployScripts.push(this.createFileProjectEntry(noneItems[n].getAttribute(constants.Include), EntryType.File));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -210,7 +210,7 @@ export class Project {
|
|||||||
await fs.mkdir(absoluteFolderPath, { recursive: true });
|
await fs.mkdir(absoluteFolderPath, { recursive: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
const folderEntry = this.createProjectEntry(relativeFolderPath, EntryType.Folder);
|
const folderEntry = this.createFileProjectEntry(relativeFolderPath, EntryType.Folder);
|
||||||
this.files.push(folderEntry);
|
this.files.push(folderEntry);
|
||||||
|
|
||||||
await this.addToProjFile(folderEntry);
|
await this.addToProjFile(folderEntry);
|
||||||
@@ -222,7 +222,7 @@ export class Project {
|
|||||||
* @param relativeFilePath Relative path of the file
|
* @param relativeFilePath Relative path of the file
|
||||||
* @param contents Contents to be written to the new file
|
* @param contents Contents to be written to the new file
|
||||||
*/
|
*/
|
||||||
public async addScriptItem(relativeFilePath: string, contents?: string, itemType?: string): Promise<ProjectEntry> {
|
public async addScriptItem(relativeFilePath: string, contents?: string, itemType?: string): Promise<FileProjectEntry> {
|
||||||
const absoluteFilePath = path.join(this.projectFolderPath, relativeFilePath);
|
const absoluteFilePath = path.join(this.projectFolderPath, relativeFilePath);
|
||||||
|
|
||||||
if (contents) {
|
if (contents) {
|
||||||
@@ -236,7 +236,7 @@ export class Project {
|
|||||||
throw new Error(constants.noFileExist(absoluteFilePath));
|
throw new Error(constants.noFileExist(absoluteFilePath));
|
||||||
}
|
}
|
||||||
|
|
||||||
const fileEntry = this.createProjectEntry(relativeFilePath, EntryType.File);
|
const fileEntry = this.createFileProjectEntry(relativeFilePath, EntryType.File);
|
||||||
|
|
||||||
let xmlTag;
|
let xmlTag;
|
||||||
switch (itemType) {
|
switch (itemType) {
|
||||||
@@ -258,16 +258,16 @@ export class Project {
|
|||||||
return fileEntry;
|
return fileEntry;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async exclude(entry: ProjectEntry): Promise<void> {
|
public async exclude(entry: FileProjectEntry): Promise<void> {
|
||||||
const toExclude: ProjectEntry[] = this.files.filter(x => x.fsUri.fsPath.startsWith(entry.fsUri.fsPath));
|
const toExclude: FileProjectEntry[] = this.files.filter(x => x.fsUri.fsPath.startsWith(entry.fsUri.fsPath));
|
||||||
await this.removeFromProjFile(toExclude);
|
await this.removeFromProjFile(toExclude);
|
||||||
this.files = this.files.filter(x => !x.fsUri.fsPath.startsWith(entry.fsUri.fsPath));
|
this.files = this.files.filter(x => !x.fsUri.fsPath.startsWith(entry.fsUri.fsPath));
|
||||||
}
|
}
|
||||||
|
|
||||||
public async deleteFileFolder(entry: ProjectEntry): Promise<void> {
|
public async deleteFileFolder(entry: FileProjectEntry): Promise<void> {
|
||||||
// compile a list of folder contents to delete; if entry is a file, contents will contain only itself
|
// compile a list of folder contents to delete; if entry is a file, contents will contain only itself
|
||||||
const toDeleteFiles: ProjectEntry[] = this.files.filter(x => x.fsUri.fsPath.startsWith(entry.fsUri.fsPath) && x.type === EntryType.File);
|
const toDeleteFiles: FileProjectEntry[] = this.files.filter(x => x.fsUri.fsPath.startsWith(entry.fsUri.fsPath) && x.type === EntryType.File);
|
||||||
const toDeleteFolders: ProjectEntry[] = this.files.filter(x => x.fsUri.fsPath.startsWith(entry.fsUri.fsPath) && x.type === EntryType.Folder).sort(x => -x.relativePath.length);
|
const toDeleteFolders: FileProjectEntry[] = this.files.filter(x => x.fsUri.fsPath.startsWith(entry.fsUri.fsPath) && x.type === EntryType.Folder).sort(x => -x.relativePath.length);
|
||||||
|
|
||||||
await Promise.all(toDeleteFiles.map(x => fs.unlink(x.fsUri.fsPath)));
|
await Promise.all(toDeleteFiles.map(x => fs.unlink(x.fsUri.fsPath)));
|
||||||
|
|
||||||
@@ -349,9 +349,19 @@ export class Project {
|
|||||||
await this.addToProjFile(databaseReferenceEntry);
|
await this.addToProjFile(databaseReferenceEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
public createProjectEntry(relativePath: string, entryType: EntryType): ProjectEntry {
|
/**
|
||||||
|
* Adds a SQLCMD variable to the project
|
||||||
|
* @param name name of the variable
|
||||||
|
* @param defaultValue
|
||||||
|
*/
|
||||||
|
public async addSqlCmdVariable(name: string, defaultValue: string) {
|
||||||
|
const sqlCmdVariableEntry = new SqlCmdVariableProjectEntry(name, defaultValue);
|
||||||
|
await this.addToProjFile(sqlCmdVariableEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
public createFileProjectEntry(relativePath: string, entryType: EntryType): FileProjectEntry {
|
||||||
let platformSafeRelativePath = utils.getPlatformSafeFileEntryPath(relativePath);
|
let platformSafeRelativePath = utils.getPlatformSafeFileEntryPath(relativePath);
|
||||||
return new ProjectEntry(Uri.file(path.join(this.projectFolderPath, platformSafeRelativePath)), relativePath, entryType);
|
return new FileProjectEntry(Uri.file(path.join(this.projectFolderPath, platformSafeRelativePath)), relativePath, entryType);
|
||||||
}
|
}
|
||||||
|
|
||||||
private findOrCreateItemGroup(containedTag?: string, prePostScriptExist?: { scriptExist: boolean; }): any {
|
private findOrCreateItemGroup(containedTag?: string, prePostScriptExist?: { scriptExist: boolean; }): any {
|
||||||
@@ -383,7 +393,7 @@ export class Project {
|
|||||||
return outputItemGroup;
|
return outputItemGroup;
|
||||||
}
|
}
|
||||||
|
|
||||||
private addFileToProjFile(path: string, xmlTag: string) {
|
private addFileToProjFile(path: string, xmlTag: string): void {
|
||||||
let itemGroup;
|
let itemGroup;
|
||||||
|
|
||||||
if (xmlTag === constants.PreDeploy || xmlTag === constants.PostDeploy) {
|
if (xmlTag === constants.PreDeploy || xmlTag === constants.PostDeploy) {
|
||||||
@@ -403,7 +413,7 @@ export class Project {
|
|||||||
itemGroup.appendChild(newFileNode);
|
itemGroup.appendChild(newFileNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
private removeFileFromProjFile(path: string) {
|
private removeFileFromProjFile(path: string): void {
|
||||||
const fileNodes = this.projFileXmlDoc.documentElement.getElementsByTagName(constants.Build);
|
const fileNodes = this.projFileXmlDoc.documentElement.getElementsByTagName(constants.Build);
|
||||||
|
|
||||||
for (let i = 0; i < fileNodes.length; i++) {
|
for (let i = 0; i < fileNodes.length; i++) {
|
||||||
@@ -416,14 +426,14 @@ export class Project {
|
|||||||
throw new Error(constants.unableToFindObject(path, constants.fileObject));
|
throw new Error(constants.unableToFindObject(path, constants.fileObject));
|
||||||
}
|
}
|
||||||
|
|
||||||
private addFolderToProjFile(path: string) {
|
private addFolderToProjFile(path: string): void {
|
||||||
const newFolderNode = this.projFileXmlDoc.createElement(constants.Folder);
|
const newFolderNode = this.projFileXmlDoc.createElement(constants.Folder);
|
||||||
newFolderNode.setAttribute(constants.Include, utils.convertSlashesForSqlProj(path));
|
newFolderNode.setAttribute(constants.Include, utils.convertSlashesForSqlProj(path));
|
||||||
|
|
||||||
this.findOrCreateItemGroup(constants.Folder).appendChild(newFolderNode);
|
this.findOrCreateItemGroup(constants.Folder).appendChild(newFolderNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
private removeFolderFromProjFile(path: string) {
|
private removeFolderFromProjFile(path: string): void {
|
||||||
const folderNodes = this.projFileXmlDoc.documentElement.getElementsByTagName(constants.Folder);
|
const folderNodes = this.projFileXmlDoc.documentElement.getElementsByTagName(constants.Folder);
|
||||||
|
|
||||||
for (let i = 0; i < folderNodes.length; i++) {
|
for (let i = 0; i < folderNodes.length; i++) {
|
||||||
@@ -436,6 +446,16 @@ export class Project {
|
|||||||
throw new Error(constants.unableToFindObject(path, constants.folderObject));
|
throw new Error(constants.unableToFindObject(path, constants.folderObject));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private removeSqlCmdVariableFromProjFile(variableName: string): void {
|
||||||
|
const sqlCmdVariableNodes = this.projFileXmlDoc.documentElement.getElementsByTagName(constants.SqlCmdVariable);
|
||||||
|
|
||||||
|
for (let i = 0; i < sqlCmdVariableNodes.length; i++) {
|
||||||
|
if (sqlCmdVariableNodes[i].getAttribute(constants.Include) === variableName) {
|
||||||
|
sqlCmdVariableNodes[i].parentNode.removeChild(sqlCmdVariableNodes[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private addSystemDatabaseReferenceToProjFile(entry: SystemDatabaseReferenceProjectEntry): void {
|
private addSystemDatabaseReferenceToProjFile(entry: SystemDatabaseReferenceProjectEntry): void {
|
||||||
const systemDbReferenceNode = this.projFileXmlDoc.createElement(constants.ArtifactReference);
|
const systemDbReferenceNode = this.projFileXmlDoc.createElement(constants.ArtifactReference);
|
||||||
|
|
||||||
@@ -495,6 +515,54 @@ export class Project {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public addSqlCmdVariableToProjFile(entry: SqlCmdVariableProjectEntry): void {
|
||||||
|
// Remove any entries with the same variable name. It'll be replaced with a new one
|
||||||
|
this.removeFromProjFile(entry);
|
||||||
|
|
||||||
|
const sqlCmdVariableNode = this.projFileXmlDoc.createElement(constants.SqlCmdVariable);
|
||||||
|
sqlCmdVariableNode.setAttribute(constants.Include, entry.variableName);
|
||||||
|
this.addSqlCmdVariableChildren(sqlCmdVariableNode, entry);
|
||||||
|
this.findOrCreateItemGroup(constants.SqlCmdVariable).appendChild(sqlCmdVariableNode);
|
||||||
|
|
||||||
|
// add to the project's loaded sqlcmd variables
|
||||||
|
this.sqlCmdVariables[entry.variableName] = <string>entry.defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
private addSqlCmdVariableChildren(sqlCmdVariableNode: any, entry: SqlCmdVariableProjectEntry): void {
|
||||||
|
// add default value
|
||||||
|
const defaultValueNode = this.projFileXmlDoc.createElement(constants.DefaultValue);
|
||||||
|
const defaultValueText = this.projFileXmlDoc.createTextNode(entry.defaultValue);
|
||||||
|
defaultValueNode.appendChild(defaultValueText);
|
||||||
|
sqlCmdVariableNode.appendChild(defaultValueNode);
|
||||||
|
|
||||||
|
// add value node which is in the format $(SqlCmdVar__x)
|
||||||
|
const valueNode = this.projFileXmlDoc.createElement(constants.Value);
|
||||||
|
const valueText = this.projFileXmlDoc.createTextNode(`$(SqlCmdVar__${this.getNextSqlCmdVariableCounter()})`);
|
||||||
|
valueNode.appendChild(valueText);
|
||||||
|
sqlCmdVariableNode.appendChild(valueNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns the next number that should be used for the new SqlCmd Variable. Old numbers don't get reused even if a SqlCmd Variable
|
||||||
|
* gets removed from the project
|
||||||
|
*/
|
||||||
|
private getNextSqlCmdVariableCounter(): number {
|
||||||
|
const sqlCmdVariableNodes = this.projFileXmlDoc.documentElement.getElementsByTagName(constants.SqlCmdVariable);
|
||||||
|
let highestNumber = 1;
|
||||||
|
|
||||||
|
for (let i = 0; i < sqlCmdVariableNodes.length; i++) {
|
||||||
|
const value: string = sqlCmdVariableNodes[i].getElementsByTagName(constants.Value)[0].childNodes[0].nodeValue;
|
||||||
|
const number = parseInt(value.substring(13).slice(0, -1)); // want the number x in $(SqlCmdVar__x)
|
||||||
|
|
||||||
|
// incremement the counter if there's already a variable with the same number or greater
|
||||||
|
if (number > highestNumber) {
|
||||||
|
highestNumber = number;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return highestNumber + 1;
|
||||||
|
}
|
||||||
|
|
||||||
private async updateImportedTargetsToProjFile(condition: string, projectAttributeVal: string, oldImportNode?: any): Promise<any> {
|
private async updateImportedTargetsToProjFile(condition: string, projectAttributeVal: string, oldImportNode?: any): Promise<any> {
|
||||||
const importNode = this.projFileXmlDoc.createElement(constants.Import);
|
const importNode = this.projFileXmlDoc.createElement(constants.Import);
|
||||||
importNode.setAttribute(constants.Condition, condition);
|
importNode.setAttribute(constants.Condition, condition);
|
||||||
@@ -570,13 +638,16 @@ export class Project {
|
|||||||
private async addToProjFile(entry: ProjectEntry, xmlTag?: string) {
|
private async addToProjFile(entry: ProjectEntry, xmlTag?: string) {
|
||||||
switch (entry.type) {
|
switch (entry.type) {
|
||||||
case EntryType.File:
|
case EntryType.File:
|
||||||
this.addFileToProjFile(entry.relativePath, xmlTag ? xmlTag : constants.Build);
|
this.addFileToProjFile((<FileProjectEntry>entry).relativePath, xmlTag ? xmlTag : constants.Build);
|
||||||
break;
|
break;
|
||||||
case EntryType.Folder:
|
case EntryType.Folder:
|
||||||
this.addFolderToProjFile(entry.relativePath);
|
this.addFolderToProjFile((<FileProjectEntry>entry).relativePath);
|
||||||
break;
|
break;
|
||||||
case EntryType.DatabaseReference:
|
case EntryType.DatabaseReference:
|
||||||
this.addDatabaseReferenceToProjFile(<IDatabaseReferenceProjectEntry>entry);
|
this.addDatabaseReferenceToProjFile(<IDatabaseReferenceProjectEntry>entry);
|
||||||
|
break;
|
||||||
|
case EntryType.SqlCmdVariable:
|
||||||
|
this.addSqlCmdVariableToProjFile(<SqlCmdVariableProjectEntry>entry);
|
||||||
break; // not required but adding so that we dont miss when we add new items
|
break; // not required but adding so that we dont miss when we add new items
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -591,12 +662,15 @@ export class Project {
|
|||||||
for (const entry of entries) {
|
for (const entry of entries) {
|
||||||
switch (entry.type) {
|
switch (entry.type) {
|
||||||
case EntryType.File:
|
case EntryType.File:
|
||||||
this.removeFileFromProjFile(entry.relativePath);
|
this.removeFileFromProjFile((<FileProjectEntry>entry).relativePath);
|
||||||
break;
|
break;
|
||||||
case EntryType.Folder:
|
case EntryType.Folder:
|
||||||
this.removeFolderFromProjFile(entry.relativePath);
|
this.removeFolderFromProjFile((<FileProjectEntry>entry).relativePath);
|
||||||
break;
|
break;
|
||||||
case EntryType.DatabaseReference:
|
case EntryType.DatabaseReference:
|
||||||
|
break;
|
||||||
|
case EntryType.SqlCmdVariable:
|
||||||
|
this.removeSqlCmdVariableFromProjFile((<SqlCmdVariableProjectEntry>entry).variableName);
|
||||||
break; // not required but adding so that we dont miss when we add new items
|
break; // not required but adding so that we dont miss when we add new items
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -638,18 +712,25 @@ export class Project {
|
|||||||
/**
|
/**
|
||||||
* Represents an entry in a project file
|
* Represents an entry in a project file
|
||||||
*/
|
*/
|
||||||
export class ProjectEntry {
|
export abstract class ProjectEntry {
|
||||||
|
type: EntryType;
|
||||||
|
|
||||||
|
constructor(type: EntryType) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class FileProjectEntry extends ProjectEntry {
|
||||||
/**
|
/**
|
||||||
* Absolute file system URI
|
* Absolute file system URI
|
||||||
*/
|
*/
|
||||||
fsUri: Uri;
|
fsUri: Uri;
|
||||||
relativePath: string;
|
relativePath: string;
|
||||||
type: EntryType;
|
|
||||||
|
|
||||||
constructor(uri: Uri, relativePath: string, type: EntryType) {
|
constructor(uri: Uri, relativePath: string, type: EntryType) {
|
||||||
|
super(type);
|
||||||
this.fsUri = uri;
|
this.fsUri = uri;
|
||||||
this.relativePath = relativePath;
|
this.relativePath = relativePath;
|
||||||
this.type = type;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public toString(): string {
|
public toString(): string {
|
||||||
@@ -665,12 +746,12 @@ export class ProjectEntry {
|
|||||||
* Represents a database reference entry in a project file
|
* Represents a database reference entry in a project file
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export interface IDatabaseReferenceProjectEntry extends ProjectEntry {
|
export interface IDatabaseReferenceProjectEntry extends FileProjectEntry {
|
||||||
databaseName: string;
|
databaseName: string;
|
||||||
databaseVariableLiteralValue?: string;
|
databaseVariableLiteralValue?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class DacpacReferenceProjectEntry extends ProjectEntry implements IDatabaseReferenceProjectEntry {
|
export class DacpacReferenceProjectEntry extends FileProjectEntry implements IDatabaseReferenceProjectEntry {
|
||||||
databaseLocation: DatabaseReferenceLocation;
|
databaseLocation: DatabaseReferenceLocation;
|
||||||
databaseVariableLiteralValue?: string;
|
databaseVariableLiteralValue?: string;
|
||||||
|
|
||||||
@@ -688,7 +769,7 @@ export class DacpacReferenceProjectEntry extends ProjectEntry implements IDataba
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class SystemDatabaseReferenceProjectEntry extends ProjectEntry implements IDatabaseReferenceProjectEntry {
|
class SystemDatabaseReferenceProjectEntry extends FileProjectEntry implements IDatabaseReferenceProjectEntry {
|
||||||
constructor(uri: Uri, public ssdtUri: Uri, public databaseVariableLiteralValue: string) {
|
constructor(uri: Uri, public ssdtUri: Uri, public databaseVariableLiteralValue: string) {
|
||||||
super(uri, '', EntryType.DatabaseReference);
|
super(uri, '', EntryType.DatabaseReference);
|
||||||
}
|
}
|
||||||
@@ -711,7 +792,7 @@ class SystemDatabaseReferenceProjectEntry extends ProjectEntry implements IDatab
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class SqlProjectReferenceProjectEntry extends ProjectEntry implements IDatabaseReferenceProjectEntry {
|
export class SqlProjectReferenceProjectEntry extends FileProjectEntry implements IDatabaseReferenceProjectEntry {
|
||||||
projectName: string;
|
projectName: string;
|
||||||
|
|
||||||
constructor(uri: Uri, name: string) {
|
constructor(uri: Uri, name: string) {
|
||||||
@@ -724,10 +805,17 @@ export class SqlProjectReferenceProjectEntry extends ProjectEntry implements IDa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class SqlCmdVariableProjectEntry extends ProjectEntry {
|
||||||
|
constructor(public variableName: string, public defaultValue: string) {
|
||||||
|
super(EntryType.SqlCmdVariable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export enum EntryType {
|
export enum EntryType {
|
||||||
File,
|
File,
|
||||||
Folder,
|
Folder,
|
||||||
DatabaseReference
|
DatabaseReference,
|
||||||
|
SqlCmdVariable
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum DatabaseReferenceLocation {
|
export enum DatabaseReferenceLocation {
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import * as path from 'path';
|
|||||||
import { DataSourcesTreeItem } from './dataSourceTreeItem';
|
import { DataSourcesTreeItem } from './dataSourceTreeItem';
|
||||||
import { BaseProjectTreeItem } from './baseTreeItem';
|
import { BaseProjectTreeItem } from './baseTreeItem';
|
||||||
import * as fileTree from './fileFolderTreeItem';
|
import * as fileTree from './fileFolderTreeItem';
|
||||||
import { Project, ProjectEntry, EntryType } from '../project';
|
import { Project, EntryType, FileProjectEntry } from '../project';
|
||||||
import * as utils from '../../common/utils';
|
import * as utils from '../../common/utils';
|
||||||
import { DatabaseReferencesTreeItem } from './databaseReferencesTreeItem';
|
import { DatabaseReferencesTreeItem } from './databaseReferencesTreeItem';
|
||||||
import { DatabaseProjectItemType, RelativeOuterPath } from '../../common/constants';
|
import { DatabaseProjectItemType, RelativeOuterPath } from '../../common/constants';
|
||||||
@@ -92,7 +92,7 @@ export class ProjectRootTreeItem extends BaseProjectTreeItem {
|
|||||||
/**
|
/**
|
||||||
* Gets the immediate parent tree node for an entry in a project file
|
* Gets the immediate parent tree node for an entry in a project file
|
||||||
*/
|
*/
|
||||||
private getEntryParentNode(entry: ProjectEntry): fileTree.FolderNode | ProjectRootTreeItem {
|
private getEntryParentNode(entry: FileProjectEntry): fileTree.FolderNode | ProjectRootTreeItem {
|
||||||
const relativePathParts = utils.trimChars(utils.trimUri(vscode.Uri.file(this.project.projectFilePath), entry.fsUri), '/').split('/').slice(0, -1); // remove the last part because we only care about the parent
|
const relativePathParts = utils.trimChars(utils.trimUri(vscode.Uri.file(this.project.projectFilePath), entry.fsUri), '/').split('/').slice(0, -1); // remove the last part because we only care about the parent
|
||||||
|
|
||||||
if (relativePathParts.length === 0) {
|
if (relativePathParts.length === 0) {
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ export let publishProfileIntegratedSecurityBaseline: string;
|
|||||||
export let publishProfileSqlLoginBaseline: string;
|
export let publishProfileSqlLoginBaseline: string;
|
||||||
export let openProjectWithProjectReferencesBaseline: string;
|
export let openProjectWithProjectReferencesBaseline: string;
|
||||||
export let openSqlProjectWithPrePostDeploymentError: string;
|
export let openSqlProjectWithPrePostDeploymentError: string;
|
||||||
|
export let openSqlProjectWithAdditionalSqlCmdVariablesBaseline: string;
|
||||||
|
|
||||||
const baselineFolderPath = __dirname;
|
const baselineFolderPath = __dirname;
|
||||||
|
|
||||||
@@ -37,6 +38,7 @@ export async function loadBaselines() {
|
|||||||
publishProfileSqlLoginBaseline = await loadBaseline(baselineFolderPath, 'publishProfileSqlLoginBaseline.publish.xml');
|
publishProfileSqlLoginBaseline = await loadBaseline(baselineFolderPath, 'publishProfileSqlLoginBaseline.publish.xml');
|
||||||
openProjectWithProjectReferencesBaseline = await loadBaseline(baselineFolderPath, 'openSqlProjectWithProjectReferenceBaseline.xml');
|
openProjectWithProjectReferencesBaseline = await loadBaseline(baselineFolderPath, 'openSqlProjectWithProjectReferenceBaseline.xml');
|
||||||
openSqlProjectWithPrePostDeploymentError = await loadBaseline(baselineFolderPath, 'openSqlProjectWithPrePostDeploymentError.xml');
|
openSqlProjectWithPrePostDeploymentError = await loadBaseline(baselineFolderPath, 'openSqlProjectWithPrePostDeploymentError.xml');
|
||||||
|
openSqlProjectWithAdditionalSqlCmdVariablesBaseline = await loadBaseline(baselineFolderPath, 'openSqlProjectWithAdditionalSqlCmdVariablesBaseline.xml');
|
||||||
}
|
}
|
||||||
|
|
||||||
async function loadBaseline(baselineFolderPath: string, fileName: string): Promise<string> {
|
async function loadBaseline(baselineFolderPath: string, fileName: string): Promise<string> {
|
||||||
|
|||||||
@@ -0,0 +1,112 @@
|
|||||||
|
<?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"/>
|
||||||
|
<Folder Include="Tables"/>
|
||||||
|
<Folder Include="Views"/>
|
||||||
|
<Folder Include="Views\Maintenance"/>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Build Include="Tables\Users.sql"/>
|
||||||
|
<Build Include="Tables\Action History.sql"/>
|
||||||
|
<Build Include="Views\Maintenance\Database Performance.sql"/>
|
||||||
|
<Build Include="..\Test\Test.sql"/>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Folder Include="Views\User"/>
|
||||||
|
<Build Include="Views\User\Profile.sql"/>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<SqlCmdVariable Include="BackupDatabaseName">
|
||||||
|
<DefaultValue>MyBackupDatabase</DefaultValue>
|
||||||
|
<Value>$(SqlCmdVar__2)</Value>
|
||||||
|
</SqlCmdVariable>
|
||||||
|
<SqlCmdVariable Include="TestDatabaseName">
|
||||||
|
<DefaultValue>TestDb</DefaultValue>
|
||||||
|
<Value>$(SqlCmdVar__3)</Value>
|
||||||
|
</SqlCmdVariable>
|
||||||
|
<SqlCmdVariable Include="ProdDatabaseName">
|
||||||
|
<DefaultValue>NewProdName</DefaultValue>
|
||||||
|
<Value>$(SqlCmdVar__4)</Value>
|
||||||
|
</SqlCmdVariable>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ArtifactReference Condition="'$(NetCoreBuild)' == 'true'" Include="$(NETCoreTargetsPath)\SystemDacpacs\130\master.dacpac">
|
||||||
|
<SuppressMissingDependenciesErrors>False</SuppressMissingDependenciesErrors>
|
||||||
|
<DatabaseVariableLiteralValue>master</DatabaseVariableLiteralValue>
|
||||||
|
</ArtifactReference>
|
||||||
|
<ArtifactReference Condition="'$(NetCoreBuild)' != 'true'" Include="$(DacPacRootPath)\Extensions\Microsoft\SQLDB\Extensions\SqlServer\130\SqlSchemas\master.dacpac">
|
||||||
|
<SuppressMissingDependenciesErrors>False</SuppressMissingDependenciesErrors>
|
||||||
|
<DatabaseVariableLiteralValue>master</DatabaseVariableLiteralValue>
|
||||||
|
</ArtifactReference>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<PreDeploy Include="Script.PreDeployment1.sql"/>
|
||||||
|
<None Include="Script.PreDeployment2.sql"/>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<PostDeploy Include="Script.PostDeployment1.sql"/>
|
||||||
|
<None Include="Tables\Script.PostDeployment1.sql"/>
|
||||||
|
</ItemGroup>
|
||||||
|
<Target Name="AfterClean">
|
||||||
|
<Delete Files="$(BaseIntermediateOutputPath)\project.assets.json"/>
|
||||||
|
</Target>
|
||||||
|
</Project>
|
||||||
@@ -291,6 +291,31 @@ describe('Project: sqlproj content operations', function (): void {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('Project: add SQLCMD Variables', function (): void {
|
||||||
|
before(async function (): Promise<void> {
|
||||||
|
await baselines.loadBaselines();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should update .sqlproj with new sqlcmd variables', async function (): Promise<void> {
|
||||||
|
projFilePath = await testUtils.createTestSqlProjFile(baselines.openProjectFileBaseline);
|
||||||
|
const project = await Project.openProject(projFilePath);
|
||||||
|
should(Object.keys(project.sqlCmdVariables).length).equal(2);
|
||||||
|
|
||||||
|
// add a new variable
|
||||||
|
await project.addSqlCmdVariable('TestDatabaseName', 'TestDb');
|
||||||
|
|
||||||
|
// add a variable with the same name as an existing sqlcmd variable and the old entry should be replaced with the new one
|
||||||
|
await project.addSqlCmdVariable('ProdDatabaseName', 'NewProdName');
|
||||||
|
|
||||||
|
should(Object.keys(project.sqlCmdVariables).length).equal(3);
|
||||||
|
should(project.sqlCmdVariables['TestDatabaseName']).equal('TestDb');
|
||||||
|
should(project.sqlCmdVariables['ProdDatabaseName']).equal('NewProdName', 'ProdDatabaseName value should have been updated to the new value');
|
||||||
|
|
||||||
|
const projFileText = (await fs.readFile(projFilePath)).toString();
|
||||||
|
should(projFileText).equal(baselines.openSqlProjectWithAdditionalSqlCmdVariablesBaseline.trim());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('Project: round trip updates', function (): void {
|
describe('Project: round trip updates', function (): void {
|
||||||
before(async function (): Promise<void> {
|
before(async function (): Promise<void> {
|
||||||
await baselines.loadBaselines();
|
await baselines.loadBaselines();
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import { SqlDatabaseProjectTreeViewProvider } from '../controllers/databaseProje
|
|||||||
import { ProjectsController } from '../controllers/projectController';
|
import { ProjectsController } from '../controllers/projectController';
|
||||||
import { promises as fs } from 'fs';
|
import { promises as fs } from 'fs';
|
||||||
import { createContext, TestContext, mockDacFxResult } from './testContext';
|
import { createContext, TestContext, mockDacFxResult } from './testContext';
|
||||||
import { Project, ProjectEntry, reservedProjectFolders, SystemDatabase } from '../models/project';
|
import { Project, reservedProjectFolders, SystemDatabase, FileProjectEntry } from '../models/project';
|
||||||
import { PublishDatabaseDialog } from '../dialogs/publishDatabaseDialog';
|
import { PublishDatabaseDialog } from '../dialogs/publishDatabaseDialog';
|
||||||
import { IPublishSettings, IGenerateScriptSettings } from '../models/IPublishSettings';
|
import { IPublishSettings, IGenerateScriptSettings } from '../models/IPublishSettings';
|
||||||
import { exists } from '../common/utils';
|
import { exists } from '../common/utils';
|
||||||
@@ -584,7 +584,7 @@ describe.skip('ProjectsController: round trip feature with SSDT', function (): v
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
async function setupDeleteExcludeTest(proj: Project): Promise<[ProjectEntry, ProjectRootTreeItem]> {
|
async function setupDeleteExcludeTest(proj: Project): Promise<[FileProjectEntry, ProjectRootTreeItem]> {
|
||||||
await proj.addFolderItem('UpperFolder');
|
await proj.addFolderItem('UpperFolder');
|
||||||
await proj.addFolderItem('UpperFolder/LowerFolder');
|
await proj.addFolderItem('UpperFolder/LowerFolder');
|
||||||
const scriptEntry = await proj.addScriptItem('UpperFolder/LowerFolder/someScript.sql', 'not a real script');
|
const scriptEntry = await proj.addScriptItem('UpperFolder/LowerFolder/someScript.sql', 'not a real script');
|
||||||
|
|||||||
@@ -52,19 +52,19 @@ describe.skip('Project Tree tests', function (): void {
|
|||||||
|
|
||||||
// nested entries before explicit top-level folder entry
|
// nested entries before explicit top-level folder entry
|
||||||
// also, ordering of files/folders at all levels
|
// also, ordering of files/folders at all levels
|
||||||
proj.files.push(proj.createProjectEntry(path.join('someFolder', 'bNestedTest.sql'), EntryType.File));
|
proj.files.push(proj.createFileProjectEntry(path.join('someFolder', 'bNestedTest.sql'), EntryType.File));
|
||||||
proj.files.push(proj.createProjectEntry(path.join('someFolder', 'bNestedFolder'), EntryType.Folder));
|
proj.files.push(proj.createFileProjectEntry(path.join('someFolder', 'bNestedFolder'), EntryType.Folder));
|
||||||
proj.files.push(proj.createProjectEntry(path.join('someFolder', 'aNestedTest.sql'), EntryType.File));
|
proj.files.push(proj.createFileProjectEntry(path.join('someFolder', 'aNestedTest.sql'), EntryType.File));
|
||||||
proj.files.push(proj.createProjectEntry(path.join('someFolder', 'aNestedFolder'), EntryType.Folder));
|
proj.files.push(proj.createFileProjectEntry(path.join('someFolder', 'aNestedFolder'), EntryType.Folder));
|
||||||
proj.files.push(proj.createProjectEntry('someFolder', EntryType.Folder));
|
proj.files.push(proj.createFileProjectEntry('someFolder', EntryType.Folder));
|
||||||
|
|
||||||
// duplicate files
|
// duplicate files
|
||||||
proj.files.push(proj.createProjectEntry('duplicate.sql', EntryType.File));
|
proj.files.push(proj.createFileProjectEntry('duplicate.sql', EntryType.File));
|
||||||
proj.files.push(proj.createProjectEntry('duplicate.sql', EntryType.File));
|
proj.files.push(proj.createFileProjectEntry('duplicate.sql', EntryType.File));
|
||||||
|
|
||||||
// duplicate folders
|
// duplicate folders
|
||||||
proj.files.push(proj.createProjectEntry('duplicateFolder', EntryType.Folder));
|
proj.files.push(proj.createFileProjectEntry('duplicateFolder', EntryType.Folder));
|
||||||
proj.files.push(proj.createProjectEntry('duplicateFolder', EntryType.Folder));
|
proj.files.push(proj.createFileProjectEntry('duplicateFolder', EntryType.Folder));
|
||||||
|
|
||||||
const tree = new ProjectRootTreeItem(proj);
|
const tree = new ProjectRootTreeItem(proj);
|
||||||
should(tree.children.map(x => x.uri.path)).deepEqual([
|
should(tree.children.map(x => x.uri.path)).deepEqual([
|
||||||
@@ -100,9 +100,9 @@ describe.skip('Project Tree tests', function (): void {
|
|||||||
|
|
||||||
// nested entries before explicit top-level folder entry
|
// nested entries before explicit top-level folder entry
|
||||||
// also, ordering of files/folders at all levels
|
// also, ordering of files/folders at all levels
|
||||||
proj.files.push(proj.createProjectEntry('someFolder1\\MyNestedFolder1\\MyFile1.sql', EntryType.File));
|
proj.files.push(proj.createFileProjectEntry('someFolder1\\MyNestedFolder1\\MyFile1.sql', EntryType.File));
|
||||||
proj.files.push(proj.createProjectEntry('someFolder1\\MyNestedFolder2', EntryType.Folder));
|
proj.files.push(proj.createFileProjectEntry('someFolder1\\MyNestedFolder2', EntryType.Folder));
|
||||||
proj.files.push(proj.createProjectEntry('someFolder1\\MyFile2.sql', EntryType.File));
|
proj.files.push(proj.createFileProjectEntry('someFolder1\\MyFile2.sql', EntryType.File));
|
||||||
|
|
||||||
const tree = new ProjectRootTreeItem(proj);
|
const tree = new ProjectRootTreeItem(proj);
|
||||||
should(tree.children.map(x => x.uri.path)).deepEqual([
|
should(tree.children.map(x => x.uri.path)).deepEqual([
|
||||||
@@ -123,9 +123,9 @@ describe.skip('Project Tree tests', function (): void {
|
|||||||
|
|
||||||
// nested entries before explicit top-level folder entry
|
// nested entries before explicit top-level folder entry
|
||||||
// also, ordering of files/folders at all levels
|
// also, ordering of files/folders at all levels
|
||||||
proj.files.push(proj.createProjectEntry('..\\someFolder1\\MyNestedFolder1\\MyFile1.sql', EntryType.File));
|
proj.files.push(proj.createFileProjectEntry('..\\someFolder1\\MyNestedFolder1\\MyFile1.sql', EntryType.File));
|
||||||
proj.files.push(proj.createProjectEntry('..\\..\\someFolder2\\MyFile2.sql', EntryType.File));
|
proj.files.push(proj.createFileProjectEntry('..\\..\\someFolder2\\MyFile2.sql', EntryType.File));
|
||||||
proj.files.push(proj.createProjectEntry('..\\..\\someFolder3', EntryType.Folder)); // folder should not be counted (same as SSDT)
|
proj.files.push(proj.createFileProjectEntry('..\\..\\someFolder3', EntryType.Folder)); // folder should not be counted (same as SSDT)
|
||||||
|
|
||||||
const tree = new ProjectRootTreeItem(proj);
|
const tree = new ProjectRootTreeItem(proj);
|
||||||
should(tree.children.map(x => x.uri.path)).deepEqual([
|
should(tree.children.map(x => x.uri.path)).deepEqual([
|
||||||
|
|||||||
Reference in New Issue
Block a user