Skip to content

Commit

Permalink
Handle packages.config restore scenario where multiple projects with …
Browse files Browse the repository at this point in the history
…the same name exist in the same solution (#5825) (#5832)
  • Loading branch information
nkolev92 authored May 31, 2024
1 parent a6b8c73 commit 69ce91e
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,15 @@ private async Task<Dictionary<string, RestoreAuditProperties>> GetRestoreAuditPr
EnableAudit = nugetAudit,
AuditLevel = auditLevel,
};
restoreAuditProperties.Add(nuGetProjectName, auditProperties);
// Here be dragons.
// The key here, nuGetProjectName, needs to match the key in the dictionary in GetPackagesReferencesDictionaryAsync and all the constructors of PackageRestoreData.
// This is because the key is used to match the project name to the package references.
// If the key is not the same, the package references will not be matched to the project name and the audit properties will not be considered.
// The side-effects is that if 2 projects have the exact same name, they will share the same audit properties.
// The chances of anyone configuring msbuild audit properties differently within the same solution are low, but still a possibility nonetheless.
// Given that the project names are used in a lot of places, changing it in a servicing release is a really large risk, so this will have the limitation of sharing audit properties.
// TODO: https://github.com/NuGet/Home/issues/13466
restoreAuditProperties[nuGetProjectName] = auditProperties;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using System.Threading;
using System.Threading.Tasks;
using FluentAssertions;
using NuGet.Configuration;
using NuGet.PackageManagement;
using NuGet.Packaging.Core;
using NuGet.Protocol.Core.Types;
Expand Down Expand Up @@ -389,6 +390,56 @@ await nuGetPackageManager.InstallPackageAsync(projectB, jQueryValidation,
}
}

[Fact]
public async Task RestoreMissingPackagesInSolutionAsync_WithProjectsSharingSameName_Succeeds()
{
// Arrange
using var simpleTestPathContext = new SimpleTestPathContext();
using var testSolutionManager = new TestSolutionManager(simpleTestPathContext);

var projectA = testSolutionManager.AddNewMSBuildProject("Project");
var projectBPath = Path.Combine(testSolutionManager.SolutionDirectory, "subfolder", "Project");
var projectB = testSolutionManager.AddNewMSBuildProject("Project", projectPath: projectBPath, validateExistingProject: false);

var packageA = new SimpleTestPackageContext("a", "1.0.0");
await SimpleTestPackageUtility.CreateFolderFeedV3Async(simpleTestPathContext.PackageSource, packageA);

var sourceRepositoryProvider = TestSourceRepositoryUtility.CreateSourceRepositoryProvider(new PackageSource(simpleTestPathContext.PackageSource));
var testSettings = NullSettings.Instance;
var resolutionContext = new ResolutionContext();

var nuGetPackageManager = new NuGetPackageManager(
sourceRepositoryProvider,
testSettings,
testSolutionManager,
new TestDeleteOnRestartManager());

await nuGetPackageManager.InstallPackageAsync(projectA, packageA.Identity,
resolutionContext, new TestNuGetProjectContext(), sourceRepositoryProvider.GetRepositories().First(), null, CancellationToken.None);
await nuGetPackageManager.InstallPackageAsync(projectB, packageA.Identity,
resolutionContext, new TestNuGetProjectContext(), sourceRepositoryProvider.GetRepositories().First(), null, CancellationToken.None);

var packageRestoreManager = new PackageRestoreManager(
sourceRepositoryProvider,
testSettings,
testSolutionManager);

// pre-conditions
nuGetPackageManager.PackageExistsInPackagesFolder(packageA.Identity).Should().BeTrue();
TestFileSystemUtility.DeleteRandomTestFolder(Path.Combine(testSolutionManager.SolutionDirectory, "packages"));
nuGetPackageManager.PackageExistsInPackagesFolder((packageA.Identity)).Should().BeFalse();

// Act
PackageRestoreResult result = await packageRestoreManager.RestoreMissingPackagesInSolutionAsync(testSolutionManager.SolutionDirectory,
new TestNuGetProjectContext(),
new TestLogger(),
CancellationToken.None);

// Assert
result.Should().NotBeNull();
nuGetPackageManager.PackageExistsInPackagesFolder((packageA.Identity)).Should().BeTrue();
}

private static DownloadResourceResult GetDownloadResult(string source, FileInfo packageFileInfo)
{
return new DownloadResourceResult(packageFileInfo.OpenRead(), source);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,24 +79,27 @@ public TestSolutionManager(string solutionDirectory)
SolutionDirectory = solutionDirectory;
}

public MSBuildNuGetProject AddNewMSBuildProject(string projectName = null, NuGetFramework projectTargetFramework = null, string packagesConfigName = null)
public MSBuildNuGetProject AddNewMSBuildProject(string projectName = null, NuGetFramework projectTargetFramework = null, string projectPath = null, bool validateExistingProject = true)
{
var existingProject = Task.Run(async () => await GetNuGetProjectAsync(projectName));
existingProject.Wait();
if (existingProject.IsCompleted && existingProject.Result != null)
if (validateExistingProject)
{
throw new ArgumentException("Project with " + projectName + " already exists");
var existingProject = Task.Run(async () => await GetNuGetProjectAsync(projectName));
existingProject.Wait();
if (existingProject.IsCompleted && existingProject.Result != null)
{
throw new ArgumentException("Project with " + projectName + " already exists");
}
}

var packagesFolder = PackagesFolder;
projectName = string.IsNullOrEmpty(projectName) ? Guid.NewGuid().ToString() : projectName;
var projectFullPath = Path.Combine(SolutionDirectory, projectName);
var projectFullPath = projectPath ?? Path.Combine(SolutionDirectory, projectName);
Directory.CreateDirectory(projectFullPath);

projectTargetFramework = projectTargetFramework ?? NuGetFramework.Parse("net45");

var msBuildNuGetProjectSystem = new TestMSBuildNuGetProjectSystem(projectTargetFramework, new TestNuGetProjectContext(),
projectFullPath, projectName);
var msBuildNuGetProject = new MSBuildNuGetProject(msBuildNuGetProjectSystem, packagesFolder, projectFullPath);
var msBuildNuGetProject = new MSBuildNuGetProject(msBuildNuGetProjectSystem, PackagesFolder, projectFullPath);
NuGetProjects.Add(msBuildNuGetProject);
return msBuildNuGetProject;
}
Expand Down

0 comments on commit 69ce91e

Please sign in to comment.