display installed packages v1

This commit is contained in:
Matt Parker
2025-11-02 12:23:56 +10:00
parent 2966e733f1
commit ce1020c369
5 changed files with 136 additions and 1 deletions

View File

@@ -44,6 +44,7 @@
<PackageVersion Include="Microsoft.VisualStudio.Shared.VSCodeDebugProtocol" Version="18.0.10427.1" />
<PackageVersion Include="Microsoft.VisualStudio.SolutionPersistence" Version="1.0.52" />
<PackageVersion Include="MudBlazor" Version="8.12.0" />
<PackageVersion Include="NuGet.ProjectModel" Version="7.1.0-preview.1.42" />
<PackageVersion Include="NuGet.Protocol" Version="7.1.0-preview.1.42" />
<PackageVersion Include="ObservableCollections" Version="3.3.4" />
<PackageVersion Include="ObservableCollections.R3" Version="3.3.4" />

View File

@@ -1,5 +1,6 @@
using Ardalis.GuardClauses;
using Microsoft.Build.Evaluation;
using NuGet.ProjectModel;
using SharpIDE.Application.Features.SolutionDiscovery.VsPersistence;
namespace SharpIDE.Application.Features.Evaluation;
@@ -55,4 +56,73 @@ public static class ProjectEvaluation
return Guid.Parse(userSecretsId);
}
public class InstalledPackage
{
public required string Name { get; set; }
public required string RequestedVersion { get; set; }
public required string? ResolvedVersion { get; set; }
public required string TargetFramework { get; set; }
public required bool IsTopLevel { get; set; }
public required bool IsAutoReferenced { get; set; }
}
public static async Task<List<InstalledPackage>> GetPackageReferencesForProject(SharpIdeProjectModel projectModel, bool includeTransitive = true)
{
using var _ = SharpIdeOtel.Source.StartActivity($"{nameof(ProjectEvaluation)}.{nameof(GetPackageReferencesForProject)}");
Guard.Against.Null(projectModel, nameof(projectModel));
var project = _projectCollection.GetLoadedProjects(projectModel.FilePath).Single();
var assetsPath = project.GetPropertyValue("ProjectAssetsFile");
if (File.Exists(assetsPath) is false)
{
throw new FileNotFoundException("Could not find project.assets.json file", assetsPath);
}
var lockFileFormat = new LockFileFormat();
var lockFile = lockFileFormat.Read(assetsPath);
var packages = GetPackagesFromAssetsFile(lockFile, includeTransitive);
return packages;
}
// ChatGPT Special
private static List<InstalledPackage> GetPackagesFromAssetsFile(LockFile assetsFile, bool includeTransitive)
{
var packages = new List<InstalledPackage>();
foreach (var target in assetsFile.Targets.Where(t => t.RuntimeIdentifier == null))
{
var tfm = target.TargetFramework.GetShortFolderName();
var tfmInfo = assetsFile.PackageSpec.TargetFrameworks
.FirstOrDefault(t => t.FrameworkName.Equals(target.TargetFramework));
if (tfmInfo == null) continue;
var topLevelDependencies = tfmInfo.Dependencies
.DistinctBy(s => s.Name)
.Select(s => s.Name)
.ToHashSet();
foreach (var library in target.Libraries.Where(l => l.Type == "package"))
{
var isTopLevel = topLevelDependencies.Contains(library.Name);
if (!includeTransitive && !isTopLevel) continue;
var dependency = tfmInfo.Dependencies
.FirstOrDefault(d => d.Name.Equals(library.Name, StringComparison.OrdinalIgnoreCase));
packages.Add(new InstalledPackage
{
Name = library.Name,
RequestedVersion = dependency?.LibraryRange.VersionRange?.ToString() ?? "",
ResolvedVersion = library.Version?.ToString(),
TargetFramework = tfm,
IsTopLevel = isTopLevel,
IsAutoReferenced = dependency?.AutoReferenced ?? false
});
}
}
return packages;
}
}

View File

