Skip to content

Commit 22bf03f

Browse files
CopilotmarcpopMSFT
andcommitted
Fix duplicate solution folder when adding multiple projects from same directory
- Added check in GenerateIntermediateSolutionFoldersForProjectPath to reuse existing solution folder instead of creating duplicate - Added test WhenMultipleProjectsFromSameDirectoryAreAddedSolutionFolderIsNotDuplicated to verify the fix - All existing tests pass (214 passed, 2 skipped) Co-authored-by: marcpopMSFT <[email protected]>
1 parent 37e3fd6 commit 22bf03f

File tree

2 files changed

+50
-3
lines changed

2 files changed

+50
-3
lines changed

src/Cli/dotnet/Commands/Solution/Add/SolutionAddCommand.cs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -102,9 +102,16 @@ public override int Execute()
102102
relativeSolutionFolderPath = _solutionFolderPath;
103103
}
104104

105-
return string.IsNullOrEmpty(relativeSolutionFolderPath)
106-
? null
107-
: solution.AddFolder(GetSolutionFolderPathWithForwardSlashes(relativeSolutionFolderPath));
105+
if (string.IsNullOrEmpty(relativeSolutionFolderPath))
106+
{
107+
return null;
108+
}
109+
110+
// Check if a solution folder with this path already exists
111+
var solutionFolderPath = GetSolutionFolderPathWithForwardSlashes(relativeSolutionFolderPath);
112+
var existingFolder = solution.SolutionFolders.FirstOrDefault(f => f.Path == solutionFolderPath);
113+
114+
return existingFolder ?? solution.AddFolder(solutionFolderPath);
108115
}
109116

110117
private async Task AddProjectsToSolutionAsync(IEnumerable<string> projectPaths, CancellationToken cancellationToken)

test/dotnet.Tests/CommandTests/Solution/Add/GivenDotnetSlnAdd.cs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,46 @@ public void WhenDirectoryContainsMultipleProjectsItCancelsWholeOperation(string
409409
.Should().BeVisuallyEquivalentTo(contentBefore);
410410
}
411411

412+
[Theory]
413+
[InlineData("sln", ".sln")]
414+
[InlineData("solution", ".sln")]
415+
[InlineData("sln", ".slnx")]
416+
[InlineData("solution", ".slnx")]
417+
public async Task WhenMultipleProjectsFromSameDirectoryAreAddedSolutionFolderIsNotDuplicated(string solutionCommand, string solutionExtension)
418+
{
419+
var projectDirectory = _testAssetsManager
420+
.CopyTestAsset("TestAppWithSlnAndCsprojFiles", identifier: $"GivenDotnetSlnAdd-{solutionCommand}{solutionExtension}")
421+
.WithSource()
422+
.Path;
423+
424+
var firstProject = Path.Combine("Multiple", "First.csproj");
425+
var secondProject = Path.Combine("Multiple", "Second.csproj");
426+
var cmd = new DotnetCommand(Log)
427+
.WithWorkingDirectory(projectDirectory)
428+
.Execute(solutionCommand, $"App{solutionExtension}", "add", firstProject, secondProject);
429+
cmd.Should().Pass();
430+
431+
ISolutionSerializer serializer = SolutionSerializers.GetSerializerByMoniker(Path.Combine(projectDirectory, $"App{solutionExtension}"));
432+
SolutionModel solution = await serializer.OpenAsync(Path.Combine(projectDirectory, $"App{solutionExtension}"), CancellationToken.None);
433+
434+
// The solution already has App project, plus we added First and Second = 3 total
435+
var projectsInSolution = solution.SolutionProjects.ToList();
436+
projectsInSolution.Count.Should().Be(3);
437+
projectsInSolution.Should().Contain(p => p.FilePath.Contains("First.csproj"));
438+
projectsInSolution.Should().Contain(p => p.FilePath.Contains("Second.csproj"));
439+
440+
// Should only have one solution folder for "Multiple", not two
441+
var solutionFolders = solution.SolutionFolders.ToList();
442+
solutionFolders.Count.Should().Be(1);
443+
solutionFolders.Single().Path.Should().Contain("Multiple");
444+
445+
// Both new projects should be in the same solution folder
446+
var solutionFolder = solutionFolders.Single();
447+
var multipleProjects = projectsInSolution.Where(p => p.FilePath.Contains("Multiple")).ToList();
448+
multipleProjects.Count.Should().Be(2);
449+
multipleProjects.All(p => p.Parent?.Id == solutionFolder.Id).Should().BeTrue();
450+
}
451+
412452
[Theory]
413453
[InlineData("sln", ".sln")]
414454
[InlineData("solution", ".sln")]

0 commit comments

Comments
 (0)