-
-
Notifications
You must be signed in to change notification settings - Fork 490
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2931 from marticliment/winget-native-package-caching
- Loading branch information
Showing
6 changed files
with
194 additions
and
149 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
137 changes: 137 additions & 0 deletions
137
src/UniGetUI.PackageEngine.Managers.WinGet/WinGetHelpers/NativePackageHandler.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
using System.Collections.Concurrent; | ||
using Microsoft.Management.Deployment; | ||
using UniGetUI.Core.Logging; | ||
using UniGetUI.PackageEngine.Enums; | ||
using UniGetUI.PackageEngine.Interfaces; | ||
|
||
namespace UniGetUI.PackageEngine.Managers.WingetManager; | ||
|
||
public static class NativePackageHandler | ||
{ | ||
private static ConcurrentDictionary<long, CatalogPackage> __nativePackages = new(); | ||
private static ConcurrentDictionary<long, CatalogPackageMetadata> __nativeDetails = new(); | ||
private static ConcurrentDictionary<long, PackageInstallerInfo> __nativeInstallers_Install = new(); | ||
private static ConcurrentDictionary<long, PackageInstallerInfo> __nativeInstallers_Uninstall = new(); | ||
|
||
/// <summary> | ||
/// Get (cache or load) the native package for the given package, if any; | ||
/// </summary> | ||
/// <returns></returns> | ||
public static CatalogPackage? GetPackage(IPackage package) | ||
{ | ||
if (NativeWinGetHelper.ExternalFactory is null || NativeWinGetHelper.ExternalManager is null) | ||
return null; | ||
|
||
__nativePackages.TryGetValue(package.GetHash(), out CatalogPackage? catalogPackage); | ||
if (catalogPackage is not null) | ||
return catalogPackage; | ||
|
||
PackageCatalogReference Catalog = NativeWinGetHelper.ExternalManager.GetPackageCatalogByName(package.Source.Name); | ||
if (Catalog is null) | ||
{ | ||
Logger.Error("Failed to get catalog " + package.Source.Name + ". Is the package local?"); | ||
return null; | ||
} | ||
|
||
// Connect to catalog | ||
Catalog.AcceptSourceAgreements = true; | ||
ConnectResult ConnectResult = Catalog.Connect(); | ||
if (ConnectResult.Status != ConnectResultStatus.Ok) | ||
{ | ||
Logger.Error("Failed to connect to catalog " + package.Source.Name); | ||
return null; | ||
} | ||
|
||
// Match only the exact same Id | ||
FindPackagesOptions packageMatchFilter = NativeWinGetHelper.ExternalFactory.CreateFindPackagesOptions(); | ||
PackageMatchFilter filters = NativeWinGetHelper.ExternalFactory.CreatePackageMatchFilter(); | ||
filters.Field = PackageMatchField.Id; | ||
filters.Value = package.Id; | ||
filters.Option = PackageFieldMatchOption.Equals; | ||
packageMatchFilter.Filters.Add(filters); | ||
packageMatchFilter.ResultLimit = 1; | ||
var SearchResult = Task.Run(() => ConnectResult.PackageCatalog.FindPackages(packageMatchFilter)); | ||
|
||
if (SearchResult?.Result?.Matches is null || | ||
SearchResult.Result.Matches.Count == 0) | ||
{ | ||
Logger.Error("Failed to find package " + package.Id + " in catalog " + package.Source.Name); | ||
return null; | ||
} | ||
|
||
// Get the Native Package | ||
catalogPackage = SearchResult.Result.Matches.First().CatalogPackage; | ||
AddPackage(package, catalogPackage); | ||
|
||
return catalogPackage; | ||
} | ||
|
||
/// <summary> | ||
/// Adds an external CatalogPackage to the internal database | ||
/// </summary> | ||
public static void AddPackage(IPackage package, CatalogPackage catalogPackage) | ||
{ | ||
__nativePackages[package.GetHash()] = catalogPackage; | ||
} | ||
|
||
/// <summary> | ||
/// Get (cached or load) the native package details for the given package, if any; | ||
/// </summary> | ||
public static CatalogPackageMetadata? GetDetails(IPackage package) | ||
{ | ||
if (__nativeDetails.TryGetValue(package.GetHash(), out CatalogPackageMetadata? metadata)) | ||
return metadata; | ||
|
||
CatalogPackage? catalogPackage = GetPackage(package); | ||
metadata = catalogPackage?.DefaultInstallVersion?.GetCatalogPackageMetadata(); | ||
metadata ??= catalogPackage?.InstalledVersion?.GetCatalogPackageMetadata(); | ||
|
||
if (metadata is not null) | ||
__nativeDetails[package.GetHash()] = metadata; | ||
|
||
return metadata; | ||
} | ||
|
||
/// <summary> | ||
/// Get (cached or load) the native installer for the given package, if any. The operation type determines wether | ||
/// </summary> | ||
public static PackageInstallerInfo? GetInstallationOptions(IPackage package, OperationType operation) | ||
{ | ||
if (NativeWinGetHelper.ExternalFactory is null) | ||
return null; | ||
|
||
PackageInstallerInfo? installerInfo = null; | ||
if (operation is OperationType.Uninstall) | ||
installerInfo = _getInstallationOptionsOnDict(package, ref __nativeInstallers_Uninstall, true); | ||
else | ||
installerInfo = _getInstallationOptionsOnDict(package, ref __nativeInstallers_Uninstall, false); | ||
|
||
return installerInfo; | ||
} | ||
|
||
public static void Clear() | ||
{ | ||
__nativePackages.Clear();; | ||
__nativeDetails.Clear();; | ||
__nativeInstallers_Install.Clear();; | ||
__nativeInstallers_Uninstall.Clear(); | ||
} | ||
|
||
private static PackageInstallerInfo? _getInstallationOptionsOnDict(IPackage package, ref ConcurrentDictionary<long, PackageInstallerInfo> source, bool installed) | ||
{ | ||
if (source.TryGetValue(package.GetHash(), out PackageInstallerInfo? installerInfo)) | ||
return installerInfo; | ||
|
||
PackageVersionInfo? catalogPackage; | ||
if (installed) catalogPackage = GetPackage(package)?.InstalledVersion; | ||
else catalogPackage = GetPackage(package)?.DefaultInstallVersion; | ||
|
||
InstallOptions? options = NativeWinGetHelper.ExternalFactory?.CreateInstallOptions(); | ||
installerInfo = catalogPackage?.GetApplicableInstaller(options); | ||
|
||
if (installerInfo is not null) | ||
source[package.GetHash()] = installerInfo; | ||
|
||
return installerInfo; | ||
} | ||
} |
Oops, something went wrong.