From ca9811061d9cee0148b70c94b7be3001c1566b53 Mon Sep 17 00:00:00 2001 From: glopesdev Date: Sat, 31 Aug 2024 11:07:05 +0100 Subject: [PATCH] Refactor package operations into common extensions --- Bonsai.Configuration/Bootstrapper.cs | 28 ++++-- .../PackageConfigurationUpdater.cs | 29 ++---- Bonsai.NuGet.Design/GalleryDialog.cs | 2 +- Bonsai.NuGet.Design/PackageManagerDialog.cs | 4 +- Bonsai.NuGet/Constants.cs | 1 + ...{PackageHelper.cs => PackageExtensions.cs} | 88 ++++++++++++++----- .../Search/LocalPackageTypeSearchResource.cs | 16 +--- Bonsai/EditorBootstrapper.cs | 7 +- 8 files changed, 100 insertions(+), 75 deletions(-) rename Bonsai.NuGet/{PackageHelper.cs => PackageExtensions.cs} (52%) diff --git a/Bonsai.Configuration/Bootstrapper.cs b/Bonsai.Configuration/Bootstrapper.cs index ac009eaed..b47a2aabf 100644 --- a/Bonsai.Configuration/Bootstrapper.cs +++ b/Bonsai.Configuration/Bootstrapper.cs @@ -8,6 +8,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Threading; using System.Threading.Tasks; namespace Bonsai.Configuration @@ -29,9 +30,9 @@ public LicenseAwarePackageManager PackageManager get { return packageManager; } } - protected virtual async Task RunPackageOperationAsync(Func operationFactory) + protected virtual async Task RunPackageOperationAsync(Func operationFactory, CancellationToken cancellationToken) { - await operationFactory(); + await operationFactory(cancellationToken); } static NuGetVersion ParseVersion(string version) @@ -52,7 +53,8 @@ public async Task RunAsync( NuGetFramework projectFramework, PackageConfiguration packageConfiguration, string bootstrapperPath, - PackageIdentity bootstrapperPackage) + PackageIdentity bootstrapperPackage, + CancellationToken cancellationToken = default) { const string OldExtension = ".old"; var backupExePath = bootstrapperPath + OldExtension; @@ -65,7 +67,7 @@ public async Task RunAsync( var missingPackages = GetMissingPackages(packageConfiguration, packageManager.LocalRepository).ToList(); if (missingPackages.Count > 0) { - async Task RestoreMissingPackages() + async Task RestoreMissingPackages(CancellationToken cancellationToken) { using var monitor = new PackageConfigurationUpdater( projectFramework, @@ -75,19 +77,23 @@ async Task RestoreMissingPackages() bootstrapperPackage); foreach (var package in missingPackages) { - await packageManager.StartRestorePackage(package.Id, ParseVersion(package.Version), projectFramework); + await packageManager.RestorePackageAsync( + package.Id, + ParseVersion(package.Version), + projectFramework, + cancellationToken); } }; packageManager.RestorePackages = true; - try { await RunPackageOperationAsync(RestoreMissingPackages); } + try { await RunPackageOperationAsync(RestoreMissingPackages, cancellationToken); } finally { packageManager.RestorePackages = false; } } var editorPackage = packageManager.LocalRepository.FindLocalPackage(bootstrapperPackage.Id); if (editorPackage == null || editorPackage.Identity.Version < bootstrapperPackage.Version) { - async Task RestoreEditorPackage() + async Task RestoreEditorPackage(CancellationToken cancellationToken) { using var monitor = new PackageConfigurationUpdater( projectFramework, @@ -95,11 +101,15 @@ async Task RestoreEditorPackage() packageManager, bootstrapperPath, bootstrapperPackage); - var package = await packageManager.StartInstallPackage(bootstrapperPackage.Id, bootstrapperPackage.Version, projectFramework); + var package = await packageManager.InstallPackageAsync( + bootstrapperPackage.Id, + bootstrapperPackage.Version, + projectFramework, + cancellationToken); editorPackage = packageManager.LocalRepository.GetLocalPackage(package.GetIdentity()); }; - await RunPackageOperationAsync(RestoreEditorPackage); + await RunPackageOperationAsync(RestoreEditorPackage, cancellationToken); } } diff --git a/Bonsai.Configuration/PackageConfigurationUpdater.cs b/Bonsai.Configuration/PackageConfigurationUpdater.cs index db7fb95c3..77c829d2f 100644 --- a/Bonsai.Configuration/PackageConfigurationUpdater.cs +++ b/Bonsai.Configuration/PackageConfigurationUpdater.cs @@ -19,12 +19,8 @@ namespace Bonsai.Configuration { public class PackageConfigurationUpdater : IDisposable { - const string PackageTagFilter = "Bonsai"; - const string GalleryDirectory = "Gallery"; - const string ExtensionsDirectory = "Extensions"; const string BinDirectory = "bin"; const string DebugDirectory = "debug"; - const string BonsaiExtension = ".bonsai"; const string AssemblyExtension = ".dll"; const string OldExtension = ".old"; @@ -55,7 +51,7 @@ public PackageConfigurationUpdater(NuGetFramework projectFramework, PackageConfi configurationPlugin = new PackageConfigurationPlugin(this); packageManager.PackageManagerPlugins.Add(configurationPlugin); - var galleryPath = Path.Combine(bootstrapperDirectory, GalleryDirectory); + var galleryPath = Path.Combine(bootstrapperDirectory, Constants.GalleryDirectory); var galleryPackageSource = new PackageSource(galleryPath); galleryRepository = new SourceRepository(galleryPackageSource, Repository.Provider.GetCoreV3()); NormalizePathSeparators(packageConfiguration); @@ -92,12 +88,6 @@ static void NormalizePathSeparators(PackageConfiguration configuration) } } - static bool IsTaggedPackage(PackageReaderBase package) - { - var tags = package.NuspecReader.GetTags(); - return tags != null && tags.Contains(PackageTagFilter); - } - static ProcessorArchitecture ResolveArchitectureAlias(string name) { switch (name) @@ -410,10 +400,7 @@ public PackageConfigurationPlugin(PackageConfigurationUpdater owner) public override async Task OnPackageInstallingAsync(PackageIdentity package, NuGetFramework projectFramework, PackageReaderBase packageReader, string installPath) { - var entryPoint = package.Id + BonsaiExtension; - var nearestFrameworkGroup = packageReader.GetContentItems().GetNearest(projectFramework); - var executablePackage = nearestFrameworkGroup?.Items.Any(file => PathUtility.GetRelativePath(ContentFolder, file) == entryPoint); - if (executablePackage.GetValueOrDefault()) + if (packageReader.IsExecutablePackage(package, projectFramework)) { var packageFolder = Path.GetDirectoryName(packageReader.GetNuspecFile()); var resolver = new VersionFolderPathResolver(packageFolder, isLowercase: false); @@ -461,7 +448,7 @@ public override async Task OnPackageInstallingAsync(PackageIdentity packag public override Task OnPackageInstalledAsync(PackageIdentity package, NuGetFramework projectFramework, PackageReaderBase packageReader, string installPath) { var packageConfiguration = Owner.packageConfiguration; - var taggedPackage = IsTaggedPackage(packageReader); + var addReferences = packageReader.IsLibraryPackage(); var relativePath = Owner.GetRelativePath(installPath); if (!packageConfiguration.Packages.Contains(package.Id)) { @@ -469,7 +456,7 @@ public override Task OnPackageInstalledAsync(PackageIdentity package, NuGetFrame } else packageConfiguration.Packages[package.Id].Version = package.Version.ToString(); - Owner.AddContentFolders(installPath, ExtensionsDirectory); + Owner.AddContentFolders(installPath, Constants.ExtensionsDirectory); Owner.RegisterLibraryFolders(packageReader, relativePath); Owner.RegisterAssemblyLocations(packageReader, installPath, relativePath, false); if (IsRunningOnMono) Owner.AddAssemblyConfigFiles(packageReader, installPath); @@ -494,7 +481,7 @@ public override Task OnPackageInstalledAsync(PackageIdentity package, NuGetFrame // resolution is OS-specific and architecture-specific and should not be versioned together // with the package dependency graph. var assemblyLocations = GetCompatibleAssemblyReferences(projectFramework, packageReader); - Owner.RegisterAssemblyLocations(assemblyLocations, installPath, relativePath, taggedPackage); + Owner.RegisterAssemblyLocations(assemblyLocations, installPath, relativePath, addReferences); packageConfiguration.Save(); if (package.Id == Owner.bootstrapperPackageId && package.Version > Owner.bootstrapperVersion) @@ -516,11 +503,11 @@ public override Task OnPackageInstalledAsync(PackageIdentity package, NuGetFrame public override async Task OnPackageUninstalledAsync(PackageIdentity package, NuGetFramework projectFramework, PackageReaderBase packageReader, string installPath) { - var taggedPackage = IsTaggedPackage(packageReader); + var removeReferences = packageReader.IsLibraryPackage(); var relativePath = Owner.GetRelativePath(installPath); Owner.packageConfiguration.Packages.Remove(package.Id); - Owner.RemoveContentFolders(packageReader, installPath, ExtensionsDirectory); + Owner.RemoveContentFolders(packageReader, installPath, Constants.ExtensionsDirectory); Owner.RemoveLibraryFolders(packageReader, relativePath); Owner.RemoveAssemblyLocations(packageReader, relativePath, false); if (IsRunningOnMono) Owner.RemoveAssemblyConfigFiles(packageReader, installPath); @@ -541,7 +528,7 @@ public override async Task OnPackageUninstalledAsync(PackageIdentity package, Nu } var assemblyLocations = GetCompatibleAssemblyReferences(projectFramework, packageReader); - Owner.RemoveAssemblyLocations(assemblyLocations, relativePath, taggedPackage); + Owner.RemoveAssemblyLocations(assemblyLocations, relativePath, removeReferences); Owner.packageConfiguration.Save(); if (pivots.Length > 0) diff --git a/Bonsai.NuGet.Design/GalleryDialog.cs b/Bonsai.NuGet.Design/GalleryDialog.cs index f25276bc6..e970822c7 100644 --- a/Bonsai.NuGet.Design/GalleryDialog.cs +++ b/Bonsai.NuGet.Design/GalleryDialog.cs @@ -123,7 +123,7 @@ public override Task OnPackageInstallingAsync(PackageIdentity package, NuG { if (PackageIdentityComparer.Default.Equals(package, Owner.targetPackage)) { - Owner.InstallPath = PackageHelper.InstallExecutablePackage(package, projectFramework, packageReader, Owner.targetPath); + Owner.InstallPath = packageReader.InstallExecutablePackage(package, projectFramework, Owner.targetPath); Owner.DialogResult = DialogResult.OK; } diff --git a/Bonsai.NuGet.Design/PackageManagerDialog.cs b/Bonsai.NuGet.Design/PackageManagerDialog.cs index 0947903e3..db6af30ce 100644 --- a/Bonsai.NuGet.Design/PackageManagerDialog.cs +++ b/Bonsai.NuGet.Design/PackageManagerDialog.cs @@ -192,7 +192,7 @@ public ExecutablePackagePlugin(PackageManagerDialog owner) public override Task OnPackageInstallingAsync(PackageIdentity package, NuGetFramework projectFramework, PackageReaderBase packageReader, string installPath) { - if (PackageHelper.IsExecutablePackage(package, projectFramework, packageReader)) + if (packageReader.IsExecutablePackage(package, projectFramework)) { Owner.Invoke((Action)(() => { @@ -204,7 +204,7 @@ public override Task OnPackageInstallingAsync(PackageIdentity package, NuG if (Owner.saveFolderDialog.ShowDialog(Owner) == DialogResult.OK) { var targetPath = Owner.saveFolderDialog.FileName; - Owner.InstallPath = PackageHelper.InstallExecutablePackage(package, projectFramework, packageReader, targetPath); + Owner.InstallPath = packageReader.InstallExecutablePackage(package, projectFramework, targetPath); Owner.DialogResult = DialogResult.OK; } } diff --git a/Bonsai.NuGet/Constants.cs b/Bonsai.NuGet/Constants.cs index 02703fb33..0deb1ebc7 100644 --- a/Bonsai.NuGet/Constants.cs +++ b/Bonsai.NuGet/Constants.cs @@ -4,6 +4,7 @@ public static class Constants { public const string BonsaiDirectory = "Bonsai"; public const string GalleryDirectory = "Gallery"; + public const string ExtensionsDirectory = "Extensions"; public const string BonsaiExtension = ".bonsai"; public const string LayoutExtension = ".layout"; public const string LibraryPackageType = "BonsaiLibrary"; diff --git a/Bonsai.NuGet/PackageHelper.cs b/Bonsai.NuGet/PackageExtensions.cs similarity index 52% rename from Bonsai.NuGet/PackageHelper.cs rename to Bonsai.NuGet/PackageExtensions.cs index 30bb95611..a43098e4f 100644 --- a/Bonsai.NuGet/PackageHelper.cs +++ b/Bonsai.NuGet/PackageExtensions.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading; @@ -9,23 +10,63 @@ using NuGet.Frameworks; using NuGet.Packaging; using NuGet.Packaging.Core; +using NuGet.Protocol; using NuGet.Versioning; namespace Bonsai.NuGet { - public static class PackageHelper + public static class PackageExtensions { + const string PackageTagFilter = "Bonsai"; public static readonly string ContentFolder = PathUtility.EnsureTrailingSlash(PackagingConstants.Folders.Content); - public static bool IsExecutablePackage(PackageIdentity package, NuGetFramework projectFramework, PackageReaderBase packageReader) + public static bool IsPackageType(this LocalPackageInfo packageInfo, string typeName) { - var entryPoint = package.Id + Constants.BonsaiExtension; + return packageInfo.Nuspec.IsPackageType(typeName); + } + + public static bool IsPackageType(this PackageReaderBase packageReader, string typeName) + { + return packageReader.NuspecReader.IsPackageType(typeName); + } + + public static bool IsPackageType(this NuspecReader reader, string typeName) + { + return reader.GetPackageTypes().IsPackageType(typeName); + } + + public static bool IsPackageType(this IReadOnlyList packageTypes, string typeName) + { + if (packageTypes.Count == 0 + && PackageType.PackageTypeNameComparer.Equals(typeName, PackageType.Dependency.Name)) + { + return true; + } + + return packageTypes.Any(type => PackageType.PackageTypeNameComparer.Equals(type.Name, typeName)); + } + + public static bool IsLibraryPackage(this PackageReaderBase packageReader) + { + return packageReader.IsPackageType(Constants.LibraryPackageType) + || packageReader.NuspecReader.GetTags()?.Contains(PackageTagFilter) is true; + } + + public static bool IsGalleryPackage(this PackageReaderBase packageReader) + { + return packageReader.IsPackageType(Constants.GalleryPackageType) + || packageReader.NuspecReader.GetTags()?.Contains(PackageTagFilter) is true; + } + + public static bool IsExecutablePackage(this PackageReaderBase packageReader, PackageIdentity identity, NuGetFramework projectFramework) + { + var entryPoint = identity.Id + Constants.BonsaiExtension; var nearestFrameworkGroup = packageReader.GetContentItems().GetNearest(projectFramework); - var executablePackage = nearestFrameworkGroup?.Items.Any(file => PathUtility.GetRelativePath(PackageHelper.ContentFolder, file) == entryPoint); - return executablePackage.GetValueOrDefault(); + var executablePackage = nearestFrameworkGroup?.Items.Any(file => PathUtility.GetRelativePath(ContentFolder, file) == entryPoint); + return IsGalleryPackage(packageReader) && executablePackage.GetValueOrDefault(); } - public static string InstallExecutablePackage(PackageIdentity package, NuGetFramework projectFramework, PackageReaderBase packageReader, string targetPath) + public static string InstallExecutablePackage(this PackageReaderBase packageReader, PackageIdentity package, NuGetFramework projectFramework, string targetPath) { var targetId = Path.GetFileName(targetPath); var targetEntryPoint = targetId + Constants.BonsaiExtension; @@ -71,30 +112,29 @@ public static string InstallExecutablePackage(PackageIdentity package, NuGetFram return effectiveEntryPoint; } - public static async Task StartInstallPackage(this IPackageManager packageManager, PackageIdentity package, NuGetFramework projectFramework) - { - if (package == null) - { - throw new ArgumentNullException(nameof(package)); - } - - packageManager.Logger.LogInformation(string.Format(Resources.InstallPackageVersion, package.Id, package.Version)); - await packageManager.InstallPackageAsync(package, projectFramework, ignoreDependencies: false, CancellationToken.None); - } - - public static async Task StartInstallPackage(this IPackageManager packageManager, string packageId, NuGetVersion version, NuGetFramework projectFramework) + public static async Task InstallPackageAsync( + this IPackageManager packageManager, + string packageId, + NuGetVersion version, + NuGetFramework projectFramework, + CancellationToken cancellationToken = default) { - var logMessage = version == null ? Resources.InstallPackageLatestVersion : Resources.InstallPackageVersion; - packageManager.Logger.LogInformation(string.Format(logMessage, packageId, version)); var package = new PackageIdentity(packageId, version); - return await packageManager.InstallPackageAsync(package, projectFramework, ignoreDependencies: false, CancellationToken.None); + var logMessage = package.Version == null ? Resources.InstallPackageLatestVersion : Resources.InstallPackageVersion; + packageManager.Logger.LogInformation(string.Format(logMessage, package.Id, package.Version)); + return await packageManager.InstallPackageAsync(package, projectFramework, ignoreDependencies: false, cancellationToken); } - public static async Task StartRestorePackage(this IPackageManager packageManager, string packageId, NuGetVersion version, NuGetFramework projectFramework) + public static async Task RestorePackageAsync( + this IPackageManager packageManager, + string packageId, + NuGetVersion version, + NuGetFramework projectFramework, + CancellationToken cancellationToken = default) { - packageManager.Logger.LogInformation(string.Format(Resources.RestorePackageVersion, packageId, version)); var package = new PackageIdentity(packageId, version); - return await packageManager.InstallPackageAsync(package, projectFramework, ignoreDependencies: true, CancellationToken.None); + packageManager.Logger.LogInformation(string.Format(Resources.RestorePackageVersion, packageId, version)); + return await packageManager.InstallPackageAsync(package, projectFramework, ignoreDependencies: true, cancellationToken); } } } diff --git a/Bonsai.NuGet/Search/LocalPackageTypeSearchResource.cs b/Bonsai.NuGet/Search/LocalPackageTypeSearchResource.cs index 2fe194f5e..1bb6b3d66 100644 --- a/Bonsai.NuGet/Search/LocalPackageTypeSearchResource.cs +++ b/Bonsai.NuGet/Search/LocalPackageTypeSearchResource.cs @@ -55,20 +55,6 @@ public FindLocalPackageWrapperResource(FindLocalPackagesResource localResource, public string PackageTypeFilter { get; } - private bool MatchesPackageType(LocalPackageInfo package) - { - var packageTypes = package.Nuspec.GetPackageTypes(); - if (packageTypes.Count == 0 - && PackageType.PackageTypeNameComparer.Equals(PackageTypeFilter, PackageType.Dependency.Name)) - { - return true; - } - - return package.Nuspec - .GetPackageTypes() - .Any(packageType => PackageType.PackageTypeNameComparer.Equals(packageType.Name, PackageTypeFilter)); - } - public override IEnumerable FindPackagesById(string id, ILogger logger, CancellationToken token) { return baseLocalResource.FindPackagesById(id, logger, token); @@ -89,7 +75,7 @@ public override IEnumerable GetPackages(ILogger logger, Cancel var result = baseLocalResource.GetPackages(logger, token); if (!string.IsNullOrEmpty(PackageTypeFilter)) { - result = result.Where(MatchesPackageType); + result = result.Where(package => package.IsPackageType(PackageTypeFilter)); } return result; } diff --git a/Bonsai/EditorBootstrapper.cs b/Bonsai/EditorBootstrapper.cs index efa049f83..10d34d93d 100644 --- a/Bonsai/EditorBootstrapper.cs +++ b/Bonsai/EditorBootstrapper.cs @@ -2,6 +2,7 @@ using Bonsai.NuGet; using Bonsai.NuGet.Design; using System; +using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; @@ -30,7 +31,7 @@ public EditorBootstrapper(string path) PackageManager.Logger = new EventLogger(); } - protected override Task RunPackageOperationAsync(Func operationFactory) + protected override Task RunPackageOperationAsync(Func operationFactory, CancellationToken cancellationToken) { EnableVisualStyles(); EventHandler requiringLicenseHandler = null; @@ -49,7 +50,7 @@ protected override Task RunPackageOperationAsync(Func operationFactory) PackageManager.RequiringLicenseAcceptance += requiringLicenseHandler; try { - var operation = operationFactory(); + var operation = operationFactory(cancellationToken); operation.ContinueWith(task => { if (task.IsFaulted) @@ -60,7 +61,7 @@ protected override Task RunPackageOperationAsync(Func operationFactory) } } else dialog.BeginInvoke((Action)dialog.Close); - }); + }, cancellationToken); dialog.ShowDialog(); return operation; }