@@ -3,6 +3,8 @@ using NuGet.Configuration;
using NuGet.Packaging.Core;
using NuGet.Protocol;
using NuGet.Protocol.Core.Types;
using NuGet.Versioning;
using SharpIDE.Application.Features.Evaluation;
using SharpIDE.Application.Features.SolutionDiscovery.VsPersistence;
namespace SharpIDE.Application.Features.Nuget;
@@ -106,4 +108,42 @@ public class NugetClientService
metadataList.Reverse();
return metadataList;
}
public async Task<List<IdePackageResult>> GetPackagesForInstalledPackages(string directoryPath, List<ProjectEvaluation.InstalledPackage> installedPackages, CancellationToken cancellationToken = default)
{
var settings = Settings.LoadDefaultSettings(root: directoryPath);
var packageSourceProvider = new PackageSourceProvider(settings);
var packageSources = packageSourceProvider.LoadPackageSources().Where(p => p.IsEnabled).ToList();
var packagesResult = new List<IdePackageResult>();
foreach (var installedPackage in installedPackages)
{
var idePackageResult = new IdePackageResult(installedPackage.Name, []);
var nugetVersionString = installedPackage.ResolvedVersion ?? installedPackage.RequestedVersion;
var nugetVersion = NuGetVersion.Parse(nugetVersionString);
var packageIdentity = new PackageIdentity(installedPackage.Name, nugetVersion);
foreach (var source in packageSources)
{
var repository = Repository.Factory.GetCoreV3(source.Source);
var metadataResource = await repository.GetResourceAsync<PackageMetadataResource>(cancellationToken).ConfigureAwait(false);
if (metadataResource == null)
continue;
var foundPackage = await metadataResource.GetMetadataAsync(packageIdentity, _sourceCacheContext, _nugetLogger, cancellationToken).ConfigureAwait(false);
if (foundPackage != null)
{
idePackageResult.PackageFromSources.Add(new IdePackageFromSourceResult(foundPackage, source));
}
}
if (idePackageResult.PackageFromSources.Count > 0)
{
packagesResult.Add(idePackageResult);
}
}
return packagesResult;
}
}

View File

@@ -49,6 +49,7 @@
<PackageReference Include="Microsoft.CodeAnalysis.Features" />
<PackageReference Include="Microsoft.CodeAnalysis.Workspaces.MSBuild" PrivateAssets="all" />
<PackageReference Include="Microsoft.VisualStudio.SolutionPersistence" />
<PackageReference Include="NuGet.ProjectModel" />
<PackageReference Include="NuGet.Protocol" />
<PackageReference Include="ObservableCollections" />
<PackageReference Include="R3" />

View File

@@ -1,4 +1,5 @@
using Godot;
using SharpIDE.Application.Features.Evaluation;
using SharpIDE.Application.Features.Nuget;
using SharpIDE.Application.Features.SolutionDiscovery.VsPersistence;
@@ -32,7 +33,29 @@ public partial class NugetPanel : Control
{
await Task.Delay(300);
var result = await _nugetClientService.GetTop100Results(Solution!.DirectoryPath);
;
_ = Task.GodotRun(async () =>
{
var project = Solution.AllProjects.First(s => s.Name == "ProjectB");
await project.MsBuildEvaluationProjectTask;
var installedPackages = await ProjectEvaluation.GetPackageReferencesForProject(project);
await this.InvokeAsync(() => _installedPackagesVboxContainer.QueueFreeChildren());
var idePackageResult = await _nugetClientService.GetPackagesForInstalledPackages(project.ChildNodeBasePath, installedPackages);
var scenes = idePackageResult.Select(s =>
{
var scene = _packageEntryScene.Instantiate<PackageEntry>();
scene.PackageResult = s;
scene.PackageSelected += OnPackageSelected;
return scene;
}).ToList();
await this.InvokeAsync(() =>
{
foreach (var scene in scenes)
{
_installedPackagesVboxContainer.AddChild(scene);
}
});
});
await this.InvokeAsync(() => _availablePackagesItemList.QueueFreeChildren());
var scenes = result.Select(s =>
{