diff --git a/src/NuGet.Core/NuGet.CommandLine.XPlat/Commands/WhyCommand/DependencyGraphFinder.cs b/src/NuGet.Core/NuGet.CommandLine.XPlat/Commands/WhyCommand/DependencyGraphFinder.cs new file mode 100644 index 00000000000..ce0a93c4d69 --- /dev/null +++ b/src/NuGet.Core/NuGet.CommandLine.XPlat/Commands/WhyCommand/DependencyGraphFinder.cs @@ -0,0 +1,300 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using NuGet.ProjectModel; + +namespace NuGet.CommandLine.XPlat +{ + internal static class DependencyGraphFinder + { + /// + /// Finds all dependency graphs for a given project. + /// + /// Assets file for the project. + /// The package we want the dependency paths for. + /// List of target framework aliases. + /// + /// Dictionary mapping target framework aliases to their respective dependency graphs. + /// Returns null if the project does not have a dependency on the target package. + /// + public static Dictionary?>? GetAllDependencyGraphsForTarget( + LockFile assetsFile, + string targetPackage, + List userInputFrameworks) + { + var dependencyGraphPerFramework = new Dictionary?>(assetsFile.Targets.Count); + bool doesProjectHaveDependencyOnPackage = false; + + // get all top-level package and project references for the project, categorized by target framework alias + Dictionary> 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? 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 + { + dependencyGraphPerFramework.Add(targetFrameworkAlias, null); + } + } + } + + return doesProjectHaveDependencyOnPackage + ? dependencyGraphPerFramework + : null; + } + + /// + /// Finds all dependency paths from the top-level packages to the target package for a given framework. + /// + /// All top-level package and project references for the framework. + /// All package libraries for the framework. + /// The package we want the dependency paths for. + /// + /// List of all top-level package nodes in the dependency graph. + /// + private static List? GetDependencyGraphForTargetPerFramework( + List topLevelReferences, + IList packageLibraries, + string targetPackage) + { + List? dependencyGraph = null; + + // hashset tracking every package node that we've traversed + var visited = new HashSet(StringComparer.OrdinalIgnoreCase); + // dictionary tracking all package nodes that have been added to the graph, mapped to their DependencyNode objects + var dependencyNodes = new Dictionary(StringComparer.OrdinalIgnoreCase); + // dictionary mapping all packageIds to their resolved version + Dictionary versions = GetAllResolvedVersions(packageLibraries); + + foreach (var topLevelReference in topLevelReferences) + { + // use depth-first search to find dependency paths from the top-level package to the target package + DependencyNode? topLevelNode = FindDependencyPathForTarget(topLevelReference, packageLibraries, visited, dependencyNodes, versions, targetPackage); + + if (topLevelNode != null) + { + dependencyGraph ??= []; + dependencyGraph.Add(topLevelNode); + } + } + + return dependencyGraph; + } + + /// + /// Traverses the dependency graph for a given top-level package, looking for a path to the target package. + /// + /// Top-level package. + /// All package libraries for a given framework. + /// HashSet tracking every package node that we've traversed. + /// Dictionary tracking all packageIds that were added to the graph, mapped to their DependencyNode objects. + /// Dictionary mapping packageIds to their resolved versions. + /// The package we want the dependency paths for. + /// + /// The top-level package node in the dependency graph (if a path was found), or null (if no path was found). + /// + private static DependencyNode? FindDependencyPathForTarget( + string topLevelPackage, + IList packageLibraries, + HashSet visited, + Dictionary dependencyNodes, + Dictionary versions, + string targetPackage) + { + var stack = new Stack(); + stack.Push(new StackDependencyData(topLevelPackage, null)); + + while (stack.Count > 0) + { + var currentPackageData = stack.Pop(); + var currentPackageId = currentPackageData.Id; + + // if we reach the target node, or if we've already traversed this node and found dependency paths, add it to the graph + if (currentPackageId.Equals(targetPackage, StringComparison.OrdinalIgnoreCase) + || dependencyNodes.ContainsKey(currentPackageId)) + { + AddToGraph(currentPackageData, dependencyNodes, versions); + continue; + } + + // if we have already traversed this node's children, continue + if (visited.Contains(currentPackageId)) + { + continue; + } + + visited.Add(currentPackageId); + + // get all dependencies for the current package + var dependencies = packageLibraries?.FirstOrDefault(i => i?.Name?.Equals(currentPackageId, StringComparison.OrdinalIgnoreCase) == true)?.Dependencies; + + if (dependencies?.Count > 0) + { + // push all the dependencies onto the stack + foreach (var dependency in dependencies) + { + stack.Push(new StackDependencyData(dependency.Id, currentPackageData)); + } + } + } + + return dependencyNodes.ContainsKey(topLevelPackage) + ? dependencyNodes[topLevelPackage] + : null; + } + + /// + /// Adds a dependency path to the graph, starting from the target package and traversing up to the top-level package. + /// + /// Target node data. This stores parent references, so it can be used to construct the dependency graph + /// up to the top-level package. + /// Dictionary tracking all packageIds that were added to the graph, mapped to their DependencyNode objects. + /// Dictionary mapping packageIds to their resolved versions. + private static void AddToGraph( + StackDependencyData targetPackageData, + Dictionary dependencyNodes, + Dictionary versions) + { + // first, we traverse the target's parents, listing the packages in the path from the target to the top-level package + var dependencyPath = new List { targetPackageData.Id }; + StackDependencyData? current = targetPackageData.Parent; + + while (current != null) + { + dependencyPath.Add(current.Id); + current = current.Parent; + } + + // then, we traverse this list from the target package to the top-level package, initializing/updating their dependency nodes as needed + for (int i = 0; i < dependencyPath.Count; i++) + { + string currentPackageId = dependencyPath[i]; + + if (!dependencyNodes.ContainsKey(currentPackageId)) + { + dependencyNodes.Add(currentPackageId, new DependencyNode(currentPackageId, versions[currentPackageId])); + } + + if (i > 0) + { + var childNode = dependencyNodes[dependencyPath[i - 1]]; + dependencyNodes[currentPackageId].Children.Add(childNode); + } + } + } + + /// + /// Get all top-level package and project references for the given project. + /// + /// Assets file for the project. + /// List of target framework aliases. + /// + /// Dictionary mapping the project's target framework aliases to their respective top-level package and project references. + /// + private static Dictionary> GetTopLevelPackageAndProjectReferences( + LockFile assetsFile, + List userInputFrameworks) + { + var topLevelReferences = new Dictionary>(); + + var targetAliases = assetsFile.PackageSpec.RestoreMetadata.OriginalTargetFrameworks; + + // filter the targets to the set of targets that the user has specified + if (userInputFrameworks?.Count > 0) + { + targetAliases = targetAliases.Where(f => userInputFrameworks.Contains(f)).ToList(); + } + + // we need to match top-level project references to their target library entries using their paths, + // so we will store all project reference paths in a dictionary here + var projectLibraries = assetsFile.Libraries.Where(l => l.Type == "project"); + var projectLibraryPathToName = new Dictionary(projectLibraries.Count()); + var projectDirectoryPath = Path.GetDirectoryName(assetsFile.PackageSpec.FilePath); + + if (projectDirectoryPath != null) + { + foreach (var library in projectLibraries) + { + projectLibraryPathToName.Add(Path.GetFullPath(library.Path, projectDirectoryPath), library.Name); + } + } + + // get all top-level references for each target alias + foreach (string targetAlias in targetAliases) + { + topLevelReferences.Add(targetAlias, []); + + // top-level packages + TargetFrameworkInformation? targetFrameworkInformation = assetsFile.PackageSpec.TargetFrameworks.FirstOrDefault(tfi => tfi.TargetAlias.Equals(targetAlias, StringComparison.OrdinalIgnoreCase)); + if (targetFrameworkInformation != default) + { + var topLevelPackages = targetFrameworkInformation.Dependencies.Select(d => d.Name); + topLevelReferences[targetAlias].AddRange(topLevelPackages); + } + + // top-level projects + ProjectRestoreMetadataFrameworkInfo? restoreMetadataFrameworkInfo = assetsFile.PackageSpec.RestoreMetadata.TargetFrameworks.FirstOrDefault(tfi => tfi.TargetAlias.Equals(targetAlias, StringComparison.OrdinalIgnoreCase)); + if (restoreMetadataFrameworkInfo != default) + { + var topLevelProjectPaths = restoreMetadataFrameworkInfo.ProjectReferences.Select(p => p.ProjectPath); + foreach (var projectPath in topLevelProjectPaths) + { + topLevelReferences[targetAlias].Add(projectLibraryPathToName[projectPath]); + } + } + } + + return topLevelReferences; + } + + /// + /// Adds all resolved versions of packages to a dictionary. + /// + /// All package libraries for a given framework. + private static Dictionary GetAllResolvedVersions(IList packageLibraries) + { + var versions = new Dictionary(StringComparer.OrdinalIgnoreCase); + + foreach (var package in packageLibraries) + { + if (package?.Name != null && package?.Version != null) + { + versions.Add(package.Name, package.Version.ToNormalizedString()); + } + } + + return versions; + } + + private class StackDependencyData + { + public string Id { get; set; } + public StackDependencyData? Parent { get; set; } + + public StackDependencyData(string currentId, StackDependencyData? parentDependencyData) + { + Id = currentId; + Parent = parentDependencyData; + } + } + } +} diff --git a/src/NuGet.Core/NuGet.CommandLine.XPlat/Commands/WhyCommand/DependencyGraphPrinter.cs b/src/NuGet.Core/NuGet.CommandLine.XPlat/Commands/WhyCommand/DependencyGraphPrinter.cs new file mode 100644 index 00000000000..34c26ccedf6 --- /dev/null +++ b/src/NuGet.Core/NuGet.CommandLine.XPlat/Commands/WhyCommand/DependencyGraphPrinter.cs @@ -0,0 +1,186 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Linq; +using NuGet.Shared; + +namespace NuGet.CommandLine.XPlat +{ + internal static class DependencyGraphPrinter + { + private const ConsoleColor TargetPackageColor = ConsoleColor.Cyan; + + // Dependency graph console output symbols + private const string ChildNodeSymbol = "├─ "; + private const string LastChildNodeSymbol = "└─ "; + + private const string ChildPrefixSymbol = "│ "; + private const string LastChildPrefixSymbol = " "; + + /// + /// Prints the dependency graphs for all target frameworks. + /// + /// A dictionary mapping target frameworks to their dependency graphs. + /// The package we want the dependency paths for. + public static void PrintAllDependencyGraphs(Dictionary?> dependencyGraphPerFramework, string targetPackage, ILoggerWithColor logger) + { + // print empty line + logger.LogMinimal(""); + + // deduplicate the dependency graphs + List> deduplicatedFrameworks = GetDeduplicatedFrameworks(dependencyGraphPerFramework); + + foreach (var frameworks in deduplicatedFrameworks) + { + if (frameworks.Count > 0) + { + PrintDependencyGraphPerFramework(frameworks, dependencyGraphPerFramework[frameworks.First()], targetPackage, logger); + } + } + } + + /// + /// Prints the dependency graph for a given framework/list of frameworks. + /// + /// The list of frameworks that share this dependency graph. + /// The top-level package nodes of the dependency graph. + /// The package we want the dependency paths for. + private static void PrintDependencyGraphPerFramework(List frameworks, List? topLevelNodes, string targetPackage, ILoggerWithColor logger) + { + // print framework header + foreach (var framework in frameworks) + { + logger.LogMinimal($" [{framework}]"); + } + + logger.LogMinimal($" {ChildPrefixSymbol}"); + + if (topLevelNodes == null || topLevelNodes.Count == 0) + { + logger.LogMinimal($" {LastChildNodeSymbol}{Strings.WhyCommand_Message_NoDependencyGraphsFoundForFramework}\n\n"); + return; + } + + var stack = new Stack(); + + // initialize the stack with all top-level nodes + int counter = 0; + foreach (var node in topLevelNodes.OrderByDescending(c => c.Id, StringComparer.OrdinalIgnoreCase)) + { + stack.Push(new StackOutputData(node, prefix: " ", isLastChild: counter++ == 0)); + } + + // print the dependency graph + while (stack.Count > 0) + { + var current = stack.Pop(); + + string currentPrefix, childPrefix; + if (current.IsLastChild) + { + currentPrefix = current.Prefix + LastChildNodeSymbol; + childPrefix = current.Prefix + LastChildPrefixSymbol; + } + else + { + currentPrefix = current.Prefix + ChildNodeSymbol; + childPrefix = current.Prefix + ChildPrefixSymbol; + } + + // print current node + if (current.Node.Id.Equals(targetPackage, StringComparison.OrdinalIgnoreCase)) + { + logger.LogMinimal($"{currentPrefix}", Console.ForegroundColor); + logger.LogMinimal($"{current.Node.Id} (v{current.Node.Version})\n", TargetPackageColor); + } + else + { + logger.LogMinimal($"{currentPrefix}{current.Node.Id} (v{current.Node.Version})"); + } + + if (current.Node.Children?.Count > 0) + { + // push all the node's children onto the stack + counter = 0; + foreach (var child in current.Node.Children.OrderByDescending(c => c.Id, StringComparer.OrdinalIgnoreCase)) + { + stack.Push(new StackOutputData(child, childPrefix, isLastChild: counter++ == 0)); + } + } + } + + logger.LogMinimal(""); + } + + /// + /// Deduplicates dependency graphs, and returns groups of frameworks that share the same graph. + /// + /// A dictionary mapping target frameworks to their dependency graphs. + /// + /// eg. { { "net6.0", "netcoreapp3.1" }, { "net472" } } + /// + private static List> GetDeduplicatedFrameworks(Dictionary?> dependencyGraphPerFramework) + { + List? frameworksWithoutGraphs = null; + var dependencyGraphHashes = new Dictionary>(dependencyGraphPerFramework.Count); + + foreach (var framework in dependencyGraphPerFramework.Keys) + { + if (dependencyGraphPerFramework[framework] == null) + { + frameworksWithoutGraphs ??= []; + frameworksWithoutGraphs.Add(framework); + continue; + } + + int hash = GetDependencyGraphHashCode(dependencyGraphPerFramework[framework]); + if (dependencyGraphHashes.ContainsKey(hash)) + { + dependencyGraphHashes[hash].Add(framework); + } + else + { + dependencyGraphHashes.Add(hash, [framework]); + } + } + + var deduplicatedFrameworks = dependencyGraphHashes.Values.ToList(); + + if (frameworksWithoutGraphs != null) + { + deduplicatedFrameworks.Add(frameworksWithoutGraphs); + } + + return deduplicatedFrameworks; + } + + /// + /// Returns a hash for a given dependency graph. Used to deduplicate dependency graphs for different frameworks. + /// + /// The dependency graph for a given framework. + private static int GetDependencyGraphHashCode(List? graph) + { + var hashCodeCombiner = new HashCodeCombiner(); + hashCodeCombiner.AddUnorderedSequence(graph); + return hashCodeCombiner.CombinedHash; + } + + private class StackOutputData + { + public DependencyNode Node { get; set; } + public string Prefix { get; set; } + public bool IsLastChild { get; set; } + + public StackOutputData(DependencyNode node, string prefix, bool isLastChild) + { + Node = node; + Prefix = prefix; + IsLastChild = isLastChild; + } + } + } +} diff --git a/src/NuGet.Core/NuGet.CommandLine.XPlat/Commands/WhyCommand/DependencyNode.cs b/src/NuGet.Core/NuGet.CommandLine.XPlat/Commands/WhyCommand/DependencyNode.cs new file mode 100644 index 00000000000..05c73c4ce5c --- /dev/null +++ b/src/NuGet.Core/NuGet.CommandLine.XPlat/Commands/WhyCommand/DependencyNode.cs @@ -0,0 +1,53 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +#nullable enable + +using System; +using System.Collections.Generic; +using NuGet.Shared; + +namespace NuGet.CommandLine.XPlat +{ + /// + /// Represents a node in the package dependency graph. + /// + internal class DependencyNode + { + public string Id { get; set; } + public string Version { get; set; } + public HashSet Children { get; set; } + + public DependencyNode(string id, string version) + { + Id = id ?? throw new ArgumentNullException(nameof(id)); + Version = version ?? throw new ArgumentNullException(nameof(version)); + Children = new HashSet(new DependencyNodeComparer()); + } + + public override int GetHashCode() + { + var hashCodeCombiner = new HashCodeCombiner(); + hashCodeCombiner.AddObject(Id); + hashCodeCombiner.AddObject(Version); + hashCodeCombiner.AddUnorderedSequence(Children); + return hashCodeCombiner.CombinedHash; + } + } + + internal class DependencyNodeComparer : IEqualityComparer + { + public bool Equals(DependencyNode? x, DependencyNode? y) + { + if (x == null || y == null) + return false; + + return string.Equals(x.Id, y.Id, StringComparison.CurrentCultureIgnoreCase); + } + + public int GetHashCode(DependencyNode obj) + { + return obj.Id.GetHashCode(); + } + } +} diff --git a/src/NuGet.Core/NuGet.CommandLine.XPlat/Commands/WhyCommand/WhyCommand.cs b/src/NuGet.Core/NuGet.CommandLine.XPlat/Commands/WhyCommand/WhyCommand.cs new file mode 100644 index 00000000000..06f561bdf2a --- /dev/null +++ b/src/NuGet.Core/NuGet.CommandLine.XPlat/Commands/WhyCommand/WhyCommand.cs @@ -0,0 +1,70 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.CommandLine; +using System.CommandLine.Help; + +namespace NuGet.CommandLine.XPlat +{ + internal static class WhyCommand + { + private static CliArgument Path = new CliArgument("PROJECT|SOLUTION") + { + Description = Strings.WhyCommand_PathArgument_Description, + Arity = ArgumentArity.ExactlyOne + }; + + private static CliArgument Package = new CliArgument("PACKAGE") + { + Description = Strings.WhyCommand_PackageArgument_Description, + Arity = ArgumentArity.ExactlyOne + }; + + private static CliOption> Frameworks = new CliOption>("--framework", "-f") + { + Description = Strings.WhyCommand_FrameworksOption_Description, + Arity = ArgumentArity.OneOrMore + }; + + private static HelpOption Help = new HelpOption() + { + Arity = ArgumentArity.Zero + }; + + internal static void Register(CliCommand rootCommand, Func getLogger) + { + var whyCommand = new CliCommand("why", Strings.WhyCommand_Description); + + whyCommand.Arguments.Add(Path); + whyCommand.Arguments.Add(Package); + whyCommand.Options.Add(Frameworks); + whyCommand.Options.Add(Help); + + whyCommand.SetAction((parseResult) => + { + ILoggerWithColor logger = getLogger(); + + try + { + var whyCommandArgs = new WhyCommandArgs( + parseResult.GetValue(Path), + parseResult.GetValue(Package), + parseResult.GetValue(Frameworks), + logger); + + int exitCode = WhyCommandRunner.ExecuteCommand(whyCommandArgs); + return exitCode; + } + catch (ArgumentException ex) + { + logger.LogError(ex.Message); + return ExitCodes.InvalidArguments; + } + }); + + rootCommand.Subcommands.Add(whyCommand); + } + } +} diff --git a/src/NuGet.Core/NuGet.CommandLine.XPlat/Commands/WhyCommand/WhyCommandArgs.cs b/src/NuGet.Core/NuGet.CommandLine.XPlat/Commands/WhyCommand/WhyCommandArgs.cs new file mode 100644 index 00000000000..3cee48370af --- /dev/null +++ b/src/NuGet.Core/NuGet.CommandLine.XPlat/Commands/WhyCommand/WhyCommandArgs.cs @@ -0,0 +1,37 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +#nullable enable + +using System; +using System.Collections.Generic; + +namespace NuGet.CommandLine.XPlat +{ + internal class WhyCommandArgs + { + public string Path { get; } + public string Package { get; } + public List Frameworks { get; } + public ILoggerWithColor Logger { get; } + + /// + /// A constructor for the arguments of the 'why' command. + /// + /// The path to the solution or project file. + /// The package for which we show the dependency graphs. + /// The target framework(s) for which we show the dependency graphs. + /// + public WhyCommandArgs( + string path, + string package, + List frameworks, + ILoggerWithColor logger) + { + Path = path ?? throw new ArgumentNullException(nameof(path)); + Package = package ?? throw new ArgumentNullException(nameof(package)); + Frameworks = frameworks ?? throw new ArgumentNullException(nameof(frameworks)); + Logger = logger ?? throw new ArgumentNullException(nameof(logger)); + } + } +} diff --git a/src/NuGet.Core/NuGet.CommandLine.XPlat/Commands/WhyCommand/WhyCommandRunner.cs b/src/NuGet.Core/NuGet.CommandLine.XPlat/Commands/WhyCommand/WhyCommandRunner.cs new file mode 100644 index 00000000000..7f8ebccc55f --- /dev/null +++ b/src/NuGet.Core/NuGet.CommandLine.XPlat/Commands/WhyCommand/WhyCommandRunner.cs @@ -0,0 +1,213 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; +using Microsoft.Build.Evaluation; +using NuGet.ProjectModel; + +namespace NuGet.CommandLine.XPlat +{ + internal static class WhyCommandRunner + { + private const string ProjectAssetsFile = "ProjectAssetsFile"; + + /// + /// Executes the 'why' command. + /// + /// CLI arguments for the 'why' command. + public static int ExecuteCommand(WhyCommandArgs whyCommandArgs) + { + bool validArgumentsUsed = ValidatePathArgument(whyCommandArgs.Path, whyCommandArgs.Logger) + && ValidatePackageArgument(whyCommandArgs.Package, whyCommandArgs.Logger); + if (!validArgumentsUsed) + { + return ExitCodes.InvalidArguments; + } + + string targetPackage = whyCommandArgs.Package; + + IEnumerable projectPaths = Path.GetExtension(whyCommandArgs.Path).Equals(".sln") + ? MSBuildAPIUtility.GetProjectsFromSolution(whyCommandArgs.Path).Where(f => File.Exists(f)) + : [whyCommandArgs.Path]; + + foreach (var projectPath in projectPaths) + { + Project project = MSBuildAPIUtility.GetProject(projectPath); + + string usingNetSdk = project.GetPropertyValue("UsingMicrosoftNETSdk"); + + if (!string.IsNullOrEmpty(usingNetSdk)) + { + LockFile? assetsFile = GetProjectAssetsFile(project, whyCommandArgs.Logger); + + if (assetsFile != null) + { + ValidateFrameworksOptions(assetsFile, whyCommandArgs.Frameworks, whyCommandArgs.Logger); + + Dictionary?>? dependencyGraphPerFramework = DependencyGraphFinder.GetAllDependencyGraphsForTarget( + assetsFile, + whyCommandArgs.Package, + whyCommandArgs.Frameworks); + + if (dependencyGraphPerFramework != null) + { + whyCommandArgs.Logger.LogMinimal( + string.Format( + Strings.WhyCommand_Message_DependencyGraphsFoundInProject, + assetsFile.PackageSpec.Name, + targetPackage)); + + DependencyGraphPrinter.PrintAllDependencyGraphs(dependencyGraphPerFramework, targetPackage, whyCommandArgs.Logger); + } + else + { + whyCommandArgs.Logger.LogMinimal( + string.Format( + Strings.WhyCommand_Message_NoDependencyGraphsFoundInProject, + assetsFile.PackageSpec.Name, + targetPackage)); + } + } + } + else + { + whyCommandArgs.Logger.LogMinimal( + string.Format( + Strings.WhyCommand_Message_NonSDKStyleProjectsAreNotSupported, + project.GetPropertyValue("MSBuildProjectName"))); + } + + ProjectCollection.GlobalProjectCollection.UnloadProject(project); + } + + return ExitCodes.Success; + } + + private static bool ValidatePathArgument(string path, ILoggerWithColor logger) + { + if (string.IsNullOrEmpty(path)) + { + logger.LogError( + string.Format( + CultureInfo.CurrentCulture, + Strings.WhyCommand_Error_ArgumentCannotBeEmpty, + "PROJECT|SOLUTION")); + + return false; + } + + if (!File.Exists(path) + || (!path.EndsWith("proj", StringComparison.OrdinalIgnoreCase) + && !path.EndsWith(".sln", StringComparison.OrdinalIgnoreCase))) + { + logger.LogError( + string.Format( + CultureInfo.CurrentCulture, + Strings.WhyCommand_Error_PathIsMissingOrInvalid, + path)); + + return false; + } + + return true; + } + + private static bool ValidatePackageArgument(string package, ILoggerWithColor logger) + { + if (string.IsNullOrEmpty(package)) + { + logger.LogError( + string.Format( + CultureInfo.CurrentCulture, + Strings.WhyCommand_Error_ArgumentCannotBeEmpty, + "PACKAGE")); + + return false; + } + + return true; + } + + /// + /// Validates and returns the assets file for the given project. + /// + /// Evaluated MSBuild project + /// Logger for the 'why' command + /// Assets file for the given project. Returns null if there was any issue finding or parsing the assets file. + private static LockFile? GetProjectAssetsFile(Project project, ILoggerWithColor logger) + { + if (!MSBuildAPIUtility.IsPackageReferenceProject(project)) + { + logger.LogError( + string.Format( + CultureInfo.CurrentCulture, + Strings.Error_NotPRProject, + project.FullPath)); + + return null; + } + + string assetsPath = project.GetPropertyValue(ProjectAssetsFile); + + if (!File.Exists(assetsPath)) + { + logger.LogError( + string.Format( + CultureInfo.CurrentCulture, + Strings.Error_AssetsFileNotFound, + project.FullPath)); + + return null; + } + + var lockFileFormat = new LockFileFormat(); + LockFile assetsFile = lockFileFormat.Read(assetsPath); + + // assets file validation + if (assetsFile.PackageSpec == null + || assetsFile.Targets == null + || assetsFile.Targets.Count == 0) + { + logger.LogError( + string.Format( + CultureInfo.CurrentCulture, + Strings.WhyCommand_Error_InvalidAssetsFile, + assetsFile.Path, + project.FullPath)); + + return null; + } + + return assetsFile; + } + + /// + /// Validates that the input frameworks options have corresponding targets in the assets file. Outputs a warning message if a framework does not exist. + /// + /// + /// + /// + private static void ValidateFrameworksOptions(LockFile assetsFile, List inputFrameworks, ILoggerWithColor logger) + { + foreach (var frameworkAlias in inputFrameworks) + { + if (assetsFile.GetTarget(frameworkAlias, runtimeIdentifier: null) == null) + { + logger.LogWarning( + string.Format( + CultureInfo.CurrentCulture, + Strings.WhyCommand_Warning_AssetsFileDoesNotContainSpecifiedTarget, + assetsFile.Path, + assetsFile.PackageSpec.Name, + frameworkAlias)); + } + } + } + } +} diff --git a/src/NuGet.Core/NuGet.CommandLine.XPlat/Program.cs b/src/NuGet.Core/NuGet.CommandLine.XPlat/Program.cs index d4f389b212f..7f99b66e309 100644 --- a/src/NuGet.Core/NuGet.CommandLine.XPlat/Program.cs +++ b/src/NuGet.Core/NuGet.CommandLine.XPlat/Program.cs @@ -74,18 +74,36 @@ public static int MainInternal(string[] args, CommandOutputLogger log) NuGet.Common.Migrations.MigrationRunner.Run(); - if ((args.Count() >= 2 && args[0] == "package" && args[1] == "search") || (args.Any() && args[0] == "config")) + // TODO: Migrating from Microsoft.Extensions.CommandLineUtils.CommandLineApplication to System.Commandline.CliCommand + // If we are looking to add further commands here, we should also look to redesign this parsing logic at that time + // See related issues: + // - https://github.com/NuGet/Home/issues/11996 + // - https://github.com/NuGet/Home/issues/11997 + // - https://github.com/NuGet/Home/issues/13089 + if ((args.Count() >= 2 && args[0] == "package" && args[1] == "search") + || (args.Any() && args[0] == "config") + || (args.Any() && args[0] == "why")) { - // We are executing command `dotnet package search` Func getHidePrefixLogger = () => { log.HidePrefixForInfoAndMinimal = true; return log; }; - CliCommand rootCommand = new CliCommand("package"); - PackageSearchCommand.Register(rootCommand, getHidePrefixLogger); - ConfigCommand.Register(rootCommand, getHidePrefixLogger); + CliCommand rootCommand; + if (args[0] == "package") + { + rootCommand = new CliCommand("package"); + + PackageSearchCommand.Register(rootCommand, getHidePrefixLogger); + } + else + { + rootCommand = new CliCommand("nuget"); + + ConfigCommand.Register(rootCommand, getHidePrefixLogger); + WhyCommand.Register(rootCommand, getHidePrefixLogger); + } CancellationTokenSource tokenSource = new CancellationTokenSource(); tokenSource.CancelAfter(TimeSpan.FromMinutes(DotnetPackageSearchTimeOut)); diff --git a/src/NuGet.Core/NuGet.CommandLine.XPlat/Strings.Designer.cs b/src/NuGet.Core/NuGet.CommandLine.XPlat/Strings.Designer.cs index b7fa2fd8db5..23735887f82 100644 --- a/src/NuGet.Core/NuGet.CommandLine.XPlat/Strings.Designer.cs +++ b/src/NuGet.Core/NuGet.CommandLine.XPlat/Strings.Designer.cs @@ -1,4 +1,4 @@ -//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ // // This code was generated by a tool. // Runtime Version:4.0.30319.42000 @@ -564,15 +564,6 @@ internal static string Error_CentralPackageVersions_VersionsNotAllowed { } } - /// - /// Looks up a localized string similar to {0} is not a valid integer.. - /// - internal static string Error_invalid_number { - get { - return ResourceManager.GetString("Error_invalid_number", resourceCulture); - } - } - /// /// Looks up a localized string similar to '{0}' is not a valid config key in config section.. /// @@ -2213,5 +2204,113 @@ internal static string Warning_HttpServerUsage_MultipleSources { return ResourceManager.GetString("Warning_HttpServerUsage_MultipleSources", resourceCulture); } } + + /// + /// Looks up a localized string similar to Shows the dependency graph for a particular package for a given project or solution.. + /// + internal static string WhyCommand_Description { + get { + return ResourceManager.GetString("WhyCommand_Description", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unable to run 'dotnet nuget why'. The '{0}' argument cannot be empty.. + /// + internal static string WhyCommand_Error_ArgumentCannotBeEmpty { + get { + return ResourceManager.GetString("WhyCommand_Error_ArgumentCannotBeEmpty", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The assets file {0} is invalid. Please run restore for project '{1}' before running this command.. + /// + internal static string WhyCommand_Error_InvalidAssetsFile { + get { + return ResourceManager.GetString("WhyCommand_Error_InvalidAssetsFile", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unable to run 'dotnet nuget why'. Missing or invalid project/solution file '{0}'.. + /// + internal static string WhyCommand_Error_PathIsMissingOrInvalid { + get { + return ResourceManager.GetString("WhyCommand_Error_PathIsMissingOrInvalid", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The target framework(s) for which dependency graphs are shown.. + /// + internal static string WhyCommand_FrameworksOption_Description { + get { + return ResourceManager.GetString("WhyCommand_FrameworksOption_Description", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Project '{0}' has the following dependency graph(s) for '{1}':. + /// + internal static string WhyCommand_Message_DependencyGraphsFoundInProject { + get { + return ResourceManager.GetString("WhyCommand_Message_DependencyGraphsFoundInProject", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to No dependency graph(s) found for this target framework.. + /// + internal static string WhyCommand_Message_NoDependencyGraphsFoundForFramework { + get { + return ResourceManager.GetString("WhyCommand_Message_NoDependencyGraphsFoundForFramework", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Project '{0}' does not have a dependency on '{1}'.. + /// + internal static string WhyCommand_Message_NoDependencyGraphsFoundInProject { + get { + return ResourceManager.GetString("WhyCommand_Message_NoDependencyGraphsFoundInProject", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unable to run 'dotnet nuget why' for project '{0}'. This command only works on SDK-style projects.. + /// + internal static string WhyCommand_Message_NonSDKStyleProjectsAreNotSupported { + get { + return ResourceManager.GetString("WhyCommand_Message_NonSDKStyleProjectsAreNotSupported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The package name to lookup in the dependency graph.. + /// + internal static string WhyCommand_PackageArgument_Description { + get { + return ResourceManager.GetString("WhyCommand_PackageArgument_Description", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to A path to a project, solution file, or directory.. + /// + internal static string WhyCommand_PathArgument_Description { + get { + return ResourceManager.GetString("WhyCommand_PathArgument_Description", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The assets file {0} for project '{1}' does not contain a target for the specified input framework '{2}'.. + /// + internal static string WhyCommand_Warning_AssetsFileDoesNotContainSpecifiedTarget { + get { + return ResourceManager.GetString("WhyCommand_Warning_AssetsFileDoesNotContainSpecifiedTarget", resourceCulture); + } + } } } diff --git a/src/NuGet.Core/NuGet.CommandLine.XPlat/Strings.resx b/src/NuGet.Core/NuGet.CommandLine.XPlat/Strings.resx index 2073706b3d9..236b2313371 100644 --- a/src/NuGet.Core/NuGet.CommandLine.XPlat/Strings.resx +++ b/src/NuGet.Core/NuGet.CommandLine.XPlat/Strings.resx @@ -912,4 +912,46 @@ Non-HTTPS access will be removed in a future version. Consider migrating to 'HTT Gets the NuGet configuration settings that will be applied. + + Shows the dependency graph for a particular package for a given project or solution. + + + A path to a project, solution file, or directory. + + + The package name to lookup in the dependency graph. + + + The target framework(s) for which dependency graphs are shown. + + + Unable to run 'dotnet nuget why'. The '{0}' argument cannot be empty. + {0} - Argument that was not provided + + + Unable to run 'dotnet nuget why'. Missing or invalid project/solution file '{0}'. + {0} - Project/solution file path + + + Unable to run 'dotnet nuget why' for project '{0}'. This command only works on SDK-style projects. + + + The assets file {0} is invalid. Please run restore for project '{1}' before running this command. + {0} - Assets file path, {1} - Project name + + + The assets file {0} for project '{1}' does not contain a target for the specified input framework '{2}'. + {0} - Assets file path, {1} - Project name, {2} - Framework + + + Project '{0}' does not have a dependency on '{1}'. + {0} - Project name, {1} - Target package + + + Project '{0}' has the following dependency graph(s) for '{1}': + {0} - Project name, {1} - Target package + + + No dependency graph(s) found for this target framework. + diff --git a/src/NuGet.Core/NuGet.CommandLine.XPlat/Utility/CommandOutputLogger.cs b/src/NuGet.Core/NuGet.CommandLine.XPlat/Utility/CommandOutputLogger.cs index c2bdc44cd5e..bc8b94b2700 100644 --- a/src/NuGet.Core/NuGet.CommandLine.XPlat/Utility/CommandOutputLogger.cs +++ b/src/NuGet.Core/NuGet.CommandLine.XPlat/Utility/CommandOutputLogger.cs @@ -128,7 +128,7 @@ public override Task LogAsync(ILogMessage message) return Task.CompletedTask; } - public void LogMinimal(string data, ConsoleColor color) + public virtual void LogMinimal(string data, ConsoleColor color) { var currentColor = Console.ForegroundColor; Console.ForegroundColor = color; diff --git a/test/NuGet.Core.FuncTests/Dotnet.Integration.Test/DotnetWhyTests.cs b/test/NuGet.Core.FuncTests/Dotnet.Integration.Test/DotnetWhyTests.cs new file mode 100644 index 00000000000..3fb63aeed1b --- /dev/null +++ b/test/NuGet.Core.FuncTests/Dotnet.Integration.Test/DotnetWhyTests.cs @@ -0,0 +1,222 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using NuGet.CommandLine.XPlat; +using NuGet.Test.Utility; +using NuGet.XPlat.FuncTest; +using Xunit; + +namespace Dotnet.Integration.Test +{ + [Collection(DotnetIntegrationCollection.Name)] + public class DotnetWhyTests + { + private static readonly string ProjectName = "Test.Project.DotnetNugetWhy"; + + private readonly DotnetIntegrationTestFixture _testFixture; + + public DotnetWhyTests(DotnetIntegrationTestFixture testFixture) + { + _testFixture = testFixture; + } + + [Fact] + public async void WhyCommand_ProjectHasTransitiveDependency_DependencyPathExists() + { + // Arrange + var pathContext = new SimpleTestPathContext(); + var projectFramework = "net7.0"; + var project = XPlatTestUtils.CreateProject(ProjectName, pathContext, projectFramework); + + var packageX = XPlatTestUtils.CreatePackage("PackageX", "1.0.0", projectFramework); + var packageY = XPlatTestUtils.CreatePackage("PackageY", "1.0.1", projectFramework); + + packageX.Dependencies.Add(packageY); + + project.AddPackageToFramework(projectFramework, packageX); + + await SimpleTestPackageUtility.CreatePackagesAsync( + pathContext.PackageSource, + packageX, + packageY); + + string addPackageCommandArgs = $"add {project.ProjectPath} package {packageX.Id}"; + CommandRunnerResult addPackageResult = _testFixture.RunDotnetExpectSuccess(pathContext.SolutionRoot, addPackageCommandArgs); + + string whyCommandArgs = $"nuget why {project.ProjectPath} {packageY.Id}"; + + // Act + CommandRunnerResult result = _testFixture.RunDotnetExpectSuccess(pathContext.SolutionRoot, whyCommandArgs); + + // Assert + Assert.Equal(ExitCodes.Success, result.ExitCode); + Assert.Contains($"Project '{ProjectName}' has the following dependency graph(s) for '{packageY.Id}'", result.AllOutput); + } + + [Fact] + public async void WhyCommand_ProjectHasNoDependencyOnTargetPackage_PathDoesNotExist() + { + // Arrange + var pathContext = new SimpleTestPathContext(); + var projectFramework = "net7.0"; + var project = XPlatTestUtils.CreateProject(ProjectName, pathContext, projectFramework); + + var packageX = XPlatTestUtils.CreatePackage("PackageX", "1.0.0", projectFramework); + project.AddPackageToFramework(projectFramework, packageX); + + var packageZ = XPlatTestUtils.CreatePackage("PackageZ", "1.0.0", projectFramework); + + await SimpleTestPackageUtility.CreatePackagesAsync( + pathContext.PackageSource, + packageX, + packageZ); + + string addPackageCommandArgs = $"add {project.ProjectPath} package {packageX.Id}"; + CommandRunnerResult addPackageResult = _testFixture.RunDotnetExpectSuccess(pathContext.SolutionRoot, addPackageCommandArgs); + + string whyCommandArgs = $"nuget why {project.ProjectPath} {packageZ.Id}"; + + // Act + CommandRunnerResult result = _testFixture.RunDotnetExpectSuccess(pathContext.SolutionRoot, whyCommandArgs); + + // Assert + Assert.Equal(ExitCodes.Success, result.ExitCode); + Assert.Contains($"Project '{ProjectName}' does not have a dependency on '{packageZ.Id}'", result.AllOutput); + } + + [Fact] + public async void WhyCommand_WithFrameworksOption_OptionParsedSuccessfully() + { + // Arrange + var pathContext = new SimpleTestPathContext(); + var projectFramework = "net7.0"; + var project = XPlatTestUtils.CreateProject(ProjectName, pathContext, projectFramework); + + var packageX = XPlatTestUtils.CreatePackage("PackageX", "1.0.0", projectFramework); + var packageY = XPlatTestUtils.CreatePackage("PackageY", "1.0.1", projectFramework); + + packageX.Dependencies.Add(packageY); + + project.AddPackageToFramework(projectFramework, packageX); + + await SimpleTestPackageUtility.CreatePackagesAsync( + pathContext.PackageSource, + packageX, + packageY); + + string addPackageCommandArgs = $"add {project.ProjectPath} package {packageX.Id}"; + CommandRunnerResult addPackageResult = _testFixture.RunDotnetExpectSuccess(pathContext.SolutionRoot, addPackageCommandArgs); + + string whyCommandArgs = $"nuget why {project.ProjectPath} {packageY.Id} --framework {projectFramework}"; + + // Act + CommandRunnerResult result = _testFixture.RunDotnetExpectSuccess(pathContext.SolutionRoot, whyCommandArgs); + + // Assert + Assert.Equal(ExitCodes.Success, result.ExitCode); + Assert.Contains($"Project '{ProjectName}' has the following dependency graph(s) for '{packageY.Id}'", result.AllOutput); + } + + [Fact] + public async void WhyCommand_WithFrameworksOptionAlias_OptionParsedSuccessfully() + { + // Arrange + var pathContext = new SimpleTestPathContext(); + var projectFramework = "net7.0"; + var project = XPlatTestUtils.CreateProject(ProjectName, pathContext, projectFramework); + + var packageX = XPlatTestUtils.CreatePackage("PackageX", "1.0.0", projectFramework); + var packageY = XPlatTestUtils.CreatePackage("PackageY", "1.0.1", projectFramework); + + packageX.Dependencies.Add(packageY); + + project.AddPackageToFramework(projectFramework, packageX); + + await SimpleTestPackageUtility.CreatePackagesAsync( + pathContext.PackageSource, + packageX, + packageY); + + string addPackageCommandArgs = $"add {project.ProjectPath} package {packageX.Id}"; + CommandRunnerResult addPackageResult = _testFixture.RunDotnetExpectSuccess(pathContext.SolutionRoot, addPackageCommandArgs); + + string whyCommandArgs = $"nuget why {project.ProjectPath} {packageY.Id} -f {projectFramework}"; + + // Act + CommandRunnerResult result = _testFixture.RunDotnetExpectSuccess(pathContext.SolutionRoot, whyCommandArgs); + + // Assert + Assert.Equal(ExitCodes.Success, result.ExitCode); + Assert.Contains($"Project '{ProjectName}' has the following dependency graph(s) for '{packageY.Id}'", result.AllOutput); + } + + [Fact] + public void WhyCommand_EmptyProjectArgument_Fails() + { + // Arrange + var pathContext = new SimpleTestPathContext(); + + string whyCommandArgs = $"nuget why"; + + // Act + CommandRunnerResult result = _testFixture.RunDotnetExpectFailure(pathContext.SolutionRoot, whyCommandArgs); + + // Assert + Assert.Equal(ExitCodes.InvalidArguments, result.ExitCode); + Assert.Contains($"Required argument missing for command: 'why'.", result.Errors); + } + + [Fact] + public void WhyCommand_EmptyPackageArgument_Fails() + { + // Arrange + var pathContext = new SimpleTestPathContext(); + var projectFramework = "net7.0"; + var project = XPlatTestUtils.CreateProject(ProjectName, pathContext, projectFramework); + + string whyCommandArgs = $"nuget why {project.ProjectPath}"; + + // Act + CommandRunnerResult result = _testFixture.RunDotnetExpectFailure(pathContext.SolutionRoot, whyCommandArgs); + + // Assert + Assert.Equal(ExitCodes.InvalidArguments, result.ExitCode); + Assert.Contains($"Required argument missing for command: 'why'.", result.Errors); + } + + [Fact] + public async void WhyCommand_InvalidFrameworksOption_WarnsCorrectly() + { + // Arrange + var pathContext = new SimpleTestPathContext(); + var projectFramework = "net7.0"; + var inputFrameworksOption = "invalidFrameworkAlias"; + var project = XPlatTestUtils.CreateProject(ProjectName, pathContext, projectFramework); + + var packageX = XPlatTestUtils.CreatePackage("PackageX", "1.0.0", projectFramework); + var packageY = XPlatTestUtils.CreatePackage("PackageY", "1.0.1", projectFramework); + + packageX.Dependencies.Add(packageY); + + project.AddPackageToFramework(projectFramework, packageX); + + await SimpleTestPackageUtility.CreatePackagesAsync( + pathContext.PackageSource, + packageX, + packageY); + + string addPackageCommandArgs = $"add {project.ProjectPath} package {packageX.Id}"; + CommandRunnerResult addPackageResult = _testFixture.RunDotnetExpectSuccess(pathContext.SolutionRoot, addPackageCommandArgs); + + string whyCommandArgs = $"nuget why {project.ProjectPath} {packageY.Id} -f {inputFrameworksOption} -f {projectFramework}"; + + // Act + CommandRunnerResult result = _testFixture.RunDotnetExpectSuccess(pathContext.SolutionRoot, whyCommandArgs); + + // Assert + Assert.Equal(ExitCodes.Success, result.ExitCode); + Assert.Contains($"warn : The assets file {project.AssetsFileOutputPath} for project '{ProjectName}' does not contain a target for the specified input framework '{inputFrameworksOption}'.", result.AllOutput); + Assert.Contains($"Project '{ProjectName}' has the following dependency graph(s) for '{packageY.Id}'", result.AllOutput); + } + } +} diff --git a/test/NuGet.Core.FuncTests/NuGet.XPlat.FuncTest/TestCommandOutputLogger.cs b/test/NuGet.Core.FuncTests/NuGet.XPlat.FuncTest/TestCommandOutputLogger.cs index aa7aebcecac..791c5bfb405 100644 --- a/test/NuGet.Core.FuncTests/NuGet.XPlat.FuncTest/TestCommandOutputLogger.cs +++ b/test/NuGet.Core.FuncTests/NuGet.XPlat.FuncTest/TestCommandOutputLogger.cs @@ -54,6 +54,11 @@ protected override void LogInternal(LogLevel logLevel, string message) } } + public override void LogMinimal(string data, ConsoleColor color) + { + LogInternal(LogLevel.Minimal, data); + } + public ConcurrentQueue Messages { get diff --git a/test/NuGet.Core.FuncTests/NuGet.XPlat.FuncTest/XPlatWhyTests.cs b/test/NuGet.Core.FuncTests/NuGet.XPlat.FuncTest/XPlatWhyTests.cs new file mode 100644 index 00000000000..40209f99eff --- /dev/null +++ b/test/NuGet.Core.FuncTests/NuGet.XPlat.FuncTest/XPlatWhyTests.cs @@ -0,0 +1,251 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using NuGet.CommandLine.XPlat; +using NuGet.Packaging; +using NuGet.Test.Utility; +using Xunit; + +namespace NuGet.XPlat.FuncTest +{ + [Collection("NuGet XPlat Test Collection")] + public class XPlatWhyTests + { + private static readonly string ProjectName = "Test.Project.DotnetNugetWhy"; + private static MSBuildAPIUtility MsBuild => new MSBuildAPIUtility(new TestCommandOutputLogger()); + + [Fact] + public async void WhyCommand_ProjectHasTransitiveDependency_DependencyPathExists() + { + // Arrange + var logger = new TestCommandOutputLogger(); + + var pathContext = new SimpleTestPathContext(); + var projectFramework = "net472"; + var project = XPlatTestUtils.CreateProject(ProjectName, pathContext, projectFramework); + + var packageX = XPlatTestUtils.CreatePackage("PackageX", "1.0.0"); + var packageY = XPlatTestUtils.CreatePackage("PackageY", "1.0.1"); + + packageX.Dependencies.Add(packageY); + + project.AddPackageToFramework(projectFramework, packageX); + + await SimpleTestPackageUtility.CreateFolderFeedV3Async( + pathContext.PackageSource, + PackageSaveMode.Defaultv3, + packageX, + packageY); + + var addPackageArgs = XPlatTestUtils.GetPackageReferenceArgs(packageX.Id, packageX.Version, project); + var addPackageCommandRunner = new AddPackageReferenceCommandRunner(); + var addPackageResult = await addPackageCommandRunner.ExecuteCommand(addPackageArgs, MsBuild); + + var whyCommandArgs = new WhyCommandArgs( + project.ProjectPath, + packageY.Id, + [projectFramework], + logger); + + // Act + var result = WhyCommandRunner.ExecuteCommand(whyCommandArgs); + + // Assert + var output = logger.ShowMessages(); + + Assert.Equal(ExitCodes.Success, result); + Assert.Contains($"Project '{ProjectName}' has the following dependency graph(s) for '{packageY.Id}'", output); + Assert.Contains($"{packageX.Id} (v{packageX.Version})", output); + Assert.Contains($"{packageY.Id} (v{packageY.Version})", output); + } + + [Fact] + public async void WhyCommand_ProjectHasNoDependencyOnTargetPackage_PathDoesNotExist() + { + // Arrange + var logger = new TestCommandOutputLogger(); + + var pathContext = new SimpleTestPathContext(); + var projectFramework = "net472"; + var project = XPlatTestUtils.CreateProject(ProjectName, pathContext, projectFramework); + + var packageX = XPlatTestUtils.CreatePackage("PackageX", "1.0.0"); + project.AddPackageToFramework(projectFramework, packageX); + + var packageZ = XPlatTestUtils.CreatePackage("PackageZ", "1.0.0"); // not added to project + + await SimpleTestPackageUtility.CreateFolderFeedV3Async( + pathContext.PackageSource, + PackageSaveMode.Defaultv3, + packageX, + packageZ); + + var addPackageArgs = XPlatTestUtils.GetPackageReferenceArgs(packageX.Id, packageX.Version, project); + var addPackageCommandRunner = new AddPackageReferenceCommandRunner(); + var addPackageResult = await addPackageCommandRunner.ExecuteCommand(addPackageArgs, MsBuild); + + var whyCommandArgs = new WhyCommandArgs( + project.ProjectPath, + packageZ.Id, + [projectFramework], + logger); + + // Act + var result = WhyCommandRunner.ExecuteCommand(whyCommandArgs); + + // Assert + var output = logger.ShowMessages(); + + Assert.Equal(ExitCodes.Success, result); + Assert.Contains($"Project '{ProjectName}' does not have a dependency on '{packageZ.Id}'", output); + } + + [Fact] + public void WhyCommand_ProjectDidNotRunRestore_Fails() + { + // Arrange + var logger = new TestCommandOutputLogger(); + + var pathContext = new SimpleTestPathContext(); + var projectFramework = "net472"; + var project = XPlatTestUtils.CreateProject(ProjectName, pathContext, projectFramework); + + var packageX = XPlatTestUtils.CreatePackage("PackageX", "1.0.0"); + var packageY = XPlatTestUtils.CreatePackage("PackageY", "1.0.1"); + + packageX.Dependencies.Add(packageY); + + project.AddPackageToFramework(projectFramework, packageX); + + var whyCommandArgs = new WhyCommandArgs( + project.ProjectPath, + packageY.Id, + [projectFramework], + logger); + + // Act + var result = WhyCommandRunner.ExecuteCommand(whyCommandArgs); + + // Assert + var output = logger.ShowMessages(); + + Assert.Equal(ExitCodes.Success, result); + Assert.Contains($"No assets file was found for `{project.ProjectPath}`. Please run restore before running this command.", output); + } + + [Fact] + public void WhyCommand_EmptyProjectArgument_Fails() + { + // Arrange + var logger = new TestCommandOutputLogger(); + + var whyCommandArgs = new WhyCommandArgs( + "", + "PackageX", + [], + logger); + + // Act + var result = WhyCommandRunner.ExecuteCommand(whyCommandArgs); + + // Assert + var errorOutput = logger.ShowErrors(); + + Assert.Equal(ExitCodes.InvalidArguments, result); + Assert.Contains($"Unable to run 'dotnet nuget why'. The 'PROJECT|SOLUTION' argument cannot be empty.", errorOutput); + } + + [Fact] + public void WhyCommand_EmptyPackageArgument_Fails() + { + // Arrange + var logger = new TestCommandOutputLogger(); + + var pathContext = new SimpleTestPathContext(); + var projectFramework = "net472"; + var project = XPlatTestUtils.CreateProject(ProjectName, pathContext, projectFramework); + + var whyCommandArgs = new WhyCommandArgs( + project.ProjectPath, + "", + [], + logger); + + // Act + var result = WhyCommandRunner.ExecuteCommand(whyCommandArgs); + + // Assert + var errorOutput = logger.ShowErrors(); + + Assert.Equal(ExitCodes.InvalidArguments, result); + Assert.Contains($"Unable to run 'dotnet nuget why'. The 'PACKAGE' argument cannot be empty.", errorOutput); + } + + [Fact] + public void WhyCommand_InvalidProject_Fails() + { + // Arrange + var logger = new TestCommandOutputLogger(); + + var whyCommandArgs = new WhyCommandArgs( + "FakeProjectPath.csproj", + "PackageX", + [], + logger); + + // Act + var result = WhyCommandRunner.ExecuteCommand(whyCommandArgs); + + // Assert + var errorOutput = logger.ShowErrors(); + + Assert.Equal(ExitCodes.InvalidArguments, result); + Assert.Contains($"Unable to run 'dotnet nuget why'. Missing or invalid project/solution file 'FakeProjectPath.csproj'.", errorOutput); + } + + [Fact] + public async void WhyCommand_InvalidFrameworksOption_WarnsCorrectly() + { + // Arrange + var logger = new TestCommandOutputLogger(); + + var pathContext = new SimpleTestPathContext(); + var projectFramework = "net472"; + var inputFrameworksOption = "invalidFrameworkAlias"; + var project = XPlatTestUtils.CreateProject(ProjectName, pathContext, projectFramework); + + var packageX = XPlatTestUtils.CreatePackage("PackageX", "1.0.0", projectFramework); + var packageY = XPlatTestUtils.CreatePackage("PackageY", "1.0.1", projectFramework); + + packageX.Dependencies.Add(packageY); + + project.AddPackageToFramework(projectFramework, packageX); + + await SimpleTestPackageUtility.CreateFolderFeedV3Async( + pathContext.PackageSource, + PackageSaveMode.Defaultv3, + packageX, + packageY); + + var addPackageCommandArgs = XPlatTestUtils.GetPackageReferenceArgs(packageX.Id, packageX.Version, project); + var addPackageCommandRunner = new AddPackageReferenceCommandRunner(); + var addPackageResult = await addPackageCommandRunner.ExecuteCommand(addPackageCommandArgs, MsBuild); + + var whyCommandArgs = new WhyCommandArgs( + project.ProjectPath, + packageY.Id, + [inputFrameworksOption, projectFramework], + logger); + + // Act + var result = WhyCommandRunner.ExecuteCommand(whyCommandArgs); + + // Assert + var output = logger.ShowMessages(); + + Assert.Equal(ExitCodes.Success, result); + Assert.Contains($"The assets file {project.AssetsFileOutputPath} for project '{ProjectName}' does not contain a target for the specified input framework '{inputFrameworksOption}'.", output); + Assert.Contains($"Project '{ProjectName}' has the following dependency graph(s) for '{packageY.Id}'", output); + } + } +} diff --git a/test/NuGet.Core.Tests/NuGet.CommandLine.Xplat.Tests/NuGet.CommandLine.Xplat.Tests.csproj b/test/NuGet.Core.Tests/NuGet.CommandLine.Xplat.Tests/NuGet.CommandLine.Xplat.Tests.csproj index 490700276cb..b54bf812816 100644 --- a/test/NuGet.Core.Tests/NuGet.CommandLine.Xplat.Tests/NuGet.CommandLine.Xplat.Tests.csproj +++ b/test/NuGet.Core.Tests/NuGet.CommandLine.Xplat.Tests/NuGet.CommandLine.Xplat.Tests.csproj @@ -21,4 +21,12 @@ + + + + + + + + diff --git a/test/NuGet.Core.Tests/NuGet.CommandLine.Xplat.Tests/XPlatWhyUnitTests.cs b/test/NuGet.Core.Tests/NuGet.CommandLine.Xplat.Tests/XPlatWhyUnitTests.cs new file mode 100644 index 00000000000..944787748ef --- /dev/null +++ b/test/NuGet.Core.Tests/NuGet.CommandLine.Xplat.Tests/XPlatWhyUnitTests.cs @@ -0,0 +1,238 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Generic; +using System.Linq; +using NuGet.CommandLine.XPlat; +using NuGet.ProjectModel; +using NuGet.Test.Utility; +using Test.Utility; +using Xunit; + +namespace NuGet.CommandLine.Xplat.Tests +{ + public class XPlatWhyUnitTests + { + [Fact] + public void WhyCommand_DependencyGraphFinder_MultipleDependencyPathsForTargetPackage_AllPathsFound() + { + // Arrange + var lockFileFormat = new LockFileFormat(); + var lockFileContent = ProtocolUtility.GetResource("NuGet.CommandLine.Xplat.Tests.compiler.resources.DNW.Test.SampleProject1.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.Text.Json"; + var frameworks = new List(); + + // Act + var dependencyGraphs = DependencyGraphFinder.GetAllDependencyGraphsForTarget(assetsFile, targetPackage, frameworks); + + // Assert + + // direct dependency on target package is found + Assert.Contains(dependencyGraphs["net472"], dep => (dep.Id == "System.Text.Json") && (dep.Version == "8.0.0")); + + // transitive dependency from a top-level package is found, with the correct resolved version + Assert.Contains(dependencyGraphs["net472"].First(dep => dep.Id == "Azure.Core").Children, dep => (dep.Id == "System.Text.Json") && (dep.Version == "8.0.0")); + + // transitive dependency from a top-level project reference is found, with the correct resolved version + Assert.Contains(dependencyGraphs["net472"].First(dep => dep.Id == "DotnetNuGetWhyPackage").Children, dep => (dep.Id == "System.Text.Json") && (dep.Version == "8.0.0")); + } + + [Fact] + public void WhyCommand_DependencyGraphFinder_DependencyOnTargetProject_AllPathsFound() + { + // Arrange + var lockFileFormat = new LockFileFormat(); + var lockFileContent = ProtocolUtility.GetResource("NuGet.CommandLine.Xplat.Tests.compiler.resources.DNW.Test.SampleProject1.project.assets.json", GetType()); + var assetsFile = lockFileFormat.Parse(lockFileContent, "In Memory"); + + if (XunitAttributeUtility.CurrentPlatform == Platform.Linux || XunitAttributeUtility.CurrentPlatform == Platform.Darwin) + { + ConvertRelevantWindowsPathsToUnix(assetsFile); + } + + string targetPackage = "DotnetNuGetWhyPackage"; // project reference + var frameworks = new List(); + + // Act + var dependencyGraphs = DependencyGraphFinder.GetAllDependencyGraphsForTarget(assetsFile, targetPackage, frameworks); + + // Assert + + // direct dependency on target project reference is found + Assert.Contains(dependencyGraphs["net472"], dep => dep.Id == "DotnetNuGetWhyPackage"); + + // transitive dependency on target project reference is found + Assert.Contains(dependencyGraphs["net472"].First(dep => dep.Id == "CustomProjectName").Children, dep => dep.Id == "DotnetNuGetWhyPackage"); + } + + [Fact] + public void WhyCommand_DependencyGraphFinder_NoDependencyOnTargetPackage_ReturnsNullGraph() + { + // Arrange + var lockFileFormat = new LockFileFormat(); + var lockFileContent = ProtocolUtility.GetResource("NuGet.CommandLine.Xplat.Tests.compiler.resources.DNW.Test.SampleProject1.project.assets.json", GetType()); + var assetsFile = lockFileFormat.Parse(lockFileContent, "In Memory"); + + if (XunitAttributeUtility.CurrentPlatform == Platform.Linux || XunitAttributeUtility.CurrentPlatform == Platform.Darwin) + { + ConvertRelevantWindowsPathsToUnix(assetsFile); + } + + string targetPackage = "NotARealPackage"; + var frameworks = new List(); + + // Act + var dependencyGraphs = DependencyGraphFinder.GetAllDependencyGraphsForTarget(assetsFile, targetPackage, frameworks); + + // Assert + + // no paths found for any framework + Assert.Null(dependencyGraphs); + } + + [Fact] + public void WhyCommand_DependencyGraphFinder_DependencyOnTargetPackageForOnlyOneFramework_ReturnsCorrectGraphs() + { + // Arrange + var lockFileFormat = new LockFileFormat(); + var lockFileContent = ProtocolUtility.GetResource("NuGet.CommandLine.Xplat.Tests.compiler.resources.DNW.Test.SampleProject1.project.assets.json", GetType()); + var assetsFile = lockFileFormat.Parse(lockFileContent, "In Memory"); + + if (XunitAttributeUtility.CurrentPlatform == Platform.Linux || XunitAttributeUtility.CurrentPlatform == Platform.Darwin) + { + ConvertRelevantWindowsPathsToUnix(assetsFile); + } + + string targetPackage = "Azure.Core"; + var frameworks = new List(); + + // Act + var dependencyGraphs = DependencyGraphFinder.GetAllDependencyGraphsForTarget(assetsFile, targetPackage, frameworks); + + // Assert + + // paths found for one framework + Assert.Contains(dependencyGraphs["net472"], dep => dep.Id == "Azure.Core"); + + // no paths found for the other framework + Assert.Null(dependencyGraphs["net6.0"]); + } + + [Fact] + public void WhyCommand_DependencyGraphFinder_DependencyOnTargetPackage_FrameworkOptionSpecified_PathIsFound() + { + // Arrange + var lockFileFormat = new LockFileFormat(); + var lockFileContent = ProtocolUtility.GetResource("NuGet.CommandLine.Xplat.Tests.compiler.resources.DNW.Test.SampleProject1.project.assets.json", GetType()); + var assetsFile = lockFileFormat.Parse(lockFileContent, "In Memory"); + + if (XunitAttributeUtility.CurrentPlatform == Platform.Linux || XunitAttributeUtility.CurrentPlatform == Platform.Darwin) + { + ConvertRelevantWindowsPathsToUnix(assetsFile); + } + + string targetPackage = "Azure.Core"; + List frameworks = ["net472"]; + + // Act + var dependencyGraphs = DependencyGraphFinder.GetAllDependencyGraphsForTarget(assetsFile, targetPackage, frameworks); + + // Assert + + // Path found + Assert.Contains(dependencyGraphs["net472"], dep => dep.Id == "Azure.Core"); + } + + [Fact] + public void WhyCommand_DependencyGraphFinder_DependencyOnTargetPackageForOnlyOneFramework_DifferentFrameworkSpecified_ReturnsNullGraph() + { + // Arrange + var lockFileFormat = new LockFileFormat(); + var lockFileContent = ProtocolUtility.GetResource("NuGet.CommandLine.Xplat.Tests.compiler.resources.DNW.Test.SampleProject1.project.assets.json", GetType()); + var assetsFile = lockFileFormat.Parse(lockFileContent, "In Memory"); + + if (XunitAttributeUtility.CurrentPlatform == Platform.Linux || XunitAttributeUtility.CurrentPlatform == Platform.Darwin) + { + ConvertRelevantWindowsPathsToUnix(assetsFile); + } + + string targetPackage = "Azure.Core"; + List frameworks = ["net6.0"]; + + // Act + var dependencyGraphs = DependencyGraphFinder.GetAllDependencyGraphsForTarget(assetsFile, targetPackage, frameworks); + + // Assert + + // no paths found + Assert.Null(dependencyGraphs); + } + + [Fact] + public void WhyCommand_DependencyGraphFinder_DifferentCaseUsedForTargetPackageId_MatchesAreCaseInsensitive_AllPathsFound() + { + // Arrange + var lockFileFormat = new LockFileFormat(); + var lockFileContent = ProtocolUtility.GetResource("NuGet.CommandLine.Xplat.Tests.compiler.resources.DNW.Test.SampleProject1.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.text.jsoN"; + var frameworks = new List(); + + // Act + var dependencyGraphs = DependencyGraphFinder.GetAllDependencyGraphsForTarget(assetsFile, targetPackage, frameworks); + + // Assert + + // direct dependency on target package is found + Assert.Contains(dependencyGraphs["net472"], dep => (dep.Id == "System.Text.Json") && (dep.Version == "8.0.0")); + + // transitive dependency from a top-level package is found, with the correct resolved version + Assert.Contains(dependencyGraphs["net472"].First(dep => dep.Id == "Azure.Core").Children, dep => (dep.Id == "System.Text.Json") && (dep.Version == "8.0.0")); + + // transitive dependency from a top-level project reference is found, with the correct resolved version + Assert.Contains(dependencyGraphs["net472"].First(dep => dep.Id == "DotnetNuGetWhyPackage").Children, dep => (dep.Id == "System.Text.Json") && (dep.Version == "8.0.0")); + } + + private static void ConvertRelevantWindowsPathsToUnix(LockFile assetsFile) + { + assetsFile.PackageSpec.FilePath = ConvertWindowsPathToUnix(assetsFile.PackageSpec.FilePath); + + var projectLibraries = assetsFile.Libraries.Where(l => l.Type == "project"); + + foreach (var library in projectLibraries) + { + library.Path = ConvertWindowsPathToUnix(library.Path); + } + + var packageSpecTargets = assetsFile.PackageSpec.RestoreMetadata.TargetFrameworks; + + foreach (var target in packageSpecTargets) + { + var projectReferences = target.ProjectReferences; + foreach (var projectReference in projectReferences) + { + projectReference.ProjectPath = ConvertWindowsPathToUnix(projectReference.ProjectPath); + } + } + } + + private static string ConvertWindowsPathToUnix(string path) + { + char[] trimChars = ['C', ':']; + return path.TrimStart(trimChars).Replace("\\", "/"); + } + } +} diff --git a/test/NuGet.Core.Tests/NuGet.CommandLine.Xplat.Tests/compiler/resources/DNW.Test.SampleProject1.project.assets.json b/test/NuGet.Core.Tests/NuGet.CommandLine.Xplat.Tests/compiler/resources/DNW.Test.SampleProject1.project.assets.json new file mode 100644 index 00000000000..5113a5be6fa --- /dev/null +++ b/test/NuGet.Core.Tests/NuGet.CommandLine.Xplat.Tests/compiler/resources/DNW.Test.SampleProject1.project.assets.json @@ -0,0 +1,1629 @@ +{ + "version": 3, + "targets": { + ".NETFramework,Version=v4.7.2": { + "Azure.Core/1.38.0": { + "type": "package", + "dependencies": { + "Microsoft.Bcl.AsyncInterfaces": "1.1.1", + "System.ClientModel": "1.0.0", + "System.Diagnostics.DiagnosticSource": "6.0.1", + "System.Memory.Data": "1.0.2", + "System.Numerics.Vectors": "4.5.0", + "System.Text.Encodings.Web": "4.7.2", + "System.Text.Json": "4.7.2", + "System.Threading.Tasks.Extensions": "4.5.4" + }, + "frameworkAssemblies": [ + "System.Net.Http" + ], + "compile": { + "lib/net472/Azure.Core.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/net472/Azure.Core.dll": { + "related": ".xml" + } + } + }, + "Microsoft.Bcl.AsyncInterfaces/8.0.0": { + "type": "package", + "dependencies": { + "System.Threading.Tasks.Extensions": "4.5.4" + }, + "compile": { + "lib/net462/Microsoft.Bcl.AsyncInterfaces.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/net462/Microsoft.Bcl.AsyncInterfaces.dll": { + "related": ".xml" + } + }, + "build": { + "buildTransitive/net462/_._": {} + } + }, + "Microsoft.CSharp/4.0.1": { + "type": "package", + "frameworkAssemblies": [ + "Microsoft.CSharp" + ], + "compile": { + "ref/net45/_._": {} + }, + "runtime": { + "lib/net45/_._": {} + } + }, + "Serilog/3.1.0": { + "type": "package", + "dependencies": { + "System.Diagnostics.DiagnosticSource": "7.0.2" + }, + "frameworkAssemblies": [ + "Microsoft.CSharp", + "System", + "System.Core" + ], + "compile": { + "lib/net471/Serilog.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/net471/Serilog.dll": { + "related": ".xml" + } + } + }, + "System.Buffers/4.5.1": { + "type": "package", + "frameworkAssemblies": [ + "mscorlib" + ], + "compile": { + "ref/net45/System.Buffers.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/net461/System.Buffers.dll": { + "related": ".xml" + } + } + }, + "System.ClientModel/1.0.0": { + "type": "package", + "dependencies": { + "System.Memory.Data": "1.0.2", + "System.Text.Json": "4.7.2" + }, + "compile": { + "lib/netstandard2.0/System.ClientModel.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/System.ClientModel.dll": { + "related": ".xml" + } + } + }, + "System.Diagnostics.DiagnosticSource/7.0.2": { + "type": "package", + "dependencies": { + "System.Memory": "4.5.5", + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + }, + "compile": { + "lib/net462/System.Diagnostics.DiagnosticSource.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/net462/System.Diagnostics.DiagnosticSource.dll": { + "related": ".xml" + } + }, + "build": { + "buildTransitive/net462/_._": {} + } + }, + "System.Drawing.Common/4.7.1": { + "type": "package", + "frameworkAssemblies": [ + "System", + "System.Drawing", + "mscorlib" + ], + "compile": { + "ref/net461/System.Drawing.Common.dll": {} + }, + "runtime": { + "lib/net461/System.Drawing.Common.dll": {} + } + }, + "System.Memory/4.5.5": { + "type": "package", + "dependencies": { + "System.Buffers": "4.5.1", + "System.Numerics.Vectors": "4.5.0", + "System.Runtime.CompilerServices.Unsafe": "4.5.3" + }, + "frameworkAssemblies": [ + "System", + "mscorlib" + ], + "compile": { + "lib/net461/System.Memory.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/net461/System.Memory.dll": { + "related": ".xml" + } + } + }, + "System.Memory.Data/1.0.2": { + "type": "package", + "dependencies": { + "System.Text.Encodings.Web": "4.7.2", + "System.Text.Json": "4.6.0" + }, + "compile": { + "lib/net461/System.Memory.Data.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/net461/System.Memory.Data.dll": { + "related": ".xml" + } + } + }, + "System.Numerics.Vectors/4.5.0": { + "type": "package", + "frameworkAssemblies": [ + "System.Numerics", + "mscorlib" + ], + "compile": { + "ref/net46/System.Numerics.Vectors.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/net46/System.Numerics.Vectors.dll": { + "related": ".xml" + } + } + }, + "System.Runtime.CompilerServices.Unsafe/6.0.0": { + "type": "package", + "frameworkAssemblies": [ + "mscorlib" + ], + "compile": { + "lib/net461/System.Runtime.CompilerServices.Unsafe.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/net461/System.Runtime.CompilerServices.Unsafe.dll": { + "related": ".xml" + } + } + }, + "System.Text.Encodings.Web/8.0.0": { + "type": "package", + "dependencies": { + "System.Buffers": "4.5.1", + "System.Memory": "4.5.5", + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + }, + "compile": { + "lib/net462/System.Text.Encodings.Web.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/net462/System.Text.Encodings.Web.dll": { + "related": ".xml" + } + }, + "build": { + "buildTransitive/net462/_._": {} + } + }, + "System.Text.Json/8.0.0": { + "type": "package", + "dependencies": { + "Microsoft.Bcl.AsyncInterfaces": "8.0.0", + "System.Buffers": "4.5.1", + "System.Memory": "4.5.5", + "System.Runtime.CompilerServices.Unsafe": "6.0.0", + "System.Text.Encodings.Web": "8.0.0", + "System.Threading.Tasks.Extensions": "4.5.4", + "System.ValueTuple": "4.5.0" + }, + "compile": { + "lib/net462/System.Text.Json.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/net462/System.Text.Json.dll": { + "related": ".xml" + } + }, + "build": { + "buildTransitive/net462/System.Text.Json.targets": {} + } + }, + "System.Threading.Tasks.Extensions/4.5.4": { + "type": "package", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "4.5.3" + }, + "frameworkAssemblies": [ + "mscorlib" + ], + "compile": { + "lib/net461/System.Threading.Tasks.Extensions.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/net461/System.Threading.Tasks.Extensions.dll": { + "related": ".xml" + } + } + }, + "System.ValueTuple/4.5.0": { + "type": "package", + "frameworkAssemblies": [ + "mscorlib" + ], + "compile": { + "ref/net47/System.ValueTuple.dll": {} + }, + "runtime": { + "lib/net47/System.ValueTuple.dll": { + "related": ".xml" + } + } + }, + "CustomProjectName/1.0.0": { + "type": "project", + "framework": ".NETFramework,Version=v4.7.2", + "dependencies": { + "DotnetNuGetWhyPackage": "1.0.0" + }, + "compile": { + "bin/placeholder/CustomProjectName.dll": {} + }, + "runtime": { + "bin/placeholder/CustomProjectName.dll": {} + } + }, + "DotnetNuGetWhyPackage/1.0.0": { + "type": "project", + "framework": ".NETFramework,Version=v4.7.2", + "dependencies": { + "Azure.Core": "1.38.0", + "Microsoft.CSharp": "4.0.1", + "Serilog": "3.1.0", + "System.Drawing.Common": "4.7.1", + "System.Text.Json": "8.0.3" + }, + "compile": { + "bin/placeholder/DotnetNuGetWhyPackage.dll": {} + }, + "runtime": { + "bin/placeholder/DotnetNuGetWhyPackage.dll": {} + } + } + }, + "net6.0": { + "Microsoft.NETCore.Platforms/3.1.3": { + "type": "package", + "compile": { + "lib/netstandard1.0/_._": {} + }, + "runtime": { + "lib/netstandard1.0/_._": {} + } + }, + "Microsoft.Win32.SystemEvents/4.7.0": { + "type": "package", + "dependencies": { + "Microsoft.NETCore.Platforms": "3.1.0" + }, + "compile": { + "ref/netstandard2.0/_._": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.Win32.SystemEvents.dll": { + "related": ".xml" + } + }, + "runtimeTargets": { + "runtimes/win/lib/netcoreapp3.0/Microsoft.Win32.SystemEvents.dll": { + "assetType": "runtime", + "rid": "win" + } + } + }, + "Newtonsoft.Json/13.0.3": { + "type": "package", + "compile": { + "lib/net6.0/Newtonsoft.Json.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/net6.0/Newtonsoft.Json.dll": { + "related": ".xml" + } + } + }, + "NuGet.Common/6.9.1": { + "type": "package", + "dependencies": { + "NuGet.Frameworks": "6.9.1" + }, + "compile": { + "lib/netstandard2.0/NuGet.Common.dll": {} + }, + "runtime": { + "lib/netstandard2.0/NuGet.Common.dll": {} + } + }, + "NuGet.Configuration/6.9.1": { + "type": "package", + "dependencies": { + "NuGet.Common": "6.9.1", + "System.Security.Cryptography.ProtectedData": "4.4.0" + }, + "compile": { + "lib/netstandard2.0/NuGet.Configuration.dll": {} + }, + "runtime": { + "lib/netstandard2.0/NuGet.Configuration.dll": {} + } + }, + "NuGet.Frameworks/6.9.1": { + "type": "package", + "compile": { + "lib/netstandard2.0/NuGet.Frameworks.dll": {} + }, + "runtime": { + "lib/netstandard2.0/NuGet.Frameworks.dll": {} + } + }, + "NuGet.Packaging/6.9.1": { + "type": "package", + "dependencies": { + "Newtonsoft.Json": "13.0.3", + "NuGet.Configuration": "6.9.1", + "NuGet.Versioning": "6.9.1", + "System.Security.Cryptography.Pkcs": "6.0.4" + }, + "compile": { + "lib/net5.0/NuGet.Packaging.dll": {} + }, + "runtime": { + "lib/net5.0/NuGet.Packaging.dll": {} + } + }, + "NuGet.Protocol/6.9.1": { + "type": "package", + "dependencies": { + "NuGet.Packaging": "6.9.1" + }, + "compile": { + "lib/net5.0/NuGet.Protocol.dll": {} + }, + "runtime": { + "lib/net5.0/NuGet.Protocol.dll": {} + } + }, + "NuGet.Resolver/6.9.1": { + "type": "package", + "dependencies": { + "NuGet.Protocol": "6.9.1" + }, + "compile": { + "lib/net5.0/NuGet.Resolver.dll": {} + }, + "runtime": { + "lib/net5.0/NuGet.Resolver.dll": {} + } + }, + "NuGet.Versioning/6.9.1": { + "type": "package", + "compile": { + "lib/netstandard2.0/NuGet.Versioning.dll": {} + }, + "runtime": { + "lib/netstandard2.0/NuGet.Versioning.dll": {} + } + }, + "Serilog/3.1.0": { + "type": "package", + "compile": { + "lib/net6.0/Serilog.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/net6.0/Serilog.dll": { + "related": ".xml" + } + } + }, + "System.Drawing.Common/4.7.1": { + "type": "package", + "dependencies": { + "Microsoft.NETCore.Platforms": "3.1.3", + "Microsoft.Win32.SystemEvents": "4.7.0" + }, + "compile": { + "ref/netcoreapp3.0/System.Drawing.Common.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/System.Drawing.Common.dll": {} + }, + "runtimeTargets": { + "runtimes/unix/lib/netcoreapp3.0/System.Drawing.Common.dll": { + "assetType": "runtime", + "rid": "unix" + }, + "runtimes/win/lib/netcoreapp3.0/System.Drawing.Common.dll": { + "assetType": "runtime", + "rid": "win" + } + } + }, + "System.Formats.Asn1/6.0.0": { + "type": "package", + "compile": { + "lib/net6.0/System.Formats.Asn1.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/net6.0/System.Formats.Asn1.dll": { + "related": ".xml" + } + }, + "build": { + "buildTransitive/netcoreapp3.1/_._": {} + } + }, + "System.Runtime.CompilerServices.Unsafe/6.0.0": { + "type": "package", + "compile": { + "lib/net6.0/System.Runtime.CompilerServices.Unsafe.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/net6.0/System.Runtime.CompilerServices.Unsafe.dll": { + "related": ".xml" + } + }, + "build": { + "buildTransitive/netcoreapp3.1/_._": {} + } + }, + "System.Security.Cryptography.Pkcs/6.0.4": { + "type": "package", + "dependencies": { + "System.Formats.Asn1": "6.0.0" + }, + "compile": { + "lib/net6.0/System.Security.Cryptography.Pkcs.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/net6.0/System.Security.Cryptography.Pkcs.dll": { + "related": ".xml" + } + }, + "build": { + "buildTransitive/netcoreapp3.1/_._": {} + }, + "runtimeTargets": { + "runtimes/win/lib/net6.0/System.Security.Cryptography.Pkcs.dll": { + "assetType": "runtime", + "rid": "win" + } + } + }, + "System.Security.Cryptography.ProtectedData/4.4.0": { + "type": "package", + "compile": { + "ref/netstandard2.0/System.Security.Cryptography.ProtectedData.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/System.Security.Cryptography.ProtectedData.dll": {} + }, + "runtimeTargets": { + "runtimes/win/lib/netstandard2.0/System.Security.Cryptography.ProtectedData.dll": { + "assetType": "runtime", + "rid": "win" + } + } + }, + "System.Text.Encodings.Web/8.0.0": { + "type": "package", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + }, + "compile": { + "lib/net6.0/System.Text.Encodings.Web.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/net6.0/System.Text.Encodings.Web.dll": { + "related": ".xml" + } + }, + "build": { + "buildTransitive/net6.0/_._": {} + }, + "runtimeTargets": { + "runtimes/browser/lib/net6.0/System.Text.Encodings.Web.dll": { + "assetType": "runtime", + "rid": "browser" + } + } + }, + "System.Text.Json/8.0.0": { + "type": "package", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0", + "System.Text.Encodings.Web": "8.0.0" + }, + "compile": { + "lib/net6.0/System.Text.Json.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/net6.0/System.Text.Json.dll": { + "related": ".xml" + } + }, + "build": { + "buildTransitive/net6.0/System.Text.Json.targets": {} + } + }, + "CustomProjectName/1.0.0": { + "type": "project", + "framework": ".NETCoreApp,Version=v6.0", + "dependencies": { + "DotnetNuGetWhyPackage": "1.0.0" + }, + "compile": { + "bin/placeholder/CustomProjectName.dll": {} + }, + "runtime": { + "bin/placeholder/CustomProjectName.dll": {} + } + }, + "DotnetNuGetWhyPackage/1.0.0": { + "type": "project", + "framework": ".NETCoreApp,Version=v6.0", + "dependencies": { + "NuGet.Resolver": "6.9.1", + "Serilog": "3.1.0", + "System.Drawing.Common": "4.7.1", + "System.Text.Json": "8.0.3" + }, + "compile": { + "bin/placeholder/DotnetNuGetWhyPackage.dll": {} + }, + "runtime": { + "bin/placeholder/DotnetNuGetWhyPackage.dll": {} + } + } + } + }, + "libraries": { + "Azure.Core/1.38.0": { + "sha512": "IuEgCoVA0ef7E4pQtpC3+TkPbzaoQfa77HlfJDmfuaJUCVJmn7fT0izamZiryW5sYUFKizsftIxMkXKbgIcPMQ==", + "type": "package", + "path": "azure.core/1.38.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "CHANGELOG.md", + "README.md", + "azure.core.1.38.0.nupkg.sha512", + "azure.core.nuspec", + "azureicon.png", + "lib/net461/Azure.Core.dll", + "lib/net461/Azure.Core.xml", + "lib/net472/Azure.Core.dll", + "lib/net472/Azure.Core.xml", + "lib/net6.0/Azure.Core.dll", + "lib/net6.0/Azure.Core.xml", + "lib/netstandard2.0/Azure.Core.dll", + "lib/netstandard2.0/Azure.Core.xml" + ] + }, + "Microsoft.Bcl.AsyncInterfaces/8.0.0": { + "sha512": "3WA9q9yVqJp222P3x1wYIGDAkpjAku0TMUaaQV22g6L67AI0LdOIrVS7Ht2vJfLHGSPVuqN94vIr15qn+HEkHw==", + "type": "package", + "path": "microsoft.bcl.asyncinterfaces/8.0.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "LICENSE.TXT", + "PACKAGE.md", + "THIRD-PARTY-NOTICES.TXT", + "buildTransitive/net461/Microsoft.Bcl.AsyncInterfaces.targets", + "buildTransitive/net462/_._", + "lib/net462/Microsoft.Bcl.AsyncInterfaces.dll", + "lib/net462/Microsoft.Bcl.AsyncInterfaces.xml", + "lib/netstandard2.0/Microsoft.Bcl.AsyncInterfaces.dll", + "lib/netstandard2.0/Microsoft.Bcl.AsyncInterfaces.xml", + "lib/netstandard2.1/Microsoft.Bcl.AsyncInterfaces.dll", + "lib/netstandard2.1/Microsoft.Bcl.AsyncInterfaces.xml", + "microsoft.bcl.asyncinterfaces.8.0.0.nupkg.sha512", + "microsoft.bcl.asyncinterfaces.nuspec", + "useSharedDesignerContext.txt" + ] + }, + "Microsoft.CSharp/4.0.1": { + "sha512": "17h8b5mXa87XYKrrVqdgZ38JefSUqLChUQpXgSnpzsM0nDOhE40FTeNWOJ/YmySGV6tG6T8+hjz6vxbknHJr6A==", + "type": "package", + "path": "microsoft.csharp/4.0.1", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net45/_._", + "lib/netcore50/Microsoft.CSharp.dll", + "lib/netstandard1.3/Microsoft.CSharp.dll", + "lib/portable-net45+win8+wp8+wpa81/_._", + "lib/win8/_._", + "lib/wp80/_._", + "lib/wpa81/_._", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "microsoft.csharp.4.0.1.nupkg.sha512", + "microsoft.csharp.nuspec", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net45/_._", + "ref/netcore50/Microsoft.CSharp.dll", + "ref/netcore50/Microsoft.CSharp.xml", + "ref/netcore50/de/Microsoft.CSharp.xml", + "ref/netcore50/es/Microsoft.CSharp.xml", + "ref/netcore50/fr/Microsoft.CSharp.xml", + "ref/netcore50/it/Microsoft.CSharp.xml", + "ref/netcore50/ja/Microsoft.CSharp.xml", + "ref/netcore50/ko/Microsoft.CSharp.xml", + "ref/netcore50/ru/Microsoft.CSharp.xml", + "ref/netcore50/zh-hans/Microsoft.CSharp.xml", + "ref/netcore50/zh-hant/Microsoft.CSharp.xml", + "ref/netstandard1.0/Microsoft.CSharp.dll", + "ref/netstandard1.0/Microsoft.CSharp.xml", + "ref/netstandard1.0/de/Microsoft.CSharp.xml", + "ref/netstandard1.0/es/Microsoft.CSharp.xml", + "ref/netstandard1.0/fr/Microsoft.CSharp.xml", + "ref/netstandard1.0/it/Microsoft.CSharp.xml", + "ref/netstandard1.0/ja/Microsoft.CSharp.xml", + "ref/netstandard1.0/ko/Microsoft.CSharp.xml", + "ref/netstandard1.0/ru/Microsoft.CSharp.xml", + "ref/netstandard1.0/zh-hans/Microsoft.CSharp.xml", + "ref/netstandard1.0/zh-hant/Microsoft.CSharp.xml", + "ref/portable-net45+win8+wp8+wpa81/_._", + "ref/win8/_._", + "ref/wp80/_._", + "ref/wpa81/_._", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._" + ] + }, + "Microsoft.NETCore.Platforms/3.1.3": { + "sha512": "EHOcrXuq/ELOANMUzrpHmGIRlu7tVYyvGYsYUKLrTNMeQMTmdN97S6PP9W/NLD1WjqljGO+tapTS3XuLPlJ4QA==", + "type": "package", + "path": "microsoft.netcore.platforms/3.1.3", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "lib/netstandard1.0/_._", + "microsoft.netcore.platforms.3.1.3.nupkg.sha512", + "microsoft.netcore.platforms.nuspec", + "runtime.json", + "useSharedDesignerContext.txt", + "version.txt" + ] + }, + "Microsoft.Win32.SystemEvents/4.7.0": { + "sha512": "mtVirZr++rq+XCDITMUdnETD59XoeMxSpLRIII7JRI6Yj0LEDiO1pPn0ktlnIj12Ix8bfvQqQDMMIF9wC98oCA==", + "type": "package", + "path": "microsoft.win32.systemevents/4.7.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "lib/net461/Microsoft.Win32.SystemEvents.dll", + "lib/net461/Microsoft.Win32.SystemEvents.xml", + "lib/netstandard2.0/Microsoft.Win32.SystemEvents.dll", + "lib/netstandard2.0/Microsoft.Win32.SystemEvents.xml", + "microsoft.win32.systemevents.4.7.0.nupkg.sha512", + "microsoft.win32.systemevents.nuspec", + "ref/net461/Microsoft.Win32.SystemEvents.dll", + "ref/net461/Microsoft.Win32.SystemEvents.xml", + "ref/net472/Microsoft.Win32.SystemEvents.dll", + "ref/net472/Microsoft.Win32.SystemEvents.xml", + "ref/netstandard2.0/Microsoft.Win32.SystemEvents.dll", + "ref/netstandard2.0/Microsoft.Win32.SystemEvents.xml", + "runtimes/win/lib/netcoreapp2.0/Microsoft.Win32.SystemEvents.dll", + "runtimes/win/lib/netcoreapp2.0/Microsoft.Win32.SystemEvents.xml", + "runtimes/win/lib/netcoreapp3.0/Microsoft.Win32.SystemEvents.dll", + "runtimes/win/lib/netcoreapp3.0/Microsoft.Win32.SystemEvents.xml", + "useSharedDesignerContext.txt", + "version.txt" + ] + }, + "Newtonsoft.Json/13.0.3": { + "sha512": "HrC5BXdl00IP9zeV+0Z848QWPAoCr9P3bDEZguI+gkLcBKAOxix/tLEAAHC+UvDNPv4a2d18lOReHMOagPa+zQ==", + "type": "package", + "path": "newtonsoft.json/13.0.3", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "LICENSE.md", + "README.md", + "lib/net20/Newtonsoft.Json.dll", + "lib/net20/Newtonsoft.Json.xml", + "lib/net35/Newtonsoft.Json.dll", + "lib/net35/Newtonsoft.Json.xml", + "lib/net40/Newtonsoft.Json.dll", + "lib/net40/Newtonsoft.Json.xml", + "lib/net45/Newtonsoft.Json.dll", + "lib/net45/Newtonsoft.Json.xml", + "lib/net6.0/Newtonsoft.Json.dll", + "lib/net6.0/Newtonsoft.Json.xml", + "lib/netstandard1.0/Newtonsoft.Json.dll", + "lib/netstandard1.0/Newtonsoft.Json.xml", + "lib/netstandard1.3/Newtonsoft.Json.dll", + "lib/netstandard1.3/Newtonsoft.Json.xml", + "lib/netstandard2.0/Newtonsoft.Json.dll", + "lib/netstandard2.0/Newtonsoft.Json.xml", + "newtonsoft.json.13.0.3.nupkg.sha512", + "newtonsoft.json.nuspec", + "packageIcon.png" + ] + }, + "NuGet.Common/6.9.1": { + "sha512": "FbuWZBjQ1NJXBDqCwSddN2yvw3Plq3sTCIh0nc66Hu8jrNr+BOaxlKZv78jvJ+pSy8BvurYOdF9sl9KoORjrtg==", + "type": "package", + "path": "nuget.common/6.9.1", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "README.md", + "icon.png", + "lib/net472/NuGet.Common.dll", + "lib/netstandard2.0/NuGet.Common.dll", + "nuget.common.6.9.1.nupkg.sha512", + "nuget.common.nuspec" + ] + }, + "NuGet.Configuration/6.9.1": { + "sha512": "GM06pcUzWdNsizeGciqCjAhryfI1F/rQPETLDF+8pDRgzVpA+wKAR01/4aFU+IXzugnQ9LqOb5YyCRuR1OVZiQ==", + "type": "package", + "path": "nuget.configuration/6.9.1", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "README.md", + "icon.png", + "lib/net472/NuGet.Configuration.dll", + "lib/netstandard2.0/NuGet.Configuration.dll", + "nuget.configuration.6.9.1.nupkg.sha512", + "nuget.configuration.nuspec" + ] + }, + "NuGet.Frameworks/6.9.1": { + "sha512": "DaKh3lenPUvzGccPkbI97BIvA27z+/UsL3ankfoZlX/4vBVDK5N1sheFTQ+GuJf+IgSzsJz/A21SPUpQLHwUtA==", + "type": "package", + "path": "nuget.frameworks/6.9.1", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "README.md", + "icon.png", + "lib/net472/NuGet.Frameworks.dll", + "lib/netstandard2.0/NuGet.Frameworks.dll", + "nuget.frameworks.6.9.1.nupkg.sha512", + "nuget.frameworks.nuspec" + ] + }, + "NuGet.Packaging/6.9.1": { + "sha512": "6FyasOxKInCELJ+pGy8f17ub9st6ofFeNcBNTo7CRiPJlxyhJfKGKNpfe3HHYwvnZhc3Vdfr0kSR+f1BVGDuTA==", + "type": "package", + "path": "nuget.packaging/6.9.1", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "README.md", + "icon.png", + "lib/net472/NuGet.Packaging.dll", + "lib/net5.0/NuGet.Packaging.dll", + "lib/netstandard2.0/NuGet.Packaging.dll", + "nuget.packaging.6.9.1.nupkg.sha512", + "nuget.packaging.nuspec" + ] + }, + "NuGet.Protocol/6.9.1": { + "sha512": "h3bdjqUY4jvwM02D/7QM4FR8x/bbf4Pyjrc1Etw7an2OrWKPUSx0vJPdapKzioxIw7GXl/aVUM/DCeIc3S9brA==", + "type": "package", + "path": "nuget.protocol/6.9.1", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "README.md", + "icon.png", + "lib/net472/NuGet.Protocol.dll", + "lib/net5.0/NuGet.Protocol.dll", + "lib/netstandard2.0/NuGet.Protocol.dll", + "nuget.protocol.6.9.1.nupkg.sha512", + "nuget.protocol.nuspec" + ] + }, + "NuGet.Resolver/6.9.1": { + "sha512": "Y/N0ACMIC3zAECrF94mjeS+kLV444UALGcCmixSWNs48sPorV36VISpdmq+qjCajpUFXIriFFCWOQ4hqGGR+4g==", + "type": "package", + "path": "nuget.resolver/6.9.1", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "README.md", + "icon.png", + "lib/net472/NuGet.Resolver.dll", + "lib/net5.0/NuGet.Resolver.dll", + "lib/netstandard2.0/NuGet.Resolver.dll", + "nuget.resolver.6.9.1.nupkg.sha512", + "nuget.resolver.nuspec" + ] + }, + "NuGet.Versioning/6.9.1": { + "sha512": "ypnSvEtpNGo48bAWn95J1oHChycCXcevFSbn53fqzLxlXFSZP7dawu8p/7mHAfGufZQSV2sBpW80XQGIfXO8kQ==", + "type": "package", + "path": "nuget.versioning/6.9.1", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "README.md", + "icon.png", + "lib/net472/NuGet.Versioning.dll", + "lib/netstandard2.0/NuGet.Versioning.dll", + "nuget.versioning.6.9.1.nupkg.sha512", + "nuget.versioning.nuspec" + ] + }, + "Serilog/3.1.0": { + "sha512": "UPJGG8Hz12obhtAELHb0q83j0YpO1vGCypUbH0P4wMZnrpcqmrSLhHkZ/4Ojc+iNVpLwZ/wPBVC3lwSzzoZ/MQ==", + "type": "package", + "path": "serilog/3.1.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "README.md", + "icon.png", + "lib/net462/Serilog.dll", + "lib/net462/Serilog.xml", + "lib/net471/Serilog.dll", + "lib/net471/Serilog.xml", + "lib/net5.0/Serilog.dll", + "lib/net5.0/Serilog.xml", + "lib/net6.0/Serilog.dll", + "lib/net6.0/Serilog.xml", + "lib/net7.0/Serilog.dll", + "lib/net7.0/Serilog.xml", + "lib/netstandard2.0/Serilog.dll", + "lib/netstandard2.0/Serilog.xml", + "lib/netstandard2.1/Serilog.dll", + "lib/netstandard2.1/Serilog.xml", + "serilog.3.1.0.nupkg.sha512", + "serilog.nuspec" + ] + }, + "System.Buffers/4.5.1": { + "sha512": "Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg==", + "type": "package", + "path": "system.buffers/4.5.1", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "lib/net461/System.Buffers.dll", + "lib/net461/System.Buffers.xml", + "lib/netcoreapp2.0/_._", + "lib/netstandard1.1/System.Buffers.dll", + "lib/netstandard1.1/System.Buffers.xml", + "lib/netstandard2.0/System.Buffers.dll", + "lib/netstandard2.0/System.Buffers.xml", + "lib/uap10.0.16299/_._", + "ref/net45/System.Buffers.dll", + "ref/net45/System.Buffers.xml", + "ref/netcoreapp2.0/_._", + "ref/netstandard1.1/System.Buffers.dll", + "ref/netstandard1.1/System.Buffers.xml", + "ref/netstandard2.0/System.Buffers.dll", + "ref/netstandard2.0/System.Buffers.xml", + "ref/uap10.0.16299/_._", + "system.buffers.4.5.1.nupkg.sha512", + "system.buffers.nuspec", + "useSharedDesignerContext.txt", + "version.txt" + ] + }, + "System.ClientModel/1.0.0": { + "sha512": "I3CVkvxeqFYjIVEP59DnjbeoGNfo/+SZrCLpRz2v/g0gpCHaEMPtWSY0s9k/7jR1rAsLNg2z2u1JRB76tPjnIw==", + "type": "package", + "path": "system.clientmodel/1.0.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "CHANGELOG.md", + "DotNetPackageIcon.png", + "README.md", + "lib/net6.0/System.ClientModel.dll", + "lib/net6.0/System.ClientModel.xml", + "lib/netstandard2.0/System.ClientModel.dll", + "lib/netstandard2.0/System.ClientModel.xml", + "system.clientmodel.1.0.0.nupkg.sha512", + "system.clientmodel.nuspec" + ] + }, + "System.Diagnostics.DiagnosticSource/7.0.2": { + "sha512": "hYr3I9N9811e0Bjf2WNwAGGyTuAFbbTgX1RPLt/3Wbm68x3IGcX5Cl75CMmgT6WlNwLQ2tCCWfqYPpypjaf2xA==", + "type": "package", + "path": "system.diagnostics.diagnosticsource/7.0.2", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "buildTransitive/net461/System.Diagnostics.DiagnosticSource.targets", + "buildTransitive/net462/_._", + "buildTransitive/net6.0/_._", + "buildTransitive/netcoreapp2.0/System.Diagnostics.DiagnosticSource.targets", + "lib/net462/System.Diagnostics.DiagnosticSource.dll", + "lib/net462/System.Diagnostics.DiagnosticSource.xml", + "lib/net6.0/System.Diagnostics.DiagnosticSource.dll", + "lib/net6.0/System.Diagnostics.DiagnosticSource.xml", + "lib/net7.0/System.Diagnostics.DiagnosticSource.dll", + "lib/net7.0/System.Diagnostics.DiagnosticSource.xml", + "lib/netstandard2.0/System.Diagnostics.DiagnosticSource.dll", + "lib/netstandard2.0/System.Diagnostics.DiagnosticSource.xml", + "system.diagnostics.diagnosticsource.7.0.2.nupkg.sha512", + "system.diagnostics.diagnosticsource.nuspec", + "useSharedDesignerContext.txt" + ] + }, + "System.Drawing.Common/4.7.1": { + "sha512": "fnb3qshElEe2lgIMBpc+Pww4xAjqa23yAAqTrtS9RX8uvnjoMJPTDbAVik2jYaOnFs3QpFMujYmAq0VS9101zA==", + "type": "package", + "path": "system.drawing.common/4.7.1", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net461/System.Drawing.Common.dll", + "lib/netstandard2.0/System.Drawing.Common.dll", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net461/System.Drawing.Common.dll", + "ref/netcoreapp3.0/System.Drawing.Common.dll", + "ref/netcoreapp3.0/System.Drawing.Common.xml", + "ref/netstandard2.0/System.Drawing.Common.dll", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "runtimes/unix/lib/netcoreapp2.0/System.Drawing.Common.dll", + "runtimes/unix/lib/netcoreapp3.0/System.Drawing.Common.dll", + "runtimes/unix/lib/netcoreapp3.0/System.Drawing.Common.xml", + "runtimes/win/lib/netcoreapp2.0/System.Drawing.Common.dll", + "runtimes/win/lib/netcoreapp3.0/System.Drawing.Common.dll", + "runtimes/win/lib/netcoreapp3.0/System.Drawing.Common.xml", + "system.drawing.common.4.7.1.nupkg.sha512", + "system.drawing.common.nuspec", + "useSharedDesignerContext.txt", + "version.txt" + ] + }, + "System.Formats.Asn1/6.0.0": { + "sha512": "T6fD00dQ3NTbPDy31m4eQUwKW84s03z0N2C8HpOklyeaDgaJPa/TexP4/SkORMSOwc7WhKifnA6Ya33AkzmafA==", + "type": "package", + "path": "system.formats.asn1/6.0.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "buildTransitive/netcoreapp2.0/System.Formats.Asn1.targets", + "buildTransitive/netcoreapp3.1/_._", + "lib/net461/System.Formats.Asn1.dll", + "lib/net461/System.Formats.Asn1.xml", + "lib/net6.0/System.Formats.Asn1.dll", + "lib/net6.0/System.Formats.Asn1.xml", + "lib/netstandard2.0/System.Formats.Asn1.dll", + "lib/netstandard2.0/System.Formats.Asn1.xml", + "system.formats.asn1.6.0.0.nupkg.sha512", + "system.formats.asn1.nuspec", + "useSharedDesignerContext.txt" + ] + }, + "System.Memory/4.5.5": { + "sha512": "XIWiDvKPXaTveaB7HVganDlOCRoj03l+jrwNvcge/t8vhGYKvqV+dMv6G4SAX2NoNmN0wZfVPTAlFwZcZvVOUw==", + "type": "package", + "path": "system.memory/4.5.5", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "lib/net461/System.Memory.dll", + "lib/net461/System.Memory.xml", + "lib/netcoreapp2.1/_._", + "lib/netstandard1.1/System.Memory.dll", + "lib/netstandard1.1/System.Memory.xml", + "lib/netstandard2.0/System.Memory.dll", + "lib/netstandard2.0/System.Memory.xml", + "ref/netcoreapp2.1/_._", + "system.memory.4.5.5.nupkg.sha512", + "system.memory.nuspec", + "useSharedDesignerContext.txt", + "version.txt" + ] + }, + "System.Memory.Data/1.0.2": { + "sha512": "JGkzeqgBsiZwKJZ1IxPNsDFZDhUvuEdX8L8BDC8N3KOj+6zMcNU28CNN59TpZE/VJYy9cP+5M+sbxtWJx3/xtw==", + "type": "package", + "path": "system.memory.data/1.0.2", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "CHANGELOG.md", + "DotNetPackageIcon.png", + "README.md", + "lib/net461/System.Memory.Data.dll", + "lib/net461/System.Memory.Data.xml", + "lib/netstandard2.0/System.Memory.Data.dll", + "lib/netstandard2.0/System.Memory.Data.xml", + "system.memory.data.1.0.2.nupkg.sha512", + "system.memory.data.nuspec" + ] + }, + "System.Numerics.Vectors/4.5.0": { + "sha512": "QQTlPTl06J/iiDbJCiepZ4H//BVraReU4O4EoRw1U02H5TLUIT7xn3GnDp9AXPSlJUDyFs4uWjWafNX6WrAojQ==", + "type": "package", + "path": "system.numerics.vectors/4.5.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net46/System.Numerics.Vectors.dll", + "lib/net46/System.Numerics.Vectors.xml", + "lib/netcoreapp2.0/_._", + "lib/netstandard1.0/System.Numerics.Vectors.dll", + "lib/netstandard1.0/System.Numerics.Vectors.xml", + "lib/netstandard2.0/System.Numerics.Vectors.dll", + "lib/netstandard2.0/System.Numerics.Vectors.xml", + "lib/portable-net45+win8+wp8+wpa81/System.Numerics.Vectors.dll", + "lib/portable-net45+win8+wp8+wpa81/System.Numerics.Vectors.xml", + "lib/uap10.0.16299/_._", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net45/System.Numerics.Vectors.dll", + "ref/net45/System.Numerics.Vectors.xml", + "ref/net46/System.Numerics.Vectors.dll", + "ref/net46/System.Numerics.Vectors.xml", + "ref/netcoreapp2.0/_._", + "ref/netstandard1.0/System.Numerics.Vectors.dll", + "ref/netstandard1.0/System.Numerics.Vectors.xml", + "ref/netstandard2.0/System.Numerics.Vectors.dll", + "ref/netstandard2.0/System.Numerics.Vectors.xml", + "ref/uap10.0.16299/_._", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "system.numerics.vectors.4.5.0.nupkg.sha512", + "system.numerics.vectors.nuspec", + "useSharedDesignerContext.txt", + "version.txt" + ] + }, + "System.Runtime.CompilerServices.Unsafe/6.0.0": { + "sha512": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg==", + "type": "package", + "path": "system.runtime.compilerservices.unsafe/6.0.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "buildTransitive/netcoreapp2.0/System.Runtime.CompilerServices.Unsafe.targets", + "buildTransitive/netcoreapp3.1/_._", + "lib/net461/System.Runtime.CompilerServices.Unsafe.dll", + "lib/net461/System.Runtime.CompilerServices.Unsafe.xml", + "lib/net6.0/System.Runtime.CompilerServices.Unsafe.dll", + "lib/net6.0/System.Runtime.CompilerServices.Unsafe.xml", + "lib/netcoreapp3.1/System.Runtime.CompilerServices.Unsafe.dll", + "lib/netcoreapp3.1/System.Runtime.CompilerServices.Unsafe.xml", + "lib/netstandard2.0/System.Runtime.CompilerServices.Unsafe.dll", + "lib/netstandard2.0/System.Runtime.CompilerServices.Unsafe.xml", + "system.runtime.compilerservices.unsafe.6.0.0.nupkg.sha512", + "system.runtime.compilerservices.unsafe.nuspec", + "useSharedDesignerContext.txt" + ] + }, + "System.Security.Cryptography.Pkcs/6.0.4": { + "sha512": "LGbXi1oUJ9QgCNGXRO9ndzBL/GZgANcsURpMhNR8uO+rca47SZmciS3RSQUvlQRwK3QHZSHNOXzoMUASKA+Anw==", + "type": "package", + "path": "system.security.cryptography.pkcs/6.0.4", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "buildTransitive/netcoreapp2.0/System.Security.Cryptography.Pkcs.targets", + "buildTransitive/netcoreapp3.1/_._", + "lib/net461/System.Security.Cryptography.Pkcs.dll", + "lib/net461/System.Security.Cryptography.Pkcs.xml", + "lib/net6.0/System.Security.Cryptography.Pkcs.dll", + "lib/net6.0/System.Security.Cryptography.Pkcs.xml", + "lib/netcoreapp3.1/System.Security.Cryptography.Pkcs.dll", + "lib/netcoreapp3.1/System.Security.Cryptography.Pkcs.xml", + "lib/netstandard2.0/System.Security.Cryptography.Pkcs.dll", + "lib/netstandard2.0/System.Security.Cryptography.Pkcs.xml", + "lib/netstandard2.1/System.Security.Cryptography.Pkcs.dll", + "lib/netstandard2.1/System.Security.Cryptography.Pkcs.xml", + "runtimes/win/lib/net461/System.Security.Cryptography.Pkcs.dll", + "runtimes/win/lib/net461/System.Security.Cryptography.Pkcs.xml", + "runtimes/win/lib/net6.0/System.Security.Cryptography.Pkcs.dll", + "runtimes/win/lib/net6.0/System.Security.Cryptography.Pkcs.xml", + "runtimes/win/lib/netcoreapp3.1/System.Security.Cryptography.Pkcs.dll", + "runtimes/win/lib/netcoreapp3.1/System.Security.Cryptography.Pkcs.xml", + "runtimes/win/lib/netstandard2.0/System.Security.Cryptography.Pkcs.dll", + "runtimes/win/lib/netstandard2.0/System.Security.Cryptography.Pkcs.xml", + "runtimes/win/lib/netstandard2.1/System.Security.Cryptography.Pkcs.dll", + "runtimes/win/lib/netstandard2.1/System.Security.Cryptography.Pkcs.xml", + "system.security.cryptography.pkcs.6.0.4.nupkg.sha512", + "system.security.cryptography.pkcs.nuspec", + "useSharedDesignerContext.txt" + ] + }, + "System.Security.Cryptography.ProtectedData/4.4.0": { + "sha512": "cJV7ScGW7EhatRsjehfvvYVBvtiSMKgN8bOVI0bQhnF5bU7vnHVIsH49Kva7i7GWaWYvmEzkYVk1TC+gZYBEog==", + "type": "package", + "path": "system.security.cryptography.protecteddata/4.4.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net46/System.Security.Cryptography.ProtectedData.dll", + "lib/net461/System.Security.Cryptography.ProtectedData.dll", + "lib/netstandard1.3/System.Security.Cryptography.ProtectedData.dll", + "lib/netstandard2.0/System.Security.Cryptography.ProtectedData.dll", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net46/System.Security.Cryptography.ProtectedData.dll", + "ref/net461/System.Security.Cryptography.ProtectedData.dll", + "ref/net461/System.Security.Cryptography.ProtectedData.xml", + "ref/netstandard1.3/System.Security.Cryptography.ProtectedData.dll", + "ref/netstandard2.0/System.Security.Cryptography.ProtectedData.dll", + "ref/netstandard2.0/System.Security.Cryptography.ProtectedData.xml", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "runtimes/win/lib/net46/System.Security.Cryptography.ProtectedData.dll", + "runtimes/win/lib/net461/System.Security.Cryptography.ProtectedData.dll", + "runtimes/win/lib/netstandard1.3/System.Security.Cryptography.ProtectedData.dll", + "runtimes/win/lib/netstandard2.0/System.Security.Cryptography.ProtectedData.dll", + "system.security.cryptography.protecteddata.4.4.0.nupkg.sha512", + "system.security.cryptography.protecteddata.nuspec", + "useSharedDesignerContext.txt", + "version.txt" + ] + }, + "System.Text.Encodings.Web/8.0.0": { + "sha512": "yev/k9GHAEGx2Rg3/tU6MQh4HGBXJs70y7j1LaM1i/ER9po+6nnQ6RRqTJn1E7Xu0fbIFK80Nh5EoODxrbxwBQ==", + "type": "package", + "path": "system.text.encodings.web/8.0.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "buildTransitive/net461/System.Text.Encodings.Web.targets", + "buildTransitive/net462/_._", + "buildTransitive/net6.0/_._", + "buildTransitive/netcoreapp2.0/System.Text.Encodings.Web.targets", + "lib/net462/System.Text.Encodings.Web.dll", + "lib/net462/System.Text.Encodings.Web.xml", + "lib/net6.0/System.Text.Encodings.Web.dll", + "lib/net6.0/System.Text.Encodings.Web.xml", + "lib/net7.0/System.Text.Encodings.Web.dll", + "lib/net7.0/System.Text.Encodings.Web.xml", + "lib/net8.0/System.Text.Encodings.Web.dll", + "lib/net8.0/System.Text.Encodings.Web.xml", + "lib/netstandard2.0/System.Text.Encodings.Web.dll", + "lib/netstandard2.0/System.Text.Encodings.Web.xml", + "runtimes/browser/lib/net6.0/System.Text.Encodings.Web.dll", + "runtimes/browser/lib/net6.0/System.Text.Encodings.Web.xml", + "runtimes/browser/lib/net7.0/System.Text.Encodings.Web.dll", + "runtimes/browser/lib/net7.0/System.Text.Encodings.Web.xml", + "runtimes/browser/lib/net8.0/System.Text.Encodings.Web.dll", + "runtimes/browser/lib/net8.0/System.Text.Encodings.Web.xml", + "system.text.encodings.web.8.0.0.nupkg.sha512", + "system.text.encodings.web.nuspec", + "useSharedDesignerContext.txt" + ] + }, + "System.Text.Json/8.0.0": { + "sha512": "OdrZO2WjkiEG6ajEFRABTRCi/wuXQPxeV6g8xvUJqdxMvvuCCEk86zPla8UiIQJz3durtUEbNyY/3lIhS0yZvQ==", + "type": "package", + "path": "system.text.json/8.0.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "LICENSE.TXT", + "PACKAGE.md", + "THIRD-PARTY-NOTICES.TXT", + "analyzers/dotnet/roslyn3.11/cs/System.Text.Json.SourceGeneration.dll", + "analyzers/dotnet/roslyn3.11/cs/cs/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn3.11/cs/de/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn3.11/cs/es/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn3.11/cs/fr/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn3.11/cs/it/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn3.11/cs/ja/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn3.11/cs/ko/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn3.11/cs/pl/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn3.11/cs/pt-BR/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn3.11/cs/ru/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn3.11/cs/tr/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn3.11/cs/zh-Hans/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn3.11/cs/zh-Hant/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/System.Text.Json.SourceGeneration.dll", + "analyzers/dotnet/roslyn4.0/cs/cs/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/de/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/es/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/fr/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/it/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/ja/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/ko/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/pl/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/pt-BR/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/ru/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/tr/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/zh-Hans/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/zh-Hant/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/System.Text.Json.SourceGeneration.dll", + "analyzers/dotnet/roslyn4.4/cs/cs/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/de/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/es/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/fr/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/it/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/ja/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/ko/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/pl/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/pt-BR/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/ru/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/tr/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/zh-Hans/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/zh-Hant/System.Text.Json.SourceGeneration.resources.dll", + "buildTransitive/net461/System.Text.Json.targets", + "buildTransitive/net462/System.Text.Json.targets", + "buildTransitive/net6.0/System.Text.Json.targets", + "buildTransitive/netcoreapp2.0/System.Text.Json.targets", + "buildTransitive/netstandard2.0/System.Text.Json.targets", + "lib/net462/System.Text.Json.dll", + "lib/net462/System.Text.Json.xml", + "lib/net6.0/System.Text.Json.dll", + "lib/net6.0/System.Text.Json.xml", + "lib/net7.0/System.Text.Json.dll", + "lib/net7.0/System.Text.Json.xml", + "lib/net8.0/System.Text.Json.dll", + "lib/net8.0/System.Text.Json.xml", + "lib/netstandard2.0/System.Text.Json.dll", + "lib/netstandard2.0/System.Text.Json.xml", + "system.text.json.8.0.0.nupkg.sha512", + "system.text.json.nuspec", + "useSharedDesignerContext.txt" + ] + }, + "System.Threading.Tasks.Extensions/4.5.4": { + "sha512": "zteT+G8xuGu6mS+mzDzYXbzS7rd3K6Fjb9RiZlYlJPam2/hU7JCBZBVEcywNuR+oZ1ncTvc/cq0faRr3P01OVg==", + "type": "package", + "path": "system.threading.tasks.extensions/4.5.4", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net461/System.Threading.Tasks.Extensions.dll", + "lib/net461/System.Threading.Tasks.Extensions.xml", + "lib/netcoreapp2.1/_._", + "lib/netstandard1.0/System.Threading.Tasks.Extensions.dll", + "lib/netstandard1.0/System.Threading.Tasks.Extensions.xml", + "lib/netstandard2.0/System.Threading.Tasks.Extensions.dll", + "lib/netstandard2.0/System.Threading.Tasks.Extensions.xml", + "lib/portable-net45+win8+wp8+wpa81/System.Threading.Tasks.Extensions.dll", + "lib/portable-net45+win8+wp8+wpa81/System.Threading.Tasks.Extensions.xml", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/netcoreapp2.1/_._", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "system.threading.tasks.extensions.4.5.4.nupkg.sha512", + "system.threading.tasks.extensions.nuspec", + "useSharedDesignerContext.txt", + "version.txt" + ] + }, + "System.ValueTuple/4.5.0": { + "sha512": "okurQJO6NRE/apDIP23ajJ0hpiNmJ+f0BwOlB/cSqTLQlw5upkf+5+96+iG2Jw40G1fCVCyPz/FhIABUjMR+RQ==", + "type": "package", + "path": "system.valuetuple/4.5.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net461/System.ValueTuple.dll", + "lib/net461/System.ValueTuple.xml", + "lib/net47/System.ValueTuple.dll", + "lib/net47/System.ValueTuple.xml", + "lib/netcoreapp2.0/_._", + "lib/netstandard1.0/System.ValueTuple.dll", + "lib/netstandard1.0/System.ValueTuple.xml", + "lib/netstandard2.0/_._", + "lib/portable-net40+sl4+win8+wp8/System.ValueTuple.dll", + "lib/portable-net40+sl4+win8+wp8/System.ValueTuple.xml", + "lib/uap10.0.16299/_._", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net461/System.ValueTuple.dll", + "ref/net47/System.ValueTuple.dll", + "ref/netcoreapp2.0/_._", + "ref/netstandard2.0/_._", + "ref/portable-net40+sl4+win8+wp8/System.ValueTuple.dll", + "ref/uap10.0.16299/_._", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "system.valuetuple.4.5.0.nupkg.sha512", + "system.valuetuple.nuspec", + "useSharedDesignerContext.txt", + "version.txt" + ] + }, + "CustomProjectName/1.0.0": { + "type": "project", + "path": "../TestingProjectReferences/TestingProjectReferences.csproj", + "msbuildProject": "../TestingProjectReferences/TestingProjectReferences.csproj" + }, + "DotnetNuGetWhyPackage/1.0.0": { + "type": "project", + "path": "../DotnetNuGetWhyPackage/DotnetNuGetWhyPackage.csproj", + "msbuildProject": "../DotnetNuGetWhyPackage/DotnetNuGetWhyPackage.csproj" + } + }, + "projectFileDependencyGroups": { + ".NETFramework,Version=v4.7.2": [ + "Azure.Core >= 1.38.0", + "CustomProjectName >= 1.0.0", + "DotnetNuGetWhyPackage >= 1.0.0", + "System.Text.Json >= 8.0.0" + ], + "net6.0": [ + "CustomProjectName >= 1.0.0", + "DotnetNuGetWhyPackage >= 1.0.0", + "NuGet.Resolver >= 6.9.1", + "System.Text.Json >= 8.0.0" + ] + }, + "packageFolders": { + "C:\\Users\\advaytandon\\.nuget\\packages\\": {} + }, + "project": { + "version": "1.0.0", + "restore": { + "projectUniqueName": "C:\\Users\\advaytandon\\source\\packages\\DotnetNuGetWhyPackage\\DNW.Test.SampleProject1\\DNW.Test.SampleProject1.csproj", + "projectName": "DNW.Test.SampleProject1", + "projectPath": "C:\\Users\\advaytandon\\source\\packages\\DotnetNuGetWhyPackage\\DNW.Test.SampleProject1\\DNW.Test.SampleProject1.csproj", + "packagesPath": "C:\\Users\\advaytandon\\.nuget\\packages\\", + "outputPath": "C:\\Users\\advaytandon\\source\\packages\\DotnetNuGetWhyPackage\\DNW.Test.SampleProject1\\obj\\", + "projectStyle": "PackageReference", + "crossTargeting": true, + "configFilePaths": [ + "C:\\Users\\advaytandon\\AppData\\Roaming\\NuGet\\NuGet.Config", + "C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config" + ], + "originalTargetFrameworks": [ + "net472", + "net6.0" + ], + "sources": { + "C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {}, + "C:\\Program Files\\dotnet\\library-packs": {}, + "https://api.nuget.org/v3/index.json": {} + }, + "frameworks": { + "net6.0": { + "targetAlias": "net6.0", + "projectReferences": { + "C:\\Users\\advaytandon\\source\\packages\\DotnetNuGetWhyPackage\\DotnetNuGetWhyPackage\\DotnetNuGetWhyPackage.csproj": { + "projectPath": "C:\\Users\\advaytandon\\source\\packages\\DotnetNuGetWhyPackage\\DotnetNuGetWhyPackage\\DotnetNuGetWhyPackage.csproj" + }, + "C:\\Users\\advaytandon\\source\\packages\\DotnetNuGetWhyPackage\\TestingProjectReferences\\TestingProjectReferences.csproj": { + "projectPath": "C:\\Users\\advaytandon\\source\\packages\\DotnetNuGetWhyPackage\\TestingProjectReferences\\TestingProjectReferences.csproj" + } + } + }, + "net472": { + "targetAlias": "net472", + "projectReferences": { + "C:\\Users\\advaytandon\\source\\packages\\DotnetNuGetWhyPackage\\DotnetNuGetWhyPackage\\DotnetNuGetWhyPackage.csproj": { + "projectPath": "C:\\Users\\advaytandon\\source\\packages\\DotnetNuGetWhyPackage\\DotnetNuGetWhyPackage\\DotnetNuGetWhyPackage.csproj" + }, + "C:\\Users\\advaytandon\\source\\packages\\DotnetNuGetWhyPackage\\TestingProjectReferences\\TestingProjectReferences.csproj": { + "projectPath": "C:\\Users\\advaytandon\\source\\packages\\DotnetNuGetWhyPackage\\TestingProjectReferences\\TestingProjectReferences.csproj" + } + } + } + }, + "warningProperties": { + "warnAsError": [ + "NU1605" + ] + }, + "restoreAuditProperties": { + "enableAudit": "true", + "auditLevel": "low", + "auditMode": "direct" + } + }, + "frameworks": { + "net6.0": { + "targetAlias": "net6.0", + "dependencies": { + "NuGet.Resolver": { + "target": "Package", + "version": "[6.9.1, )" + }, + "System.Text.Json": { + "target": "Package", + "version": "[8.0.0, )" + } + }, + "imports": [ + "net461", + "net462", + "net47", + "net471", + "net472", + "net48", + "net481" + ], + "assetTargetFallback": true, + "warn": true, + "frameworkReferences": { + "Microsoft.NETCore.App": { + "privateAssets": "all" + } + }, + "runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\8.0.300\\RuntimeIdentifierGraph.json" + }, + "net472": { + "targetAlias": "net472", + "dependencies": { + "Azure.Core": { + "target": "Package", + "version": "[1.38.0, )" + }, + "System.Text.Json": { + "target": "Package", + "version": "[8.0.0, )" + } + }, + "runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\8.0.300\\RuntimeIdentifierGraph.json" + } + } + }, + "logs": [ + { + "code": "NU1605", + "level": "Error", + "message": "Warning As Error: Detected package downgrade: System.Text.Json from 8.0.3 to 8.0.0. Reference the package directly from the project to select a different version. \r\n DNW.Test.SampleProject1 -> DotnetNuGetWhyPackage -> System.Text.Json (>= 8.0.3) \r\n DNW.Test.SampleProject1 -> System.Text.Json (>= 8.0.0)", + "libraryId": "System.Text.Json", + "targetGraphs": [ + ".NETFramework,Version=v4.7.2", + "net6.0" + ] + } + ] +} \ No newline at end of file