From c1eedba5a7cf80665cd63adad2280b1bfe9a0735 Mon Sep 17 00:00:00 2001 From: Maksim Khomutov Date: Wed, 15 Jan 2025 23:44:11 +1100 Subject: [PATCH 1/4] allow to install multiple versions of the same packages --- ...er_HasNoBreakingChanges_Async.verified.txt | 22 ++++++ .../Models/InstallationContext.cs | 18 +++++ .../Interfaces/IPackageInstallationService.cs | 3 + .../Services/PackageInstallationService.cs | 71 ++++++++++++++----- 4 files changed, 96 insertions(+), 18 deletions(-) create mode 100644 src/Orc.NuGetExplorer/Models/InstallationContext.cs diff --git a/src/Orc.NuGetExplorer.Tests/PublicApiFacts.Orc_NuGetExplorer_HasNoBreakingChanges_Async.verified.txt b/src/Orc.NuGetExplorer.Tests/PublicApiFacts.Orc_NuGetExplorer_HasNoBreakingChanges_Async.verified.txt index 2e8db0e0..8b7f846d 100644 --- a/src/Orc.NuGetExplorer.Tests/PublicApiFacts.Orc_NuGetExplorer_HasNoBreakingChanges_Async.verified.txt +++ b/src/Orc.NuGetExplorer.Tests/PublicApiFacts.Orc_NuGetExplorer_HasNoBreakingChanges_Async.verified.txt @@ -984,6 +984,27 @@ namespace Orc.NuGetExplorer.Messaging public PackagingDeletemeMessage(Orc.NuGetExplorer.Packaging.PackageOperationInfo content) { } } } +namespace Orc.NuGetExplorer.Models +{ + [System.Runtime.CompilerServices.RequiredMember] + public class InstallationContext + { + [System.Obsolete(("Constructors of types with required members are not supported in this version of " + + "your compiler."), true)] + [System.Runtime.CompilerServices.CompilerFeatureRequired("RequiredMembers")] + public InstallationContext() { } + public bool AllowMultipleVersions { get; set; } + public System.Threading.CancellationToken CancellationToken { get; set; } + public bool IgnoreMissingPackages { get; set; } + [System.Runtime.CompilerServices.RequiredMember] + public NuGet.Packaging.Core.PackageIdentity Package { get; set; } + public System.Func? PackagePredicate { get; set; } + [System.Runtime.CompilerServices.RequiredMember] + public Orc.NuGetExplorer.IExtensibleProject Project { get; set; } + [System.Runtime.CompilerServices.RequiredMember] + public System.Collections.Generic.IReadOnlyList Repositories { get; set; } + } +} namespace Orc.NuGetExplorer.Packaging { public class EmptyPackageDetails : Orc.NuGetExplorer.IPackageDetails @@ -1249,6 +1270,7 @@ namespace Orc.NuGetExplorer.Services public interface IPackageInstallationService { NuGet.Packaging.VersionFolderPathResolver InstallerPathResolver { get; } + System.Threading.Tasks.Task InstallAsync(Orc.NuGetExplorer.Models.InstallationContext context); System.Threading.Tasks.Task InstallAsync(NuGet.Packaging.Core.PackageIdentity package, Orc.NuGetExplorer.IExtensibleProject project, System.Collections.Generic.IReadOnlyList repositories, bool ignoreMissingPackages = false, System.Func? packagePredicate = null, System.Threading.CancellationToken cancellationToken = default); System.Threading.Tasks.Task MeasurePackageSizeFromRepositoryAsync(NuGet.Packaging.Core.PackageIdentity packageIdentity, NuGet.Protocol.Core.Types.SourceRepository sourceRepository); System.Threading.Tasks.Task UninstallAsync(NuGet.Packaging.Core.PackageIdentity package, Orc.NuGetExplorer.IExtensibleProject project, System.Collections.Generic.IEnumerable installedPackageReferences, System.Func? packagePredicate = null, System.Threading.CancellationToken cancellationToken = default); diff --git a/src/Orc.NuGetExplorer/Models/InstallationContext.cs b/src/Orc.NuGetExplorer/Models/InstallationContext.cs new file mode 100644 index 00000000..6296e9d9 --- /dev/null +++ b/src/Orc.NuGetExplorer/Models/InstallationContext.cs @@ -0,0 +1,18 @@ +namespace Orc.NuGetExplorer.Models; + +using System; +using System.Collections.Generic; +using System.Threading; +using NuGet.Packaging.Core; +using NuGet.Protocol.Core.Types; + +public class InstallationContext +{ + public required PackageIdentity Package { get; set; } + public required IExtensibleProject Project { get; set; } + public required IReadOnlyList Repositories { get; set; } + public bool IgnoreMissingPackages { get; set; } + public Func? PackagePredicate { get; set; } + public CancellationToken CancellationToken { get; set; } + public bool AllowMultipleVersions { get; set; } = false; +} diff --git a/src/Orc.NuGetExplorer/Services/Interfaces/IPackageInstallationService.cs b/src/Orc.NuGetExplorer/Services/Interfaces/IPackageInstallationService.cs index 90a7c874..c870a872 100644 --- a/src/Orc.NuGetExplorer/Services/Interfaces/IPackageInstallationService.cs +++ b/src/Orc.NuGetExplorer/Services/Interfaces/IPackageInstallationService.cs @@ -7,6 +7,7 @@ using NuGet.Packaging; using NuGet.Packaging.Core; using NuGet.Protocol.Core.Types; +using Orc.NuGetExplorer.Models; public interface IPackageInstallationService { @@ -15,6 +16,8 @@ public interface IPackageInstallationService /// VersionFolderPathResolver InstallerPathResolver { get; } + Task InstallAsync(InstallationContext context); + Task InstallAsync( PackageIdentity package, IExtensibleProject project, diff --git a/src/Orc.NuGetExplorer/Services/PackageInstallationService.cs b/src/Orc.NuGetExplorer/Services/PackageInstallationService.cs index a9dc34dd..b583e4f7 100644 --- a/src/Orc.NuGetExplorer/Services/PackageInstallationService.cs +++ b/src/Orc.NuGetExplorer/Services/PackageInstallationService.cs @@ -3,12 +3,14 @@ using System; using System.Collections.Generic; using System.IO; +using System.IO.Packaging; using System.Linq; using System.Threading; using System.Threading.Tasks; using Catel.IoC; using Catel.Logging; using MethodTimer; +using Models; using NuGet.Common; using NuGet.Configuration; using NuGet.Frameworks; @@ -183,18 +185,17 @@ public async Task UninstallAsync(PackageIdentity package, IExtensibleProject pro } } - [Time] - public async Task InstallAsync( - PackageIdentity package, - IExtensibleProject project, - IReadOnlyList repositories, - bool ignoreMissingPackages = false, - Func? packagePredicate = null, - CancellationToken cancellationToken = default) + public async Task InstallAsync(InstallationContext context) { - ArgumentNullException.ThrowIfNull(package); - ArgumentNullException.ThrowIfNull(project); - ArgumentNullException.ThrowIfNull(repositories); + ArgumentNullException.ThrowIfNull(context); + + var project = context.Project; + var package = context.Package; + var repositories = context.Repositories; + var ignoreMissingPackages = context.IgnoreMissingPackages; + var packagePredicate = context.PackagePredicate; + var cancellationToken = context.CancellationToken; + var allowMultipleVersions = context.AllowMultipleVersions; try { @@ -235,7 +236,7 @@ public async Task InstallAsync( var dependencyInfoResources = new DependencyInfoResourceCollection(dependencyResources); - resolverContext = await ResolveDependenciesAsync(package, targetFramework, PackageIdentityComparer.Default, dependencyInfoResources, + resolverContext = await ResolveDependenciesAsync(package, targetFramework, PackageIdentityComparer.Default, dependencyInfoResources, sourceCacheContext, project, ignoreMissingPackages, packagePredicate, cancellationToken); if (resolverContext is null || @@ -271,12 +272,20 @@ public async Task InstallAsync( throw Log.ErrorAndCreateException($"Package {package} incompatible with project target platform {targetFramework}"); } - // Step 5. Build install list using NuGet Resolver and select available resources. - // Track packages which already installed and make sure only one version of package exists - var resolver = new Resolver.PackageResolver(); - var availablePackagesToInstall = await resolver.ResolveWithVersionOverrideAsync(resolverContext, project, DependencyBehavior.Highest, - (project, conflict) => _fileSystemService.CreateDeleteme(conflict.PackageIdentity.Id, project.GetInstallPath(conflict.PackageIdentity)), - cancellationToken); + // Step 5. Build install list using NuGet Resolver and select available resources. + List availablePackagesToInstall; + if (allowMultipleVersions) + { + availablePackagesToInstall = resolverContext.AvailablePackages.ToList(); + } + else + { + // Track packages which already installed and make sure only one version of package exists + var resolver = new Resolver.PackageResolver(); + availablePackagesToInstall = await resolver.ResolveWithVersionOverrideAsync(resolverContext, project, DependencyBehavior.Ignore, + (project, conflict) => _fileSystemService.CreateDeleteme(conflict.PackageIdentity.Id, project.GetInstallPath(conflict.PackageIdentity)), + cancellationToken); + } // Step 6. Download everything except main package and extract all availablePackagesToInstall.Remove(mainPackageInfo); @@ -302,6 +311,32 @@ public async Task InstallAsync( } } + [Time] + public async Task InstallAsync( + PackageIdentity package, + IExtensibleProject project, + IReadOnlyList repositories, + bool ignoreMissingPackages = false, + Func? packagePredicate = null, + CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(package); + ArgumentNullException.ThrowIfNull(project); + ArgumentNullException.ThrowIfNull(repositories); + + var context = new InstallationContext + { + Package = package, + Project = project, + Repositories = repositories, + IgnoreMissingPackages = ignoreMissingPackages, + PackagePredicate = packagePredicate, + CancellationToken = cancellationToken + }; + + return await InstallAsync(context); + } + // TODO move to separate class public async Task MeasurePackageSizeFromRepositoryAsync(PackageIdentity packageIdentity, SourceRepository sourceRepository) { From e5cb4a12dbe8d392003ab1d847d66163e50b849e Mon Sep 17 00:00:00 2001 From: Maksim Khomutov Date: Wed, 15 Jan 2025 23:54:49 +1100 Subject: [PATCH 2/4] remove CancellationToken from InstallationContext --- ...rc_NuGetExplorer_HasNoBreakingChanges_Async.verified.txt | 3 +-- src/Orc.NuGetExplorer/Models/InstallationContext.cs | 1 - .../Services/Interfaces/IPackageInstallationService.cs | 2 +- .../Services/PackageInstallationService.cs | 6 ++---- 4 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/Orc.NuGetExplorer.Tests/PublicApiFacts.Orc_NuGetExplorer_HasNoBreakingChanges_Async.verified.txt b/src/Orc.NuGetExplorer.Tests/PublicApiFacts.Orc_NuGetExplorer_HasNoBreakingChanges_Async.verified.txt index 8b7f846d..d70cee66 100644 --- a/src/Orc.NuGetExplorer.Tests/PublicApiFacts.Orc_NuGetExplorer_HasNoBreakingChanges_Async.verified.txt +++ b/src/Orc.NuGetExplorer.Tests/PublicApiFacts.Orc_NuGetExplorer_HasNoBreakingChanges_Async.verified.txt @@ -994,7 +994,6 @@ namespace Orc.NuGetExplorer.Models [System.Runtime.CompilerServices.CompilerFeatureRequired("RequiredMembers")] public InstallationContext() { } public bool AllowMultipleVersions { get; set; } - public System.Threading.CancellationToken CancellationToken { get; set; } public bool IgnoreMissingPackages { get; set; } [System.Runtime.CompilerServices.RequiredMember] public NuGet.Packaging.Core.PackageIdentity Package { get; set; } @@ -1270,7 +1269,7 @@ namespace Orc.NuGetExplorer.Services public interface IPackageInstallationService { NuGet.Packaging.VersionFolderPathResolver InstallerPathResolver { get; } - System.Threading.Tasks.Task InstallAsync(Orc.NuGetExplorer.Models.InstallationContext context); + System.Threading.Tasks.Task InstallAsync(Orc.NuGetExplorer.Models.InstallationContext context, System.Threading.CancellationToken cancellationToken = default); System.Threading.Tasks.Task InstallAsync(NuGet.Packaging.Core.PackageIdentity package, Orc.NuGetExplorer.IExtensibleProject project, System.Collections.Generic.IReadOnlyList repositories, bool ignoreMissingPackages = false, System.Func? packagePredicate = null, System.Threading.CancellationToken cancellationToken = default); System.Threading.Tasks.Task MeasurePackageSizeFromRepositoryAsync(NuGet.Packaging.Core.PackageIdentity packageIdentity, NuGet.Protocol.Core.Types.SourceRepository sourceRepository); System.Threading.Tasks.Task UninstallAsync(NuGet.Packaging.Core.PackageIdentity package, Orc.NuGetExplorer.IExtensibleProject project, System.Collections.Generic.IEnumerable installedPackageReferences, System.Func? packagePredicate = null, System.Threading.CancellationToken cancellationToken = default); diff --git a/src/Orc.NuGetExplorer/Models/InstallationContext.cs b/src/Orc.NuGetExplorer/Models/InstallationContext.cs index 6296e9d9..c8b44af9 100644 --- a/src/Orc.NuGetExplorer/Models/InstallationContext.cs +++ b/src/Orc.NuGetExplorer/Models/InstallationContext.cs @@ -13,6 +13,5 @@ public class InstallationContext public required IReadOnlyList Repositories { get; set; } public bool IgnoreMissingPackages { get; set; } public Func? PackagePredicate { get; set; } - public CancellationToken CancellationToken { get; set; } public bool AllowMultipleVersions { get; set; } = false; } diff --git a/src/Orc.NuGetExplorer/Services/Interfaces/IPackageInstallationService.cs b/src/Orc.NuGetExplorer/Services/Interfaces/IPackageInstallationService.cs index c870a872..1cac2afc 100644 --- a/src/Orc.NuGetExplorer/Services/Interfaces/IPackageInstallationService.cs +++ b/src/Orc.NuGetExplorer/Services/Interfaces/IPackageInstallationService.cs @@ -16,7 +16,7 @@ public interface IPackageInstallationService /// VersionFolderPathResolver InstallerPathResolver { get; } - Task InstallAsync(InstallationContext context); + Task InstallAsync(InstallationContext context, CancellationToken cancellationToken = default); Task InstallAsync( PackageIdentity package, diff --git a/src/Orc.NuGetExplorer/Services/PackageInstallationService.cs b/src/Orc.NuGetExplorer/Services/PackageInstallationService.cs index b583e4f7..c19eac81 100644 --- a/src/Orc.NuGetExplorer/Services/PackageInstallationService.cs +++ b/src/Orc.NuGetExplorer/Services/PackageInstallationService.cs @@ -185,7 +185,7 @@ public async Task UninstallAsync(PackageIdentity package, IExtensibleProject pro } } - public async Task InstallAsync(InstallationContext context) + public async Task InstallAsync(InstallationContext context, CancellationToken cancellationToken = default) { ArgumentNullException.ThrowIfNull(context); @@ -194,7 +194,6 @@ public async Task InstallAsync(InstallationContext context) var repositories = context.Repositories; var ignoreMissingPackages = context.IgnoreMissingPackages; var packagePredicate = context.PackagePredicate; - var cancellationToken = context.CancellationToken; var allowMultipleVersions = context.AllowMultipleVersions; try @@ -331,10 +330,9 @@ public async Task InstallAsync( Repositories = repositories, IgnoreMissingPackages = ignoreMissingPackages, PackagePredicate = packagePredicate, - CancellationToken = cancellationToken }; - return await InstallAsync(context); + return await InstallAsync(context, cancellationToken); } // TODO move to separate class From eee55db07c5766fc97809a486b285a111ef9c4a6 Mon Sep 17 00:00:00 2001 From: Maksim Khomutov Date: Thu, 16 Jan 2025 00:00:34 +1100 Subject: [PATCH 3/4] create extensions for IPackageInstallationService --- ...er_HasNoBreakingChanges_Async.verified.txt | 5 ++- .../IPackageInstallationServiceExtensions.cs | 42 +++++++++++++++++++ .../Management/NuGetProjectPackageManager.cs | 13 +++++- .../Interfaces/IPackageInstallationService.cs | 8 ---- .../Services/PackageInstallationService.cs | 26 +----------- 5 files changed, 58 insertions(+), 36 deletions(-) create mode 100644 src/Orc.NuGetExplorer/Extensions/IPackageInstallationServiceExtensions.cs diff --git a/src/Orc.NuGetExplorer.Tests/PublicApiFacts.Orc_NuGetExplorer_HasNoBreakingChanges_Async.verified.txt b/src/Orc.NuGetExplorer.Tests/PublicApiFacts.Orc_NuGetExplorer_HasNoBreakingChanges_Async.verified.txt index d70cee66..907dfce4 100644 --- a/src/Orc.NuGetExplorer.Tests/PublicApiFacts.Orc_NuGetExplorer_HasNoBreakingChanges_Async.verified.txt +++ b/src/Orc.NuGetExplorer.Tests/PublicApiFacts.Orc_NuGetExplorer_HasNoBreakingChanges_Async.verified.txt @@ -316,6 +316,10 @@ namespace Orc.NuGetExplorer NuGet.Packaging.Core.PackageIdentity GetIdentity(); void ResetValidationContext(); } + public static class IPackageInstallationServiceExtensions + { + public static System.Threading.Tasks.Task InstallAsync(this Orc.NuGetExplorer.Services.IPackageInstallationService service, NuGet.Packaging.Core.PackageIdentity package, Orc.NuGetExplorer.IExtensibleProject project, System.Collections.Generic.IReadOnlyList repositories, bool ignoreMissingPackages = false, System.Func? packagePredicate = null, System.Threading.CancellationToken cancellationToken = default) { } + } public interface IPackageLoaderService { Orc.NuGetExplorer.Providers.IPackageMetadataProvider? PackageMetadataProvider { get; } @@ -1270,7 +1274,6 @@ namespace Orc.NuGetExplorer.Services { NuGet.Packaging.VersionFolderPathResolver InstallerPathResolver { get; } System.Threading.Tasks.Task InstallAsync(Orc.NuGetExplorer.Models.InstallationContext context, System.Threading.CancellationToken cancellationToken = default); - System.Threading.Tasks.Task InstallAsync(NuGet.Packaging.Core.PackageIdentity package, Orc.NuGetExplorer.IExtensibleProject project, System.Collections.Generic.IReadOnlyList repositories, bool ignoreMissingPackages = false, System.Func? packagePredicate = null, System.Threading.CancellationToken cancellationToken = default); System.Threading.Tasks.Task MeasurePackageSizeFromRepositoryAsync(NuGet.Packaging.Core.PackageIdentity packageIdentity, NuGet.Protocol.Core.Types.SourceRepository sourceRepository); System.Threading.Tasks.Task UninstallAsync(NuGet.Packaging.Core.PackageIdentity package, Orc.NuGetExplorer.IExtensibleProject project, System.Collections.Generic.IEnumerable installedPackageReferences, System.Func? packagePredicate = null, System.Threading.CancellationToken cancellationToken = default); } diff --git a/src/Orc.NuGetExplorer/Extensions/IPackageInstallationServiceExtensions.cs b/src/Orc.NuGetExplorer/Extensions/IPackageInstallationServiceExtensions.cs new file mode 100644 index 00000000..e7163fd7 --- /dev/null +++ b/src/Orc.NuGetExplorer/Extensions/IPackageInstallationServiceExtensions.cs @@ -0,0 +1,42 @@ +namespace Orc.NuGetExplorer; + +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using MethodTimer; +using Models; +using NuGet.Packaging.Core; +using NuGet.Protocol.Core.Types; +using Services; + +public static class IPackageInstallationServiceExtensions +{ + [Time] + public static async Task InstallAsync( + this IPackageInstallationService service, + PackageIdentity package, + IExtensibleProject project, + IReadOnlyList repositories, + bool ignoreMissingPackages = false, + Func? packagePredicate = null, + CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(service); + ArgumentNullException.ThrowIfNull(package); + ArgumentNullException.ThrowIfNull(project); + ArgumentNullException.ThrowIfNull(repositories); + + var context = new InstallationContext + { + Package = package, + Project = project, + Repositories = repositories, + IgnoreMissingPackages = ignoreMissingPackages, + PackagePredicate = packagePredicate, + }; + + return await service.InstallAsync(context, cancellationToken); + } + +} diff --git a/src/Orc.NuGetExplorer/Management/NuGetProjectPackageManager.cs b/src/Orc.NuGetExplorer/Management/NuGetProjectPackageManager.cs index fb1c1f51..8a5526f4 100644 --- a/src/Orc.NuGetExplorer/Management/NuGetProjectPackageManager.cs +++ b/src/Orc.NuGetExplorer/Management/NuGetProjectPackageManager.cs @@ -8,6 +8,7 @@ using Catel; using Catel.Logging; using Catel.Services; +using Models; using NuGet.Configuration; using NuGet.Packaging; using NuGet.Packaging.Core; @@ -240,8 +241,16 @@ public async Task InstallPackageForProjectAsync(IExtensibleProject project return false; } - - var installerResults = await _packageInstallationService.InstallAsync(package, project, repositories, project.IgnoreDependencies, packagePredicate, token); + var context = new InstallationContext + { + Project = project, + Repositories = repositories, + Package = package, + PackagePredicate = packagePredicate, + AllowMultipleVersions = true + }; + + var installerResults = await _packageInstallationService.InstallAsync(context, token); if (!installerResults.Result.Any()) { if (showErrors) diff --git a/src/Orc.NuGetExplorer/Services/Interfaces/IPackageInstallationService.cs b/src/Orc.NuGetExplorer/Services/Interfaces/IPackageInstallationService.cs index 1cac2afc..ddeea824 100644 --- a/src/Orc.NuGetExplorer/Services/Interfaces/IPackageInstallationService.cs +++ b/src/Orc.NuGetExplorer/Services/Interfaces/IPackageInstallationService.cs @@ -18,14 +18,6 @@ public interface IPackageInstallationService Task InstallAsync(InstallationContext context, CancellationToken cancellationToken = default); - Task InstallAsync( - PackageIdentity package, - IExtensibleProject project, - IReadOnlyList repositories, - bool ignoreMissingPackages = false, - Func? packagePredicate = null, - CancellationToken cancellationToken = default); - Task UninstallAsync(PackageIdentity package, IExtensibleProject project, IEnumerable installedPackageReferences, diff --git a/src/Orc.NuGetExplorer/Services/PackageInstallationService.cs b/src/Orc.NuGetExplorer/Services/PackageInstallationService.cs index c19eac81..63e065ec 100644 --- a/src/Orc.NuGetExplorer/Services/PackageInstallationService.cs +++ b/src/Orc.NuGetExplorer/Services/PackageInstallationService.cs @@ -185,6 +185,7 @@ public async Task UninstallAsync(PackageIdentity package, IExtensibleProject pro } } + [Time] public async Task InstallAsync(InstallationContext context, CancellationToken cancellationToken = default) { ArgumentNullException.ThrowIfNull(context); @@ -310,31 +311,6 @@ public async Task InstallAsync(InstallationContext context, Can } } - [Time] - public async Task InstallAsync( - PackageIdentity package, - IExtensibleProject project, - IReadOnlyList repositories, - bool ignoreMissingPackages = false, - Func? packagePredicate = null, - CancellationToken cancellationToken = default) - { - ArgumentNullException.ThrowIfNull(package); - ArgumentNullException.ThrowIfNull(project); - ArgumentNullException.ThrowIfNull(repositories); - - var context = new InstallationContext - { - Package = package, - Project = project, - Repositories = repositories, - IgnoreMissingPackages = ignoreMissingPackages, - PackagePredicate = packagePredicate, - }; - - return await InstallAsync(context, cancellationToken); - } - // TODO move to separate class public async Task MeasurePackageSizeFromRepositoryAsync(PackageIdentity packageIdentity, SourceRepository sourceRepository) { From cc1fb27215baeca9ba9059efec62745431595756 Mon Sep 17 00:00:00 2001 From: Maksim Khomutov Date: Thu, 16 Jan 2025 00:37:56 +1100 Subject: [PATCH 4/4] apply changes after review --- ...er_HasNoBreakingChanges_Async.verified.txt | 47 +++++++++---------- .../IPackageInstallationServiceExtensions.cs | 42 ----------------- .../Management/NuGetProjectPackageManager.cs | 1 - .../Models/InstallationContext.cs | 2 +- .../Interfaces/IPackageInstallationService.cs | 10 +++- .../Services/PackageInstallationService.cs | 20 +++++++- 6 files changed, 50 insertions(+), 72 deletions(-) delete mode 100644 src/Orc.NuGetExplorer/Extensions/IPackageInstallationServiceExtensions.cs diff --git a/src/Orc.NuGetExplorer.Tests/PublicApiFacts.Orc_NuGetExplorer_HasNoBreakingChanges_Async.verified.txt b/src/Orc.NuGetExplorer.Tests/PublicApiFacts.Orc_NuGetExplorer_HasNoBreakingChanges_Async.verified.txt index 907dfce4..5fe3db5e 100644 --- a/src/Orc.NuGetExplorer.Tests/PublicApiFacts.Orc_NuGetExplorer_HasNoBreakingChanges_Async.verified.txt +++ b/src/Orc.NuGetExplorer.Tests/PublicApiFacts.Orc_NuGetExplorer_HasNoBreakingChanges_Async.verified.txt @@ -316,10 +316,6 @@ namespace Orc.NuGetExplorer NuGet.Packaging.Core.PackageIdentity GetIdentity(); void ResetValidationContext(); } - public static class IPackageInstallationServiceExtensions - { - public static System.Threading.Tasks.Task InstallAsync(this Orc.NuGetExplorer.Services.IPackageInstallationService service, NuGet.Packaging.Core.PackageIdentity package, Orc.NuGetExplorer.IExtensibleProject project, System.Collections.Generic.IReadOnlyList repositories, bool ignoreMissingPackages = false, System.Func? packagePredicate = null, System.Threading.CancellationToken cancellationToken = default) { } - } public interface IPackageLoaderService { Orc.NuGetExplorer.Providers.IPackageMetadataProvider? PackageMetadataProvider { get; } @@ -432,6 +428,23 @@ namespace Orc.NuGetExplorer string GetDirectory(string relativeDirectoryName); string GetFile(string relativeFilePath); } + [System.Runtime.CompilerServices.RequiredMember] + public class InstallationContext + { + [System.Obsolete(("Constructors of types with required members are not supported in this version of " + + "your compiler."), true)] + [System.Runtime.CompilerServices.CompilerFeatureRequired("RequiredMembers")] + public InstallationContext() { } + public bool AllowMultipleVersions { get; set; } + public bool IgnoreMissingPackages { get; set; } + [System.Runtime.CompilerServices.RequiredMember] + public NuGet.Packaging.Core.PackageIdentity Package { get; set; } + public System.Func? PackagePredicate { get; set; } + [System.Runtime.CompilerServices.RequiredMember] + public Orc.NuGetExplorer.IExtensibleProject Project { get; set; } + [System.Runtime.CompilerServices.RequiredMember] + public System.Collections.Generic.IReadOnlyList Repositories { get; set; } + } public class InstallerResult { public InstallerResult(System.Collections.Generic.IDictionary downloadResult) { } @@ -988,26 +1001,6 @@ namespace Orc.NuGetExplorer.Messaging public PackagingDeletemeMessage(Orc.NuGetExplorer.Packaging.PackageOperationInfo content) { } } } -namespace Orc.NuGetExplorer.Models -{ - [System.Runtime.CompilerServices.RequiredMember] - public class InstallationContext - { - [System.Obsolete(("Constructors of types with required members are not supported in this version of " + - "your compiler."), true)] - [System.Runtime.CompilerServices.CompilerFeatureRequired("RequiredMembers")] - public InstallationContext() { } - public bool AllowMultipleVersions { get; set; } - public bool IgnoreMissingPackages { get; set; } - [System.Runtime.CompilerServices.RequiredMember] - public NuGet.Packaging.Core.PackageIdentity Package { get; set; } - public System.Func? PackagePredicate { get; set; } - [System.Runtime.CompilerServices.RequiredMember] - public Orc.NuGetExplorer.IExtensibleProject Project { get; set; } - [System.Runtime.CompilerServices.RequiredMember] - public System.Collections.Generic.IReadOnlyList Repositories { get; set; } - } -} namespace Orc.NuGetExplorer.Packaging { public class EmptyPackageDetails : Orc.NuGetExplorer.IPackageDetails @@ -1273,7 +1266,11 @@ namespace Orc.NuGetExplorer.Services public interface IPackageInstallationService { NuGet.Packaging.VersionFolderPathResolver InstallerPathResolver { get; } - System.Threading.Tasks.Task InstallAsync(Orc.NuGetExplorer.Models.InstallationContext context, System.Threading.CancellationToken cancellationToken = default); + System.Threading.Tasks.Task InstallAsync(Orc.NuGetExplorer.InstallationContext context, System.Threading.CancellationToken cancellationToken = default); + [System.Obsolete(("Use `InstallAsync(InstallationContext context, CancellationToken cancellationToke" + + "n = default)` instead. Will be treated as an error from version 6.0.0. Will be r" + + "emoved in version 7.0.0."), false)] + System.Threading.Tasks.Task InstallAsync(NuGet.Packaging.Core.PackageIdentity package, Orc.NuGetExplorer.IExtensibleProject project, System.Collections.Generic.IReadOnlyList repositories, bool ignoreMissingPackages = false, System.Func? packagePredicate = null, System.Threading.CancellationToken cancellationToken = default); System.Threading.Tasks.Task MeasurePackageSizeFromRepositoryAsync(NuGet.Packaging.Core.PackageIdentity packageIdentity, NuGet.Protocol.Core.Types.SourceRepository sourceRepository); System.Threading.Tasks.Task UninstallAsync(NuGet.Packaging.Core.PackageIdentity package, Orc.NuGetExplorer.IExtensibleProject project, System.Collections.Generic.IEnumerable installedPackageReferences, System.Func? packagePredicate = null, System.Threading.CancellationToken cancellationToken = default); } diff --git a/src/Orc.NuGetExplorer/Extensions/IPackageInstallationServiceExtensions.cs b/src/Orc.NuGetExplorer/Extensions/IPackageInstallationServiceExtensions.cs deleted file mode 100644 index e7163fd7..00000000 --- a/src/Orc.NuGetExplorer/Extensions/IPackageInstallationServiceExtensions.cs +++ /dev/null @@ -1,42 +0,0 @@ -namespace Orc.NuGetExplorer; - -using System; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; -using MethodTimer; -using Models; -using NuGet.Packaging.Core; -using NuGet.Protocol.Core.Types; -using Services; - -public static class IPackageInstallationServiceExtensions -{ - [Time] - public static async Task InstallAsync( - this IPackageInstallationService service, - PackageIdentity package, - IExtensibleProject project, - IReadOnlyList repositories, - bool ignoreMissingPackages = false, - Func? packagePredicate = null, - CancellationToken cancellationToken = default) - { - ArgumentNullException.ThrowIfNull(service); - ArgumentNullException.ThrowIfNull(package); - ArgumentNullException.ThrowIfNull(project); - ArgumentNullException.ThrowIfNull(repositories); - - var context = new InstallationContext - { - Package = package, - Project = project, - Repositories = repositories, - IgnoreMissingPackages = ignoreMissingPackages, - PackagePredicate = packagePredicate, - }; - - return await service.InstallAsync(context, cancellationToken); - } - -} diff --git a/src/Orc.NuGetExplorer/Management/NuGetProjectPackageManager.cs b/src/Orc.NuGetExplorer/Management/NuGetProjectPackageManager.cs index 8a5526f4..28aee856 100644 --- a/src/Orc.NuGetExplorer/Management/NuGetProjectPackageManager.cs +++ b/src/Orc.NuGetExplorer/Management/NuGetProjectPackageManager.cs @@ -8,7 +8,6 @@ using Catel; using Catel.Logging; using Catel.Services; -using Models; using NuGet.Configuration; using NuGet.Packaging; using NuGet.Packaging.Core; diff --git a/src/Orc.NuGetExplorer/Models/InstallationContext.cs b/src/Orc.NuGetExplorer/Models/InstallationContext.cs index c8b44af9..f96e3fff 100644 --- a/src/Orc.NuGetExplorer/Models/InstallationContext.cs +++ b/src/Orc.NuGetExplorer/Models/InstallationContext.cs @@ -1,4 +1,4 @@ -namespace Orc.NuGetExplorer.Models; +namespace Orc.NuGetExplorer; using System; using System.Collections.Generic; diff --git a/src/Orc.NuGetExplorer/Services/Interfaces/IPackageInstallationService.cs b/src/Orc.NuGetExplorer/Services/Interfaces/IPackageInstallationService.cs index ddeea824..a6c4f541 100644 --- a/src/Orc.NuGetExplorer/Services/Interfaces/IPackageInstallationService.cs +++ b/src/Orc.NuGetExplorer/Services/Interfaces/IPackageInstallationService.cs @@ -7,7 +7,6 @@ using NuGet.Packaging; using NuGet.Packaging.Core; using NuGet.Protocol.Core.Types; -using Orc.NuGetExplorer.Models; public interface IPackageInstallationService { @@ -18,6 +17,15 @@ public interface IPackageInstallationService Task InstallAsync(InstallationContext context, CancellationToken cancellationToken = default); + [ObsoleteEx(ReplacementTypeOrMember = "InstallAsync(InstallationContext context, CancellationToken cancellationToken = default)", TreatAsErrorFromVersion = "6", RemoveInVersion = "7")] + public Task InstallAsync( + PackageIdentity package, + IExtensibleProject project, + IReadOnlyList repositories, + bool ignoreMissingPackages = false, + Func? packagePredicate = null, + CancellationToken cancellationToken = default); + Task UninstallAsync(PackageIdentity package, IExtensibleProject project, IEnumerable installedPackageReferences, diff --git a/src/Orc.NuGetExplorer/Services/PackageInstallationService.cs b/src/Orc.NuGetExplorer/Services/PackageInstallationService.cs index 63e065ec..d809f73e 100644 --- a/src/Orc.NuGetExplorer/Services/PackageInstallationService.cs +++ b/src/Orc.NuGetExplorer/Services/PackageInstallationService.cs @@ -10,7 +10,6 @@ using Catel.IoC; using Catel.Logging; using MethodTimer; -using Models; using NuGet.Common; using NuGet.Configuration; using NuGet.Frameworks; @@ -92,6 +91,23 @@ public PackageInstallationService(IServiceLocator serviceLocator, public VersionFolderPathResolver InstallerPathResolver => _installerPathResolver; + [ObsoleteEx(ReplacementTypeOrMember = "InstallAsync(InstallationContext context, CancellationToken cancellationToken = default)", TreatAsErrorFromVersion = "6", RemoveInVersion = "7")] + public Task InstallAsync(PackageIdentity package, IExtensibleProject project, IReadOnlyList repositories, bool ignoreMissingPackages = false, Func? packagePredicate = null, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(package); + ArgumentNullException.ThrowIfNull(project); + ArgumentNullException.ThrowIfNull(repositories); + var context = new InstallationContext + { + Package = package, + Project = project, + Repositories = repositories, + IgnoreMissingPackages = ignoreMissingPackages, + PackagePredicate = packagePredicate, + }; + return InstallAsync(context, cancellationToken); + } + public async Task UninstallAsync(PackageIdentity package, IExtensibleProject project, IEnumerable installedPackageReferences, Func? packagePredicate = null, CancellationToken cancellationToken = default) { @@ -282,7 +298,7 @@ public async Task InstallAsync(InstallationContext context, Can { // Track packages which already installed and make sure only one version of package exists var resolver = new Resolver.PackageResolver(); - availablePackagesToInstall = await resolver.ResolveWithVersionOverrideAsync(resolverContext, project, DependencyBehavior.Ignore, + availablePackagesToInstall = await resolver.ResolveWithVersionOverrideAsync(resolverContext, project, DependencyBehavior.Highest, (project, conflict) => _fileSystemService.CreateDeleteme(conflict.PackageIdentity.Id, project.GetInstallPath(conflict.PackageIdentity)), cancellationToken); }