|
4 | 4 | using System.CommandLine;
|
5 | 5 | using Microsoft.DotNet.Cli;
|
6 | 6 | using Microsoft.DotNet.Cli.Sln.Internal;
|
| 7 | +using Microsoft.DotNet.Cli.Utils; |
7 | 8 | using Microsoft.DotNet.Tools.Common;
|
| 9 | +using Microsoft.VisualStudio.SolutionPersistence; |
| 10 | +using Microsoft.VisualStudio.SolutionPersistence.Model; |
8 | 11 |
|
9 | 12 | namespace Microsoft.DotNet.Tools.Sln.Remove
|
10 | 13 | {
|
11 | 14 | internal class RemoveProjectFromSolutionCommand : CommandBase
|
12 | 15 | {
|
13 | 16 | private readonly string _fileOrDirectory;
|
14 |
| - private readonly IReadOnlyCollection<string> _arguments; |
| 17 | + private readonly IReadOnlyCollection<string> _projects; |
15 | 18 |
|
16 | 19 | public RemoveProjectFromSolutionCommand(ParseResult parseResult) : base(parseResult)
|
17 | 20 | {
|
18 | 21 | _fileOrDirectory = parseResult.GetValue(SlnCommandParser.SlnArgument);
|
19 | 22 |
|
20 |
| - _arguments = (parseResult.GetValue(SlnRemoveParser.ProjectPathArgument) ?? Array.Empty<string>()).ToList().AsReadOnly(); |
| 23 | + _projects = (parseResult.GetValue(SlnRemoveParser.ProjectPathArgument) ?? Array.Empty<string>()).ToList().AsReadOnly(); |
21 | 24 |
|
22 |
| - SlnArgumentValidator.ParseAndValidateArguments(_fileOrDirectory, _arguments, SlnArgumentValidator.CommandType.Remove); |
| 25 | + SlnArgumentValidator.ParseAndValidateArguments(_fileOrDirectory, _projects, SlnArgumentValidator.CommandType.Remove); |
23 | 26 | }
|
24 | 27 |
|
25 | 28 | public override int Execute()
|
26 | 29 | {
|
27 |
| - SlnFile slnFile = SlnFileFactory.CreateFromFileOrDirectory(_fileOrDirectory); |
| 30 | + string solutionFileFullPath = SlnCommandParser.GetSlnFileFullPath(_fileOrDirectory); |
| 31 | + if (_projects.Count == 0) |
| 32 | + { |
| 33 | + throw new GracefulException(CommonLocalizableStrings.SpecifyAtLeastOneProjectToRemove); |
| 34 | + } |
28 | 35 |
|
29 |
| - var baseDirectory = PathUtility.EnsureTrailingSlash(slnFile.BaseDirectory); |
30 |
| - var relativeProjectPaths = _arguments.Select(p => |
| 36 | + IEnumerable<string> fullProjectPaths = _projects.Select(project => |
31 | 37 | {
|
32 |
| - var fullPath = Path.GetFullPath(p); |
33 |
| - return Path.GetRelativePath( |
34 |
| - baseDirectory, |
35 |
| - Directory.Exists(fullPath) ? |
36 |
| - MsbuildProject.GetProjectFileFromDirectory(fullPath).FullName : |
37 |
| - fullPath |
38 |
| - ); |
| 38 | + var fullPath = Path.GetFullPath(project); |
| 39 | + return Directory.Exists(fullPath) ? MsbuildProject.GetProjectFileFromDirectory(fullPath).FullName : fullPath; |
39 | 40 | });
|
40 | 41 |
|
41 |
| - bool slnChanged = false; |
42 |
| - foreach (var path in relativeProjectPaths) |
| 42 | + try |
43 | 43 | {
|
44 |
| - slnChanged |= slnFile.RemoveProject(path); |
| 44 | + RemoveProjectsAsync(solutionFileFullPath, fullProjectPaths, CancellationToken.None).Wait(); |
| 45 | + return 0; |
45 | 46 | }
|
| 47 | + catch (Exception ex) |
| 48 | + { |
| 49 | + throw new GracefulException(ex.Message, ex); |
| 50 | + } |
| 51 | + } |
46 | 52 |
|
47 |
| - slnFile.RemoveEmptyConfigurationSections(); |
48 |
| - |
49 |
| - slnFile.RemoveEmptySolutionFolders(); |
| 53 | + private async Task RemoveProjectsAsync(string solutionFileFullPath, IEnumerable<string> projectPaths, CancellationToken cancellationToken) |
| 54 | + { |
| 55 | + ISolutionSerializer serializer = SlnCommandParser.GetSolutionSerializer(solutionFileFullPath); |
| 56 | + SolutionModel solution = await serializer.OpenAsync(solutionFileFullPath, cancellationToken); |
50 | 57 |
|
51 |
| - if (slnChanged) |
| 58 | + foreach (var project in projectPaths) |
52 | 59 | {
|
53 |
| - slnFile.Write(); |
| 60 | + SolutionProjectModel projectModel = solution.FindProject(project); |
| 61 | + solution.RemoveProject(projectModel); |
54 | 62 | }
|
55 | 63 |
|
56 |
| - return 0; |
| 64 | + await serializer.SaveAsync(solutionFileFullPath, solution, cancellationToken); |
57 | 65 | }
|
58 | 66 | }
|
59 | 67 | }
|
0 commit comments