Skip to content
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

sln-remove: Support for slnx #45160

Merged
merged 12 commits into from
Jan 8, 2025
Next Next commit
sln-remove: Support for slnx
  • Loading branch information
edvilme committed Jan 6, 2025
commit b9d21348b088636e783a768dd91d82b6376da816
52 changes: 30 additions & 22 deletions src/Cli/dotnet/commands/dotnet-sln/remove/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,56 +4,64 @@
using System.CommandLine;
using Microsoft.DotNet.Cli;
using Microsoft.DotNet.Cli.Sln.Internal;
edvilme marked this conversation as resolved.
Show resolved Hide resolved
using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.Tools.Common;
using Microsoft.VisualStudio.SolutionPersistence;
using Microsoft.VisualStudio.SolutionPersistence.Model;

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

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);
}

var baseDirectory = PathUtility.EnsureTrailingSlash(slnFile.BaseDirectory);
var relativeProjectPaths = _arguments.Select(p =>
IEnumerable<string> fullProjectPaths = _projects.Select(project =>
{
var fullPath = Path.GetFullPath(p);
return Path.GetRelativePath(
baseDirectory,
Directory.Exists(fullPath) ?
MsbuildProject.GetProjectFileFromDirectory(fullPath).FullName :
fullPath
);
var fullPath = Path.GetFullPath(project);
return Directory.Exists(fullPath) ? MsbuildProject.GetProjectFileFromDirectory(fullPath).FullName : fullPath;
});

bool slnChanged = false;
foreach (var path in relativeProjectPaths)
try
{
slnChanged |= slnFile.RemoveProject(path);
RemoveProjectsAsync(solutionFileFullPath, fullProjectPaths, CancellationToken.None).Wait();
return 0;
}
catch (Exception ex)
{
throw new GracefulException(ex.Message, ex);
}
}

slnFile.RemoveEmptyConfigurationSections();

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

if (slnChanged)
foreach (var project in projectPaths)
{
slnFile.Write();
SolutionProjectModel projectModel = solution.FindProject(project);
solution.RemoveProject(projectModel);
}

return 0;
await serializer.SaveAsync(solutionFileFullPath, solution, cancellationToken);
}
}
}