diff --git a/Packages.props b/Packages.props
index 3017a447..2399365b 100644
--- a/Packages.props
+++ b/Packages.props
@@ -23,7 +23,7 @@
-
+
diff --git a/bin/nuget/Microsoft.SqlServer.DacFx.Projects.162.0.28-alpha.nupkg b/bin/nuget/Microsoft.SqlServer.DacFx.Projects.162.0.28-alpha.nupkg
deleted file mode 100644
index 32b039cc..00000000
Binary files a/bin/nuget/Microsoft.SqlServer.DacFx.Projects.162.0.28-alpha.nupkg and /dev/null differ
diff --git a/bin/nuget/Microsoft.SqlServer.DacFx.Projects.162.0.32-alpha.nupkg b/bin/nuget/Microsoft.SqlServer.DacFx.Projects.162.0.32-alpha.nupkg
new file mode 100644
index 00000000..bea4926a
Binary files /dev/null and b/bin/nuget/Microsoft.SqlServer.DacFx.Projects.162.0.32-alpha.nupkg differ
diff --git a/src/Microsoft.SqlTools.ServiceLayer/SqlProjects/Contracts/Folders/ExcludeFolder.cs b/src/Microsoft.SqlTools.ServiceLayer/SqlProjects/Contracts/Folders/ExcludeFolder.cs
new file mode 100644
index 00000000..cc4fdd4b
--- /dev/null
+++ b/src/Microsoft.SqlTools.ServiceLayer/SqlProjects/Contracts/Folders/ExcludeFolder.cs
@@ -0,0 +1,18 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+using Microsoft.SqlTools.Hosting.Protocol.Contracts;
+using Microsoft.SqlTools.ServiceLayer.Utility;
+
+namespace Microsoft.SqlTools.ServiceLayer.SqlProjects.Contracts
+{
+ ///
+ /// Exclude a folder and its contents from a project
+ ///
+ public class ExcludeFolderRequest
+ {
+ public static readonly RequestType Type = RequestType.Create("sqlProjects/excludeFolder");
+ }
+}
diff --git a/src/Microsoft.SqlTools.ServiceLayer/SqlProjects/Contracts/Folders/MoveFolder.cs b/src/Microsoft.SqlTools.ServiceLayer/SqlProjects/Contracts/Folders/MoveFolder.cs
new file mode 100644
index 00000000..c6fc45d3
--- /dev/null
+++ b/src/Microsoft.SqlTools.ServiceLayer/SqlProjects/Contracts/Folders/MoveFolder.cs
@@ -0,0 +1,31 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+#nullable disable
+
+using Microsoft.SqlTools.Hosting.Protocol.Contracts;
+using Microsoft.SqlTools.ServiceLayer.Utility;
+
+namespace Microsoft.SqlTools.ServiceLayer.SqlProjects.Contracts
+{
+ ///
+ /// Parameters for moving a folder
+ ///
+ public class MoveFolderParams : FolderParams
+ {
+ ///
+ /// Path of the folder, typically relative to the .sqlproj file
+ ///
+ public string DestinationPath { get; set; }
+ }
+
+ ///
+ /// Move a folder and its contents within a project
+ ///
+ public class MoveFolderRequest
+ {
+ public static readonly RequestType Type = RequestType.Create("sqlProjects/moveFolder");
+ }
+}
diff --git a/src/Microsoft.SqlTools.ServiceLayer/SqlProjects/SqlProjectsService.cs b/src/Microsoft.SqlTools.ServiceLayer/SqlProjects/SqlProjectsService.cs
index bae3ede5..f9112560 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/SqlProjects/SqlProjectsService.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/SqlProjects/SqlProjectsService.cs
@@ -81,6 +81,8 @@ namespace Microsoft.SqlTools.ServiceLayer.SqlProjects
serviceHost.SetRequestHandler(GetFoldersRequest.Type, HandleGetFoldersRequest, isParallelProcessingSupported: true);
serviceHost.SetRequestHandler(AddFolderRequest.Type, HandleAddFolderRequest, isParallelProcessingSupported: false);
serviceHost.SetRequestHandler(DeleteFolderRequest.Type, HandleDeleteFolderRequest, isParallelProcessingSupported: false);
+ serviceHost.SetRequestHandler(ExcludeFolderRequest.Type, HandleExcludeFolderRequest, isParallelProcessingSupported: false);
+ serviceHost.SetRequestHandler(MoveFolderRequest.Type, HandleMoveFolderRequest, isParallelProcessingSupported: false);
// SQLCMD variable functions
serviceHost.SetRequestHandler(GetSqlCmdVariablesRequest.Type, HandleGetSqlCmdVariablesRequest, isParallelProcessingSupported: true);
@@ -343,6 +345,16 @@ namespace Microsoft.SqlTools.ServiceLayer.SqlProjects
await RunWithErrorHandling(() => GetProject(requestParams.ProjectUri).Folders.Delete(requestParams.Path), requestContext);
}
+ internal async Task HandleExcludeFolderRequest(FolderParams requestParams, RequestContext requestContext)
+ {
+ await RunWithErrorHandling(() => GetProject(requestParams.ProjectUri).Folders.Exclude(requestParams.Path), requestContext);
+ }
+
+ internal async Task HandleMoveFolderRequest(MoveFolderParams requestParams, RequestContext requestContext)
+ {
+ await RunWithErrorHandling(() => GetProject(requestParams.ProjectUri).Folders.Move(requestParams.Path, requestParams.DestinationPath), requestContext);
+ }
+
#endregion
#endregion
diff --git a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/SqlProjects/SqlProjectsServiceTests.cs b/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/SqlProjects/SqlProjectsServiceTests.cs
index 78ebce82..ec87835d 100644
--- a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/SqlProjects/SqlProjectsServiceTests.cs
+++ b/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/SqlProjects/SqlProjectsServiceTests.cs
@@ -372,7 +372,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.SqlProjects
}
[Test]
- public async Task TestPostDeploymentScriptAddDeleteExcludeMove()
+ public async Task TestPostDeploymentScriptOperations()
{
// Setup
SqlProjectsService service = new();
@@ -816,9 +816,9 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.SqlProjects
requestMock.AssertSuccess(nameof(service.HandleAddFolderRequest));
Assert.AreEqual(1, service.Projects[projectUri].Folders.Count, "Folder count after add");
Assert.IsTrue(Directory.Exists(Path.Join(Path.GetDirectoryName(projectUri), folderParams.Path)), $"Subfolder '{folderParams.Path}' expected to exist on disk");
- Assert.IsTrue(service.Projects[projectUri].Folders.Contains(folderParams.Path), $"SqlObjectScripts expected to contain {folderParams.Path}");
+ Assert.IsTrue(service.Projects[projectUri].Folders.Contains(folderParams.Path), $"Folders expected to contain {folderParams.Path}");
- // Validate getting a list of the post-deployment scripts
+ // Validate getting a list of the folders
MockRequest getMock = new();
await service.HandleGetFoldersRequest(new SqlProjectParams()
{
@@ -829,12 +829,48 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.SqlProjects
Assert.AreEqual(1, getMock.Result.Folders.Length);
Assert.AreEqual(folderParams.Path, getMock.Result.Folders[0]);
+ // Validate moving a folder
+ requestMock = new();
+ const string parentFolder = "NewParentFolder";
+ MoveFolderParams moveFolderParams = new MoveFolderParams()
+ {
+ ProjectUri = projectUri,
+ Path = folderParams.Path,
+ DestinationPath = $@"{parentFolder}\{folderParams.Path}"
+ };
+
+ await service.HandleMoveFolderRequest(moveFolderParams, requestMock.Object);
+
+ requestMock.AssertSuccess(nameof(service.HandleMoveFolderRequest));
+ Assert.AreEqual(2, service.Projects[projectUri].Folders.Count, "Folder count after move");
+ Assert.IsTrue(service.Projects[projectUri].Folders.Contains(parentFolder), $"Folders expected to contain '{parentFolder}' after move");
+ Assert.IsTrue(service.Projects[projectUri].Folders.Contains(moveFolderParams.DestinationPath), $"Folders expected to contain '{moveFolderParams.DestinationPath}' after move");
+
+ // Validate excluding a folder
+ requestMock = new();
+ await service.HandleExcludeFolderRequest(new FolderParams()
+ {
+ ProjectUri = projectUri,
+ Path = moveFolderParams.DestinationPath
+ }, requestMock.Object);
+
+ requestMock.AssertSuccess(nameof(service.HandleExcludeFolderRequest));
+ Assert.AreEqual(1, service.Projects[projectUri].Folders.Count, "Folder count after exclude");
+ Assert.IsTrue(service.Projects[projectUri].Folders.Contains(parentFolder), $"Folders expected to still contain '{parentFolder}' after exclude");
+ Assert.IsFalse(service.Projects[projectUri].Folders.Contains(moveFolderParams.DestinationPath), $"Folders expected to no longer contain '{moveFolderParams.DestinationPath}' after exclude");
+ Assert.IsTrue(Directory.Exists(Path.Join(service.Projects[projectUri].DirectoryPath, parentFolder, folderParams.Path)), "Folder should still exist on disk after exclude");
+
// Validate deleting a folder
requestMock = new();
- await service.HandleDeleteFolderRequest(folderParams, requestMock.Object);
+ await service.HandleDeleteFolderRequest(new FolderParams()
+ {
+ ProjectUri = projectUri,
+ Path = parentFolder
+ }, requestMock.Object);
requestMock.AssertSuccess(nameof(service.HandleDeleteFolderRequest));
Assert.AreEqual(0, service.Projects[projectUri].Folders.Count, "Folder count after delete");
+ Assert.IsFalse(Directory.Exists(Path.Join(service.Projects[projectUri].DirectoryPath, parentFolder)), "Folder should have been deleted from disk");
}
[Test]