Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Recursive / transitive package dependency resolution using the NuGet Client SDK #6188

Open
ohadschn opened this issue Nov 15, 2017 · 9 comments
Labels
Functionality:SDK The NuGet client packages published to nuget.org Priority:3 Issues under consideration. With enough upvotes, will be reconsidered to be added to the backlog. Style:PackageReference Style:Packages.Config Type:Feature

Comments

@ohadschn
Copy link

ohadschn commented Nov 15, 2017

Provided a package ID and version, how can I programmatically obtain its recursive/transitive list of dependencies? I'm using the NuGet Client SDK (NuGet.Protocol etc).

This code below is working, but I'm wondering if there's anything built in and/or more efficient (perhaps even some way to build a lock file and then load that up using a JSON deserializer?)

private static async Task GetRecursiveDependenciesCore(string id, string version, ConcurrentQueue<string> dependencies)
{
    var sourceRepository = new SourceRepository(new PackageSource(NugetOrgSource), Repository.Provider.GetCoreV3());
    var dependencyResource = await sourceRepository.GetResourceAsync<DependencyInfoResource>(CancellationToken.None);
    var package = await dependencyResource.ResolvePackage(new PackageIdentity(id, new NuGetVersion(version)), NuGetFramework.AnyFramework, new NugetLogger(), CancellationToken.None);
    if (package == null)
    {
        throw new InvalidOperationException("Could not locate dependency!");
    }

    foreach (var dependency in package.Dependencies)
    {
        dependencies.Enqueue(dependency.Id + " " + dependency.VersionRange.MinVersion);
    }

    await Task.WhenAll(package.Dependencies.Select(d => GetRecursiveDependenciesCore(d.Id, d.VersionRange.MinVersion.ToNormalizedString(), dependencies)));
}
@ohadschn ohadschn changed the title Recursive / transitive package dependency resolution Recursive / transitive package dependency resolution using the NuGet Client SDK Nov 15, 2017
@emgarten
Copy link
Member

Restoring the provided package id and version and then reading the project.assets.json file will be the easiest way. To run it programmatically take a look at:
https://github.com/NuGet/NuGet.Client/blob/8bc20a92f97b5007b8cb80b2e4285da7c7a63a03/src/NuGet.Core/NuGet.Commands/RestoreCommand/RestoreRunner.cs#L103

If you are using DependencyInfoResource take a look at the gather code which finds all possible transitive dependencies for packages.config:
https://github.com/NuGet/NuGet.Client/blob/8bc20a92f97b5007b8cb80b2e4285da7c7a63a03/src/NuGet.Core/NuGet.PackageManagement/Resolution/ResolverGather.cs#L35

Note that you would still need to resolve to find the best version of the package to use after this.

@ohadschn
Copy link
Author

@emgarten thank you, but ResolverGather looks like too much code to copy/paste... any way to use it publicly? I guess I could also invoke the private ctor/methods using reflection...

I would rather avoid a full restore as it is too heavyweight for my needs.

@emgarten
Copy link
Member

There isn't a lightweight public way to use this. What is the scenario you are trying to achieve?

@ohadschn
Copy link
Author

I need to submit all my dependencies for open source licensing review (OSS MSFT). I just need the package IDs and versions, which is why a full restore is overkill. Like I said my code above works so I'm not blocked so far.

@jainaashish
Copy link
Contributor

As mentioned above, there isn't a easy way to do this at this time. And it also doesn't look like it will happen in near future so closing it for now.

@jainaashish jainaashish added this to the 4.6 milestone Jan 10, 2018
@0xced
Copy link

0xced commented Oct 26, 2019

Has something changed now that NuGet packages are at version 5.3?

@StingyJack
Copy link
Contributor

@jainaashish - can this be re-evaluated? Something like this would be nice for troubleshooting or understanding things like "Why does Visual Studio want to install System.Security.AccessControl v5.0.0 when my netstandard2.0 package has only newtonsoft.json v12.0.3 as a declared dependency?"

There was also an issue open here somewhere requesting the old visualization tool be resurrected for general use and in "What if" scenarios.

Not having to do this with cobbled together (and probably not correct) scripts would have been useful when I was doing Big Pharma work a few years ago (where every little thing is recorded and validated in giant binders with two signatures per validation, and seemingly sensible things reducing "extra" 0's in a version number actually create a bunch of manual work.)

I'd like to be able to answer the question I posed in the first paragraph without having to bother you all about it.

@zivkan zivkan removed this from the 4.6 milestone Mar 10, 2021
@zivkan zivkan added Functionality:SDK The NuGet client packages published to nuget.org Priority:3 Issues under consideration. With enough upvotes, will be reconsidered to be added to the backlog. Type:Feature and removed Resolution:Question This issues appears to be a question, not a product defect labels Mar 10, 2021
@zivkan zivkan reopened this Mar 10, 2021
@zivkan
Copy link
Member

zivkan commented Mar 10, 2021

@StingyJack The resolver algorithms themselves are in:
NuGet.DependencyResolver.Core for PackageReference
NuGet.Resolver for packages.config

I've never looked at NuGet.Resolver myself. But from what I've seen of NuGet.DependencyResolver.Core, it's very tied to NuGet.Command's RestoreCommand, to the point that it's probably just as difficult as performing a restore itself. I have no idea how to use either NuGet.Resolver or NuGet.DependencyResolver.Core independently, and would need to read the source to try to figure it out. Of course, since I'm already somewhat familiar with NuGet's source, it would be easier for me than others, but I'm unable to commit to a lot of time helping people with these APIs. Just setting expectations.

I've reopened this issue to encourage customers to upvote the issue. If it gets enough upvotes we can schedule work to create easier to use APIs.

For now, my best advice is to repeat what was previously mentioned. For PackageReference, restore a project and read the project.assets.json. Otherwise perhaps you could script nuget.exe install <packageid> then check the packages folder for all the packages it downloaded and extracted. Although I imagine that nuget.exe install should be simple enough for most people to debug themselves and figure out NuGet.Resolver's API.

@StingyJack
Copy link
Contributor

@zivkan - i found that using package manager console and the Install-Package along with -WhatIf and -Verbose were useful enough to locate that additional System.Security package issue I was having (some other package needed them that hadn't been installed correctly a few months ago, I'm just the next lucky maintenance programmer). Anyone needing the OP request because they are having a problem with figuring out a dependency resolution issue should really try the install-package -whatif -verbose.

@jeffkl jeffkl added Priority:3 Issues under consideration. With enough upvotes, will be reconsidered to be added to the backlog. and removed Priority:3 Issues under consideration. With enough upvotes, will be reconsidered to be added to the backlog. Triage:NeedsTriageDiscussion labels Apr 8, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Functionality:SDK The NuGet client packages published to nuget.org Priority:3 Issues under consideration. With enough upvotes, will be reconsidered to be added to the backlog. Style:PackageReference Style:Packages.Config Type:Feature
Projects
None yet
Development

No branches or pull requests

9 participants