Skip to content

Commit

Permalink
Allow overlaying RID specific package dependencies
Browse files Browse the repository at this point in the history
Fixes #881
  • Loading branch information
glopesdev committed May 3, 2022
1 parent 5088a83 commit e2127af
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 29 deletions.
49 changes: 41 additions & 8 deletions Bonsai.Configuration/OverlayHelper.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
using Bonsai.NuGet;
using NuGet.Configuration;
using NuGet.Packaging;
using NuGet.Packaging.Core;
using NuGet.RuntimeModel;
using NuGet.Versioning;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
Expand All @@ -14,6 +17,22 @@ static class OverlayHelper
const string NuGetOverlayCommandFileName = "NuGet-Overlay.cmd";
const string NuGetOverlayCommand = "nuget overlay";
const string NuGetOverlayVersionArgument = "-Version";
static readonly string[] SupportedRuntimes = new[] { "win-x86", "win-x64" };

static RuntimeGraph GetRuntimeGraph(PackageReaderBase packageReader)
{
var runtimeGraphFilePath = packageReader.GetFiles().FirstOrDefault(path => string.Equals(
Path.GetFileName(path),
RuntimeGraph.RuntimeGraphFileName,
StringComparison.OrdinalIgnoreCase));
if (runtimeGraphFilePath != null)
{
var runtimeGraphStream = packageReader.GetStream(runtimeGraphFilePath);
return JsonRuntimeFormat.ReadRuntimeGraph(runtimeGraphStream);
}

return null;
}

static IEnumerable<string> ReadAllLines(Stream stream)
{
Expand All @@ -26,11 +45,11 @@ static IEnumerable<string> ReadAllLines(Stream stream)
}
}

