praeclarum / FuGetGallery

An alternative web UI for browsing nuget packages
https://www.fuget.org
MIT License
683 stars 121 forks source link

APIDiff doesn't work for NetCore Apps #65

Open TravisEz13 opened 5 years ago

TravisEz13 commented 5 years ago

When <group targetFramework=".NETCoreApp2.1"> is the only group, APIDiff doesn't work

https://www.fuget.org/packages/System.Management.Automation/6.2.1/lib

bgrainger commented 4 years ago

This comment is relevant: https://github.com/praeclarum/FuGetGallery/issues/84#issuecomment-577100047

The bug is in the same method, because otargetFramework is null, so the full diff URL isn't generated.

bgrainger commented 4 years ago

I've traced the problem back to https://github.com/praeclarum/FuGetGallery/blob/c9e7aec5df7a07b20e6168f3ba9994abb22a42a6/Data/PackageData.cs#L123-L129

It looks like this code attempts to find the target frameworks by looking for entries in the archive of the form lib/{tfm}/{assembly}.dll or build/{tfm}/{assembly}.dll. However, in this nupkg, the files are runtimes/(unix|win)/lib/{tfm}/{assembly}.dll, which doesn't match.

Thus, no target frameworks are detected, and the diff URLs are not generated properly.

bgrainger commented 4 years ago

The file layout for architecture-specific assemblies is documented here: https://docs.microsoft.com/en-us/nuget/create-packages/supporting-multiple-target-frameworks#framework-version-folder-structure

bgrainger commented 4 years ago

The problem can be fixed with this patch:

if (n.StartsWith("runtimes/", StringComparison.Ordinal)) {
    var buildIndex = n.IndexOf ("/build/", StringComparison.Ordinal);
    var libIndex = n.IndexOf ("/lib/", StringComparison.Ordinal);
    if (libIndex != -1)
        n = n.Substring (libIndex + 1);
    else if (buildIndex != -1)
        n = n.Substring (buildIndex + 1);
}

However, this combines all the runtime-specific assemblies for one TFM together. For System.Management.Automation 6.2.4, this results in quite a bit of duplication:

image

Since (I don't think) FuGet has a concept of runtime in its UI/URL structure, I don't really know how these should be surfaced properly.