Skip to content

[automated] Merge branch 'release/9.0.2xx' => 'main' #45793

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 29 commits into from
Jan 10, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
405c63f
Update dependencies from https://github.com/dotnet/roslyn build 20250…
dotnet-maestro[bot] Jan 6, 2025
2dd724c
Update dependencies from https://github.com/dotnet/roslyn build 20250…
dotnet-maestro[bot] Jan 6, 2025
04fff54
Update dependencies from https://github.com/dotnet/roslyn build 20250…
dotnet-maestro[bot] Jan 6, 2025
a09b425
Update dependencies from https://github.com/dotnet/roslyn build 20250…
dotnet-maestro[bot] Jan 6, 2025
3b633ce
Update dependencies from https://github.com/dotnet/roslyn build 20250…
dotnet-maestro[bot] Jan 6, 2025
f781745
Update dependencies from https://github.com/dotnet/roslyn build 20250…
dotnet-maestro[bot] Jan 6, 2025
47270ca
Update dependencies from https://github.com/dotnet/roslyn build 20250…
dotnet-maestro[bot] Jan 6, 2025
3048c1c
Update dependencies from https://github.com/dotnet/roslyn build 20250…
dotnet-maestro[bot] Jan 7, 2025
e5e2927
Install the host rather than upgrading it
marcpopMSFT Jan 7, 2025
1613483
Remove testsdkrpm entirely as it breaks because the host is already i…
marcpopMSFT Jan 7, 2025
0a87b36
Update dependencies from https://github.com/dotnet/razor build 202501…
dotnet-maestro[bot] Jan 7, 2025
cf6faae
Remove the test rpm step as it's blocking builds and disabled in all …
marcpopMSFT Jan 7, 2025
72d0b4a
Update branding to 9.0.103
vseanreesermsft Jan 7, 2025
8b25057
Update dependencies from https://github.com/dotnet/roslyn build 20250…
dotnet-maestro[bot] Jan 7, 2025
1b3a70f
Update branding to 9.0.103 (#45759)
marcpopMSFT Jan 7, 2025
2cba37e
Update dependencies from https://github.com/dotnet/templating build 2…
dotnet-maestro[bot] Jan 8, 2025
e979f25
[release/9.0.1xx] Update dependencies from dotnet/templating (#45773)
v-wuzhai Jan 8, 2025
e7de18f
Merge branch 'release/9.0.2xx' of https://github.com/dotnet/sdk into …
v-wuzhai Jan 8, 2025
0d0a3ef
[release/9.0.2xx] Update dependencies from dotnet/razor (#45754)
v-wuzhai Jan 8, 2025
ffd4fa4
[release/9.0.2xx] Update dependencies from nuget/nuget.client (#45748)
dotnet-maestro[bot] Jan 8, 2025
afc8829
[release/9.0.2xx] Update dependencies from dotnet/roslyn (#45725)
v-wuzhai Jan 8, 2025
3431945
[automated] Merge branch 'release/9.0.1xx' => 'release/9.0.2xx' (#45771)
v-wuzhai Jan 8, 2025
5faffec
Add posix dmp copy command (#45704)
Forgind Jan 8, 2025
ef91c4e
sln-remove: Support for slnx (#45160)
edvilme Jan 8, 2025
d2940a1
[release/9.0.2xx] Update dependencies from nuget/nuget.client (#45787)
dotnet-maestro[bot] Jan 8, 2025
36432e4
Update dependencies from https://github.com/dotnet/razor build 202501…
dotnet-maestro[bot] Jan 8, 2025
bee76bd
[release/9.0.2xx] Update dependencies from dotnet/razor (#45805)
v-wuzhai Jan 9, 2025
cff7b34
Merge branch 'main' of https://github.com/dotnet/sdk into merge/relea…
v-wuzhai Jan 9, 2025
ac30ec5
Merge branch 'main' into merge/release/9.0.2xx-to-main
Forgind Jan 10, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
124 changes: 101 additions & 23 deletions src/Cli/dotnet/commands/dotnet-sln/remove/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,58 +2,136 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System.CommandLine;
using Microsoft.Build.Construction;
using Microsoft.Build.Execution;
using Microsoft.DotNet.Cli;
using Microsoft.DotNet.Cli.Sln.Internal;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.Tools.Common;
using Microsoft.Extensions.EnvironmentAbstractions;
using Microsoft.VisualStudio.SolutionPersistence;
using Microsoft.VisualStudio.SolutionPersistence.Model;
using Microsoft.VisualStudio.SolutionPersistence.Serializer.SlnV12;

namespace Microsoft.DotNet.Tools.Sln.Remove
{
internal class RemoveProjectFromSolutionCommand : CommandBase
{
private readonly string _fileOrDirectory;
private readonly IReadOnlyCollection<string> _arguments;
private readonly IReadOnlyCollection<string> _projects;

private int CountNonFolderDescendants(
SolutionModel solution,
SolutionFolderModel item,
Dictionary<SolutionFolderModel, SolutionItemModel[]> solutionItemsGroupedByParent,
Dictionary<SolutionFolderModel, int> cached)
{
if (cached.ContainsKey(item))
{
return cached[item];
}
int count = item.Files?.Count ?? 0;
var children = solutionItemsGroupedByParent.TryGetValue(item, out var items) ? items : Array.Empty<SolutionItemModel>();
foreach (var child in children)
{
count += child is SolutionFolderModel folderModel
? CountNonFolderDescendants(solution, folderModel, solutionItemsGroupedByParent, cached)
: 1;
}
cached.Add(item, count);
return count;
}

public RemoveProjectFromSolutionCommand(ParseResult parseResult) : base(parseResult)
{
_fileOrDirectory = parseResult.GetValue(SlnCommandParser.SlnArgument);

_arguments = (parseResult.GetValue(SlnRemoveParser.ProjectPathArgument) ?? Array.Empty<string>()).ToList().AsReadOnly();
_projects = (parseResult.GetValue(SlnRemoveParser.ProjectPathArgument) ?? Array.Empty<string>()).ToList().AsReadOnly();

SlnArgumentValidator.ParseAndValidateArguments(_fileOrDirectory, _arguments, SlnArgumentValidator.CommandType.Remove);
SlnArgumentValidator.ParseAndValidateArguments(_fileOrDirectory, _projects, SlnArgumentValidator.CommandType.Remove);
}

public override int Execute()
{
SlnFile slnFile = SlnFileFactory.CreateFromFileOrDirectory(_fileOrDirectory);
string solutionFileFullPath = SlnCommandParser.GetSlnFileFullPath(_fileOrDirectory);
if (_projects.Count == 0)
{
throw new GracefulException(CommonLocalizableStrings.SpecifyAtLeastOneProjectToRemove);
}

try
{
var relativeProjectPaths = _projects.Select(p =>
{
var fullPath = Path.GetFullPath(p);
return Path.GetRelativePath(
Path.GetDirectoryName(solutionFileFullPath),
Directory.Exists(fullPath)
? MsbuildProject.GetProjectFileFromDirectory(fullPath).FullName
: fullPath);
});
RemoveProjectsAsync(solutionFileFullPath, relativeProjectPaths, CancellationToken.None).Wait();
return 0;
}
catch (Exception ex) when (ex is not GracefulException)
{
if (ex is SolutionException || ex.InnerException is SolutionException)
{
throw new GracefulException(CommonLocalizableStrings.InvalidSolutionFormatString, solutionFileFullPath, ex.Message);
}
if (ex.InnerException is GracefulException)
{
throw ex.InnerException;
}
throw new GracefulException(ex.Message, ex);
}
}

private async Task RemoveProjectsAsync(string solutionFileFullPath, IEnumerable<string> projectPaths, CancellationToken cancellationToken)
{
ISolutionSerializer serializer = SlnCommandParser.GetSolutionSerializer(solutionFileFullPath);
SolutionModel solution = await serializer.OpenAsync(solutionFileFullPath, cancellationToken);

var baseDirectory = PathUtility.EnsureTrailingSlash(slnFile.BaseDirectory);
var relativeProjectPaths = _arguments.Select(p =>
// set UTF8 BOM encoding for .sln
if (serializer is ISolutionSerializer<SlnV12SerializerSettings> v12Serializer)
{
var fullPath = Path.GetFullPath(p);
return Path.GetRelativePath(
baseDirectory,
Directory.Exists(fullPath) ?
MsbuildProject.GetProjectFileFromDirectory(fullPath).FullName :
fullPath
);
});
solution.SerializerExtension = v12Serializer.CreateModelExtension(new()
{
Encoding = new UTF8Encoding(encoderShouldEmitUTF8Identifier: true)
});
}

bool slnChanged = false;
foreach (var path in relativeProjectPaths)
foreach (var projectPath in projectPaths)
{
slnChanged |= slnFile.RemoveProject(path);
var project = solution.FindProject(projectPath);
if (project != null)
{
solution.RemoveProject(project);
Reporter.Output.WriteLine(CommonLocalizableStrings.ProjectRemovedFromTheSolution, projectPath);
}
else
{
Reporter.Output.WriteLine(CommonLocalizableStrings.ProjectNotFoundInTheSolution, projectPath);
}
}

slnFile.RemoveEmptyConfigurationSections();
Dictionary<SolutionFolderModel, SolutionItemModel[]> solutionItemsGroupedByParent = solution.SolutionItems
.Where(i => i.Parent != null)
.GroupBy(i => i.Parent)
.ToDictionary(g => g.Key, g => g.ToArray());

slnFile.RemoveEmptySolutionFolders();
Dictionary<SolutionFolderModel, int> nonFolderDescendantsCount = new();
foreach (var item in solution.SolutionFolders)
{
CountNonFolderDescendants(solution, item, solutionItemsGroupedByParent, nonFolderDescendantsCount);
}

if (slnChanged)
var emptyFolders = nonFolderDescendantsCount.Where(i => i.Value == 0).Select(i => i.Key);
foreach (var folder in emptyFolders)
{
slnFile.Write();
solution.RemoveFolder(folder);
}

return 0;
await serializer.SaveAsync(solutionFileFullPath, solution, cancellationToken);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<Solution>
<Folder Name="/EmptyFolder/" />
<Folder Name="/EmptyFolder/NestedEmptyFolder/" />
<Folder Name="/NestedSolution/" />
<Folder Name="/NestedSolution/NestedFolder/" />
<Folder Name="/NestedSolution/NestedFolder/NestedFolder/">
<Project Path="ConsoleApp2/ConsoleApp2.csproj" />
</Folder>
<Folder Name="/NewFolder1/" />
<Folder Name="/NewFolder1/NewFolder2/">
<File Path="TextFile1.txt" />
</Folder>
<Folder Name="/Root Empty Folder/" />
<Project Path="ConsoleApp1/ConsoleApp1.csproj" />
</Solution>
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26006.2
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "App", "App\App.csproj", "{7072A694-548F-4CAE-A58F-12D257D5F486}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|x64.ActiveCfg = Debug|x64
{7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|x64.Build.0 = Debug|x64
{7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|x86.ActiveCfg = Debug|x86
{7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|x86.Build.0 = Debug|x86
{7072A694-548F-4CAE-A58F-12D257D5F486}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7072A694-548F-4CAE-A58F-12D257D5F486}.Release|Any CPU.Build.0 = Release|Any CPU
{7072A694-548F-4CAE-A58F-12D257D5F486}.Release|x64.ActiveCfg = Release|x64
{7072A694-548F-4CAE-A58F-12D257D5F486}.Release|x64.Build.0 = Release|x64
{7072A694-548F-4CAE-A58F-12D257D5F486}.Release|x86.ActiveCfg = Release|x86
{7072A694-548F-4CAE-A58F-12D257D5F486}.Release|x86.Build.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<Solution>
<Configurations>
<Platform Name="Any CPU" />
<Platform Name="x64" />
<Platform Name="x86" />
</Configurations>
<Project Path="App/App.csproj">
<Platform Solution="*|x64" Project="x64" />
<Platform Solution="*|x86" Project="x86" />
</Project>
</Solution>
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26006.2
MinimumVisualStudioVersion = 10.0.40219.1
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<Solution>
<Configurations>
<Platform Name="Any CPU" />
<Platform Name="x64" />
<Platform Name="x86" />
</Configurations>
</Solution>
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26006.2
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "App", "App.csproj", "{7072A694-548F-4CAE-A58F-12D257D5F486}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|x64.ActiveCfg = Debug|x64
{7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|x64.Build.0 = Debug|x64
{7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|x86.ActiveCfg = Debug|x86
{7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|x86.Build.0 = Debug|x86
{7072A694-548F-4CAE-A58F-12D257D5F486}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7072A694-548F-4CAE-A58F-12D257D5F486}.Release|Any CPU.Build.0 = Release|Any CPU
{7072A694-548F-4CAE-A58F-12D257D5F486}.Release|x64.ActiveCfg = Release|x64
{7072A694-548F-4CAE-A58F-12D257D5F486}.Release|x64.Build.0 = Release|x64
{7072A694-548F-4CAE-A58F-12D257D5F486}.Release|x86.ActiveCfg = Release|x86
{7072A694-548F-4CAE-A58F-12D257D5F486}.Release|x86.Build.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<Solution>
<Configurations>
<Platform Name="Any CPU" />
<Platform Name="x64" />
<Platform Name="x86" />
</Configurations>
<Project Path="App.csproj">
<Platform Solution="*|x64" Project="x64" />
<Platform Solution="*|x86" Project="x86" />
</Project>
</Solution>
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26006.2
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "App", "App.csproj", "{7072A694-548F-4CAE-A58F-12D257D5F486}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{7B86CE74-F620-4B32-99FE-82D40F8D6BF2}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Lib", "Lib", "{EAB71280-AF32-4531-8703-43CDBA261AA3}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Lib", "src\Lib\Lib.csproj", "{84A45D44-B677-492D-A6DA-B3A71135AB8E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|x64.ActiveCfg = Debug|x64
{7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|x64.Build.0 = Debug|x64
{7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|x86.ActiveCfg = Debug|x86
{7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|x86.Build.0 = Debug|x86
{7072A694-548F-4CAE-A58F-12D257D5F486}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7072A694-548F-4CAE-A58F-12D257D5F486}.Release|Any CPU.Build.0 = Release|Any CPU
{7072A694-548F-4CAE-A58F-12D257D5F486}.Release|x64.ActiveCfg = Release|x64
{7072A694-548F-4CAE-A58F-12D257D5F486}.Release|x64.Build.0 = Release|x64
{7072A694-548F-4CAE-A58F-12D257D5F486}.Release|x86.ActiveCfg = Release|x86
{7072A694-548F-4CAE-A58F-12D257D5F486}.Release|x86.Build.0 = Release|x86
{84A45D44-B677-492D-A6DA-B3A71135AB8E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{84A45D44-B677-492D-A6DA-B3A71135AB8E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{84A45D44-B677-492D-A6DA-B3A71135AB8E}.Debug|x64.ActiveCfg = Debug|x64
{84A45D44-B677-492D-A6DA-B3A71135AB8E}.Debug|x64.Build.0 = Debug|x64
{84A45D44-B677-492D-A6DA-B3A71135AB8E}.Debug|x86.ActiveCfg = Debug|x86
{84A45D44-B677-492D-A6DA-B3A71135AB8E}.Debug|x86.Build.0 = Debug|x86
{84A45D44-B677-492D-A6DA-B3A71135AB8E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{84A45D44-B677-492D-A6DA-B3A71135AB8E}.Release|Any CPU.Build.0 = Release|Any CPU
{84A45D44-B677-492D-A6DA-B3A71135AB8E}.Release|x64.ActiveCfg = Release|x64
{84A45D44-B677-492D-A6DA-B3A71135AB8E}.Release|x64.Build.0 = Release|x64
{84A45D44-B677-492D-A6DA-B3A71135AB8E}.Release|x86.ActiveCfg = Release|x86
{84A45D44-B677-492D-A6DA-B3A71135AB8E}.Release|x86.Build.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{EAB71280-AF32-4531-8703-43CDBA261AA3} = {7B86CE74-F620-4B32-99FE-82D40F8D6BF2}
{84A45D44-B677-492D-A6DA-B3A71135AB8E} = {EAB71280-AF32-4531-8703-43CDBA261AA3}
EndGlobalSection
EndGlobal
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<Solution>
<Configurations>
<Platform Name="Any CPU" />
<Platform Name="x64" />
<Platform Name="x86" />
</Configurations>
<Folder Name="/src/" />
<Folder Name="/src/Lib/">
<Project Path="src/Lib/Lib.csproj">
<Platform Solution="*|x64" Project="x64" />
<Platform Solution="*|x86" Project="x86" />
</Project>
</Folder>
<Project Path="App.csproj">
<Platform Solution="*|x64" Project="x64" />
<Platform Solution="*|x86" Project="x86" />
</Project>
</Solution>
Loading
Loading