public static NuGetVersion FindOverlayVersion(PackageReaderBase package)
static NuGetVersion FindOverlayVersion(PackageReaderBase packageReader)
{
return (from file in package.GetFiles()
return (from file in packageReader.GetFiles()
where Path.GetFileName(file) == NuGetOverlayCommandFileName
from line in ReadAllLines(package.GetStream(file))
from line in ReadAllLines(packageReader.GetStream(file))
where line.StartsWith(NuGetOverlayCommand)
let version = line.Split(' ')
.SkipWhile(xs => xs != NuGetOverlayVersionArgument)
Expand All @@ -39,12 +58,26 @@ where line.StartsWith(NuGetOverlayCommand)
select NuGetVersion.Parse(version)).FirstOrDefault();
}

public static IEnumerable<string> FindPivots(PackageReaderBase package, string installPath)
public static IEnumerable<PackageIdentity> FindPivots(PackageIdentity package, PackageReaderBase packageReader)
{
return from file in package.GetFiles()
where Path.GetFileName(file) == PivotListFileName
from pivot in ReadAllLines(package.GetStream(file))
select pivot;
var runtimeGraph = GetRuntimeGraph(packageReader);
if (runtimeGraph != null)
{
return from runtimeName in SupportedRuntimes
from dependency in runtimeGraph.FindRuntimeDependencies(runtimeName, package.Id)
select new PackageIdentity(dependency.Id, dependency.VersionRange.MinVersion);
}

var overlayVersion = FindOverlayVersion(packageReader);
if (overlayVersion != null)
{
return from file in packageReader.GetFiles()
where Path.GetFileName(file) == PivotListFileName
from pivot in ReadAllLines(packageReader.GetStream(file))
select new PackageIdentity(pivot, overlayVersion);
}

return Enumerable.Empty<PackageIdentity>();
}

public static PackageManager CreateOverlayManager(IPackageManager packageManager, string installPath)
Expand Down
52 changes: 32 additions & 20 deletions Bonsai.Configuration/PackageConfigurationUpdater.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ public class PackageConfigurationUpdater : IDisposable
const string PackageTagFilter = "Bonsai";
const string GalleryDirectory = "Gallery";
const string ExtensionsDirectory = "Extensions";
const string BuildDirectory = "build";
const string BinDirectory = "bin";
const string DebugDirectory = "debug";
const string BonsaiExtension = ".bonsai";
Expand All @@ -41,6 +40,7 @@ public class PackageConfigurationUpdater : IDisposable
static readonly string ContentFolder = PathUtility.EnsureTrailingSlash(PackagingConstants.Folders.Content);
static readonly char[] DirectorySeparators = new[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar };
static readonly NuGetFramework NativeFramework = NuGetFramework.ParseFrameworkName("native,Version=v0.0", DefaultFrameworkNameProvider.Instance);
static readonly NuGetFramework WindowsFramework = new NuGetFramework(FrameworkConstants.FrameworkIdentifiers.Windows, FrameworkConstants.EmptyVersion);

public PackageConfigurationUpdater(NuGetFramework projectFramework, PackageConfiguration configuration, IPackageManager manager, string bootstrapperPath = null, PackageIdentity bootstrapperName = null)
{
Expand All @@ -57,7 +57,6 @@ public PackageConfigurationUpdater(NuGetFramework projectFramework, PackageConfi
var galleryPath = Path.Combine(bootstrapperDirectory, GalleryDirectory);
var galleryPackageSource = new PackageSource(galleryPath);
galleryRepository = new SourceRepository(galleryPackageSource, Repository.Provider.GetCoreV3());
bootstrapperFramework = projectFramework;
}

string GetRelativePath(string path)
Expand Down Expand Up @@ -117,7 +116,7 @@ static string ResolvePathPlatformName(string path)

static IEnumerable<string> GetAssemblyLocations(NuGetFramework projectFramework, PackageReaderBase package)
{
var nearestFramework = package.GetItems(BuildDirectory).GetNearest(projectFramework);
var nearestFramework = package.GetItems(PackagingConstants.Folders.Build).GetNearest(projectFramework);
if (nearestFramework == null) return Enumerable.Empty<string>();

return from file in nearestFramework.Items
Expand All @@ -128,7 +127,14 @@ where Path.GetExtension(file) == AssemblyExtension &&

static IEnumerable<LibraryFolder> GetLibraryFolders(PackageReaderBase package, string installPath)
{
var nativeFramework = package.GetItems(BuildDirectory).FirstOrDefault(
var buildFolders = GetBuildLibraryFolders(package, installPath);
var runtimeFolders = GetRuntimeLibraryFolders(package, installPath);
return buildFolders.Concat(runtimeFolders);
}

static IEnumerable<LibraryFolder> GetBuildLibraryFolders(PackageReaderBase package, string installPath)
{
var nativeFramework = package.GetItems(PackagingConstants.Folders.Build).FirstOrDefault(
frameworkGroup => NuGetFramework.FrameworkNameComparer.Equals(frameworkGroup.TargetFramework, NativeFramework));
if (nativeFramework == null) return Enumerable.Empty<LibraryFolder>();

Expand All @@ -139,6 +145,17 @@ group file by Path.GetDirectoryName(file) into folder
select new LibraryFolder(Path.Combine(installPath, folder.Key), platform);
}

static IEnumerable<LibraryFolder> GetRuntimeLibraryFolders(PackageReaderBase package, string installPath)
{
return from frameworkGroup in package.GetItems(PackagingConstants.Folders.Runtimes)
where NuGetFramework.FrameworkNameComparer.Equals(frameworkGroup.TargetFramework, WindowsFramework)
let platform = frameworkGroup.TargetFramework.Profile
where !string.IsNullOrWhiteSpace(platform)
from file in frameworkGroup.Items
group file by new { platform, path = Path.GetDirectoryName(file) } into folder
select new LibraryFolder(Path.Combine(installPath, folder.Key.path), folder.Key.platform);
}

static IEnumerable<string> GetCompatibleAssemblyReferences(NuGetFramework projectFramework, PackageReaderBase package)
{
var nearestFramework = package.GetReferenceItems().GetNearest(projectFramework);
Expand Down Expand Up @@ -304,7 +321,7 @@ public PackageConfigurationPlugin(PackageConfigurationUpdater owner)
public override async Task<bool> OnPackageInstallingAsync(PackageIdentity package, NuGetFramework projectFramework, PackageReaderBase packageReader, string installPath)
{
var entryPoint = package.Id + BonsaiExtension;
var nearestFrameworkGroup = packageReader.GetContentItems().GetNearest(Owner.bootstrapperFramework);
var nearestFrameworkGroup = packageReader.GetContentItems().GetNearest(projectFramework);
var executablePackage = nearestFrameworkGroup?.Items.Any(file => PathUtility.GetRelativePath(ContentFolder, file) == entryPoint);
if (executablePackage.GetValueOrDefault())
{
Expand All @@ -323,28 +340,25 @@ public override async Task<bool> OnPackageInstallingAsync(PackageIdentity packag
}
else
{
var pivots = OverlayHelper.FindPivots(packageReader, installPath).ToArray();
var pivots = OverlayHelper.FindPivots(package, packageReader).ToArray();
if (pivots.Length > 0)
{
PathUtility.EnsureParentDirectory(Path.Combine(installPath, package.Id));
var overlayVersion = OverlayHelper.FindOverlayVersion(packageReader);
var overlayManager = OverlayHelper.CreateOverlayManager(Owner.packageManager, installPath);
overlayManager.Logger = Owner.packageManager.Logger;
try
{
foreach (var pivot in pivots)
{
var pivotIdentity = new PackageIdentity(pivot, overlayVersion);
var pivotPackage = await overlayManager.InstallPackageAsync(pivotIdentity, projectFramework, ignoreDependencies: true, CancellationToken.None);
var pivotPackage = await overlayManager.InstallPackageAsync(pivot, projectFramework, ignoreDependencies: true, CancellationToken.None);
if (pivotPackage == null) throw new InvalidOperationException(string.Format("The package '{0}' could not be found.", pivot));
}
}
catch
{
foreach (var pivot in pivots)
{
var pivotIdentity = new PackageIdentity(pivot, overlayVersion);
await overlayManager.UninstallPackageAsync(pivotIdentity, projectFramework, removeDependencies: false, CancellationToken.None);
await overlayManager.UninstallPackageAsync(pivot, projectFramework, removeDependencies: false, CancellationToken.None);
}
throw;
}
Expand All @@ -368,20 +382,20 @@ public override Task OnPackageInstalledAsync(PackageIdentity package, NuGetFrame
Owner.AddContentFolders(installPath, ExtensionsDirectory);
Owner.RegisterLibraryFolders(packageReader, relativePath);
Owner.RegisterAssemblyLocations(packageReader, installPath, relativePath, false);
var pivots = OverlayHelper.FindPivots(packageReader, installPath).ToArray();
var pivots = OverlayHelper.FindPivots(package, packageReader).ToArray();
if (pivots.Length > 0)
{
var overlayManager = OverlayHelper.CreateOverlayManager(Owner.packageManager, installPath);
foreach (var pivot in pivots)
{
var pivotPackage = overlayManager.LocalRepository.FindLocalPackage(pivot);
var pivotPackage = overlayManager.LocalRepository.FindLocalPackage(pivot.Id);
using var pivotReader = pivotPackage.GetReader();
Owner.RegisterLibraryFolders(pivotReader, relativePath);
Owner.RegisterAssemblyLocations(pivotReader, installPath, relativePath, false);
}
}

var assemblyLocations = GetCompatibleAssemblyReferences(Owner.bootstrapperFramework, packageReader);
var assemblyLocations = GetCompatibleAssemblyReferences(projectFramework, packageReader);
Owner.RegisterAssemblyLocations(assemblyLocations, installPath, relativePath, taggedPackage);
packageConfiguration.Save();

Expand Down Expand Up @@ -411,13 +425,13 @@ public override async Task OnPackageUninstalledAsync(PackageIdentity package, Nu
Owner.RemoveContentFolders(packageReader, installPath, ExtensionsDirectory);
Owner.RemoveLibraryFolders(packageReader, relativePath);
Owner.RemoveAssemblyLocations(packageReader, relativePath, false);
var pivots = OverlayHelper.FindPivots(packageReader, installPath).ToArray();
var pivots = OverlayHelper.FindPivots(package, packageReader).ToArray();
if (pivots.Length > 0)
{
var overlayManager = OverlayHelper.CreateOverlayManager(Owner.packageManager, installPath);
foreach (var pivot in pivots)
{
var pivotPackage = overlayManager.LocalRepository.FindLocalPackage(pivot);
var pivotPackage = overlayManager.LocalRepository.FindLocalPackage(pivot.Id);
if (pivotPackage != null)
{
using var pivotReader = pivotPackage.GetReader();
Expand All @@ -427,19 +441,17 @@ public override async Task OnPackageUninstalledAsync(PackageIdentity package, Nu
}
}

var assemblyLocations = GetCompatibleAssemblyReferences(Owner.bootstrapperFramework, packageReader);
var assemblyLocations = GetCompatibleAssemblyReferences(projectFramework, packageReader);
Owner.RemoveAssemblyLocations(assemblyLocations, relativePath, taggedPackage);
Owner.packageConfiguration.Save();

if (pivots.Length > 0)
{
var overlayVersion = OverlayHelper.FindOverlayVersion(packageReader);
var overlayManager = OverlayHelper.CreateOverlayManager(Owner.packageManager, installPath);
overlayManager.Logger = Owner.packageManager.Logger;
foreach (var pivot in pivots)
{
var pivotIdentity = new PackageIdentity(pivot, overlayVersion);
await overlayManager.UninstallPackageAsync(pivotIdentity, projectFramework, removeDependencies: false, CancellationToken.None);
await overlayManager.UninstallPackageAsync(pivot, projectFramework, removeDependencies: false, CancellationToken.None);
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion Bonsai/Bonsai.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<PackageTags>Bonsai Rx Reactive Extensions</PackageTags>
<UseWindowsForms>true</UseWindowsForms>
<TargetFramework>net472</TargetFramework>
<Version>2.6.3</Version>
<Version>2.7.0</Version>
<OutputType>Exe</OutputType>
<DisableWinExeOutputInference>true</DisableWinExeOutputInference>
<ApplicationIcon>..\Bonsai.Editor\Bonsai.ico</ApplicationIcon>
Expand Down

0 comments on commit e2127af

Please sign in to comment.