Skip to content

Commit

Permalink
Add RID specific packages to dotnet nuget why (#6154)
Browse files Browse the repository at this point in the history
  • Loading branch information
Nigusu-Allehu authored Nov 22, 2024
1 parent 46b470c commit 3332ab2
Show file tree
Hide file tree
Showing 7 changed files with 2,105 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,28 +31,37 @@ internal static class DependencyGraphFinder
var dependencyGraphPerFramework = new Dictionary<string, List<DependencyNode>?>(assetsFile.Targets.Count);
bool doesProjectHaveDependencyOnPackage = false;

// add null to the list of runtime identifiers to account for projects that do not have a runtime identifier
var runtimeIdentifiers = assetsFile.PackageSpec.RuntimeGraph.Runtimes.Keys
.Append(null)
.ToList();
// get all top-level package and project references for the project, categorized by target framework alias
Dictionary<string, List<string>> topLevelReferencesByFramework = GetTopLevelPackageAndProjectReferences(assetsFile, userInputFrameworks);

if (topLevelReferencesByFramework.Count > 0)
{
foreach (var (targetFrameworkAlias, topLevelReferences) in topLevelReferencesByFramework)
{
LockFileTarget? target = assetsFile.GetTarget(targetFrameworkAlias, runtimeIdentifier: null);

// get all package libraries for the framework
IList<LockFileTargetLibrary>? packageLibraries = target?.Libraries;

// if the project has a dependency on the target package, get the dependency graph
if (packageLibraries?.Any(l => l?.Name?.Equals(targetPackage, StringComparison.OrdinalIgnoreCase) == true) == true)
{
doesProjectHaveDependencyOnPackage = true;
dependencyGraphPerFramework.Add(targetFrameworkAlias,
GetDependencyGraphForTargetPerFramework(topLevelReferences, packageLibraries, targetPackage));
}
else
foreach (var runtimeIdentifier in runtimeIdentifiers)
{
dependencyGraphPerFramework.Add(targetFrameworkAlias, null);
var targetFrameworkDisplayName = runtimeIdentifier == null ? targetFrameworkAlias : $"{targetFrameworkAlias}/{runtimeIdentifier}";

LockFileTarget target = assetsFile.GetTarget(targetFrameworkAlias, runtimeIdentifier: runtimeIdentifier);

// get all package libraries for the framework
IList<LockFileTargetLibrary>? packageLibraries = target.Libraries;

// if the project has a dependency on the target package, get the dependency graph
if (packageLibraries?.Any(l => l?.Name?.Equals(targetPackage, StringComparison.OrdinalIgnoreCase) == true) == true)
{
doesProjectHaveDependencyOnPackage = true;
dependencyGraphPerFramework.Add(targetFrameworkDisplayName,
GetDependencyGraphForTargetPerFramework(topLevelReferences, packageLibraries, targetPackage));
}
else
{
dependencyGraphPerFramework.Add(targetFrameworkDisplayName, null);
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,121 @@ public void DifferentCaseUsedForTargetPackageId_MatchesAreCaseInsensitive_AllPat
Assert.Contains(dependencyGraphs["net472"].First(dep => dep.Id == "DotnetNuGetWhyPackage").Children, dep => (dep.Id == "System.Text.Json") && (dep.Version == "8.0.0"));
}

[Fact]
public void GetAllDependencyGraphsForTarget_WithWinX64Runtime_FindsRIDSpecificPackages()
{
// Arrange
var lockFileFormat = new LockFileFormat();
var lockFileContent = ProtocolUtility.GetResource("NuGet.CommandLine.Xplat.Tests.compiler.resources.Test.SampleProject2.project.assets.json", GetType());
var assetsFile = lockFileFormat.Parse(lockFileContent, "In Memory");

if (XunitAttributeUtility.CurrentPlatform == Platform.Linux || XunitAttributeUtility.CurrentPlatform == Platform.Darwin)
{
ConvertRelevantWindowsPathsToUnix(assetsFile);
}

string targetPackage = "system.private.uri";
var frameworks = new List<string>();

// Act
var dependencyGraphs = DependencyGraphFinder.GetAllDependencyGraphsForTarget(assetsFile, targetPackage, frameworks);

// Assert
Assert.Contains(dependencyGraphs["net9.0/win-x64"], dep => (dep.Id == "System.AppContext") && (dep.Version == "4.3.0"));
Assert.Contains(dependencyGraphs["net9.0/win-x64"].First().Children, dep => (dep.Id == "System.Runtime") && (dep.Version == "4.3.0"));
Assert.Contains(dependencyGraphs["net9.0/win-x64"].First().Children.First().Children, dep => (dep.Id == "runtime.any.System.Runtime") && (dep.Version == "4.3.0"));
Assert.Contains(dependencyGraphs["net9.0/win-x64"].First().Children.First().Children.First().Children, dep => (dep.Id == "System.Private.Uri") && (dep.Version == "4.3.0"));
}

[Theory]
[InlineData("system.private.uri")]
[InlineData("system.PRIVATE.uri")]
[InlineData("system.private.URI")]
public void GetAllDependencyGraphsForTarget_TwoRidSpecificVersionsVariousCasings_FindsRIDSpecificPackages(string package)
{
// Arrange
var lockFileFormat = new LockFileFormat();
var lockFileContent = ProtocolUtility.GetResource("NuGet.CommandLine.Xplat.Tests.compiler.resources.Test.TwoDifferentVersions.project.assets.json", GetType());
var assetsFile = lockFileFormat.Parse(lockFileContent, "In Memory");

if (XunitAttributeUtility.CurrentPlatform == Platform.Linux || XunitAttributeUtility.CurrentPlatform == Platform.Darwin)
{
ConvertRelevantWindowsPathsToUnix(assetsFile);
}

var frameworks = new List<string>();

// Act
var dependencyGraphs = DependencyGraphFinder.GetAllDependencyGraphsForTarget(assetsFile, package, frameworks);

// Assert
Assert.Contains(dependencyGraphs["net9.0/win-x64"], dep => (dep.Id == "System.Private.Uri") && (dep.Version == "4.3.0"));
Assert.Contains(dependencyGraphs["net9.0"], dep => (dep.Id == "System.Private.Uri") && (dep.Version == "4.3.2"));
}

[Fact]
public void GetAllDependencyGraphsForTarget_MultiTfmMultiRid_FindsRIDSpecificPackages()
{
// Arrange
var lockFileFormat = new LockFileFormat();
var lockFileContent = ProtocolUtility.GetResource("NuGet.CommandLine.Xplat.Tests.compiler.resources.Test.MultiTfmMultiRidProject.project.assets.json", GetType());
var assetsFile = lockFileFormat.Parse(lockFileContent, "In Memory");

if (XunitAttributeUtility.CurrentPlatform == Platform.Linux || XunitAttributeUtility.CurrentPlatform == Platform.Darwin)
{
ConvertRelevantWindowsPathsToUnix(assetsFile);
}

string targetPackage = "system.private.uri";
var frameworks = new List<string>();

// Act
var dependencyGraphs = DependencyGraphFinder.GetAllDependencyGraphsForTarget(assetsFile, targetPackage, frameworks);

// Assert
Assert.Contains(dependencyGraphs["net9.0/win-x64"], dep => (dep.Id == "System.AppContext") && (dep.Version == "4.3.0"));
Assert.Contains(dependencyGraphs["net9.0/win-x64"].First().Children, dep => (dep.Id == "System.Runtime") && (dep.Version == "4.3.0"));
Assert.Contains(dependencyGraphs["net9.0/win-x64"].First().Children.First().Children, dep => (dep.Id == "runtime.any.System.Runtime") && (dep.Version == "4.3.0"));
Assert.Contains(dependencyGraphs["net9.0/win-x64"].First().Children.First().Children.First().Children, dep => (dep.Id == "System.Private.Uri") && (dep.Version == "4.3.0"));
Assert.Contains(dependencyGraphs["net8.0/win-x64"], dep => (dep.Id == "System.AppContext") && (dep.Version == "4.3.0"));
Assert.Contains(dependencyGraphs["net8.0/win-x64"].First().Children, dep => (dep.Id == "System.Runtime") && (dep.Version == "4.3.0"));
Assert.Contains(dependencyGraphs["net8.0/win-x64"].First().Children.First().Children, dep => (dep.Id == "runtime.any.System.Runtime") && (dep.Version == "4.3.0"));
Assert.Contains(dependencyGraphs["net8.0/win-x64"].First().Children.First().Children.First().Children, dep => (dep.Id == "System.Private.Uri") && (dep.Version == "4.3.0"));
Assert.Contains(dependencyGraphs["net9.0/linux-x64"], dep => (dep.Id == "System.AppContext") && (dep.Version == "4.3.0"));
Assert.Contains(dependencyGraphs["net9.0/linux-x64"].First().Children, dep => (dep.Id == "System.Runtime") && (dep.Version == "4.3.0"));
Assert.Contains(dependencyGraphs["net9.0/linux-x64"].First().Children.First().Children, dep => (dep.Id == "runtime.any.System.Runtime") && (dep.Version == "4.3.0"));
Assert.Contains(dependencyGraphs["net9.0/linux-x64"].First().Children.First().Children.First().Children, dep => (dep.Id == "System.Private.Uri") && (dep.Version == "4.3.0"));
Assert.Contains(dependencyGraphs["net8.0/linux-x64"], dep => (dep.Id == "System.AppContext") && (dep.Version == "4.3.0"));
Assert.Contains(dependencyGraphs["net8.0/linux-x64"].First().Children, dep => (dep.Id == "System.Runtime") && (dep.Version == "4.3.0"));
Assert.Contains(dependencyGraphs["net8.0/linux-x64"].First().Children.First().Children, dep => (dep.Id == "runtime.any.System.Runtime") && (dep.Version == "4.3.0"));
Assert.Contains(dependencyGraphs["net8.0/linux-x64"].First().Children.First().Children.First().Children, dep => (dep.Id == "System.Private.Uri") && (dep.Version == "4.3.0"));
}

[Fact]
public void GetAllDependencyGraphsForTarget_NoRidSpecificPackages_FindsRIDlessPackages()
{
// Arrange
var lockFileFormat = new LockFileFormat();
var lockFileContent = ProtocolUtility.GetResource("NuGet.CommandLine.Xplat.Tests.compiler.resources.Test.NoPackageRidSpecificPackageProject.project.assets.json", GetType());
var assetsFile = lockFileFormat.Parse(lockFileContent, "In Memory");

if (XunitAttributeUtility.CurrentPlatform == Platform.Linux || XunitAttributeUtility.CurrentPlatform == Platform.Darwin)
{
ConvertRelevantWindowsPathsToUnix(assetsFile);
}

string targetPackage = "System.Runtime";
var frameworks = new List<string>();

// Act
var dependencyGraphs = DependencyGraphFinder.GetAllDependencyGraphsForTarget(assetsFile, targetPackage, frameworks);

// Assert
Assert.Null(dependencyGraphs["net9.0/win-x64"]);
Assert.Contains(dependencyGraphs["net9.0"], dep => (dep.Id == "System.AppContext") && (dep.Version == "4.3.0"));
Assert.Contains(dependencyGraphs["net9.0"].First().Children, dep => (dep.Id == "System.Runtime") && (dep.Version == "4.3.0"));
}

private static void ConvertRelevantWindowsPathsToUnix(LockFile assetsFile)
{
assetsFile.PackageSpec.FilePath = ConvertWindowsPathToUnix(assetsFile.PackageSpec.FilePath);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@
<PackageReference Include="System.CommandLine" />
</ItemGroup>

<ItemGroup>
<Folder Include="compiler\resources\" />
</ItemGroup>

<ItemGroup>
<EmbeddedResource Include="compiler\resources\DNW.Test.SampleProject1.project.assets.json" />
<EmbeddedResource Include="compiler\resources\Test.SampleProject2.project.assets.json" />
<EmbeddedResource Include="compiler\resources\Test.TwoDifferentVersions.project.assets.json" />
<EmbeddedResource Include="compiler\resources\Test.MultiTfmMultiRidProject.project.assets.json" />
<EmbeddedResource Include="compiler\resources\Test.NoPackageRidSpecificPackageProject.project.assets.json" />
</ItemGroup>
</Project>
Loading

0 comments on commit 3332ab2

Please sign in to comment.