|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using NuGet.Client;
using NuGet.ContentModel;
using NuGet.Frameworks;
using NuGet.RuntimeModel;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
namespace Microsoft.DotNet.Build.Tasks.Packaging
{
public class NuGetAssetResolver
{
private ManagedCodeConventions _conventions;
private ContentItemCollection _sourceItems;
public const string PlaceHolderFile = "_._";
public NuGetAssetResolver(string runtimeFile, IEnumerable<string> packageItems)
{
RuntimeGraph runtimeGraph = null;
if (!string.IsNullOrEmpty(runtimeFile))
{
runtimeGraph = JsonRuntimeFormat.ReadRuntimeGraph(runtimeFile);
}
_conventions = new ManagedCodeConventions(runtimeGraph);
_sourceItems = new ContentItemCollection();
_sourceItems.Load(packageItems);
}
public ContentItemGroup GetCompileItems(NuGetFramework framework)
{
// don't use the RID for compile assets.
var managedCriteria = _conventions.Criteria.ForFramework(framework);
FixCriteria(managedCriteria);
// compile falls back to runtime pattern in the case of lib with no ref, this won't fallback
// to a runtime asset since we have no RID passed in.
return _sourceItems.FindBestItemGroup(managedCriteria,
_conventions.Patterns.CompileRefAssemblies,
_conventions.Patterns.RuntimeAssemblies);
}
public IEnumerable<string> ResolveCompileAssets(NuGetFramework framework)
{
// we only care about compile items from this package, runtime packages will
// never contribute compile items since the runtime graph is only used for runtime assets.
var compileItems = GetCompileItems(framework);
return (compileItems != null) ?
compileItems.Items.Select(ci => ci.Path) :
Enumerable.Empty<string>();
}
public ContentItemGroup GetRuntimeItems(NuGetFramework framework, string runtimeIdentifier)
{
var managedCriteria = _conventions.Criteria.ForFrameworkAndRuntime(framework, runtimeIdentifier);
FixCriteria(managedCriteria);
return _sourceItems.FindBestItemGroup(managedCriteria,
_conventions.Patterns.RuntimeAssemblies);
}
public IEnumerable<string> ResolveRuntimeAssets(NuGetFramework framework, string runtimeId)
{
var runtimeItems = GetRuntimeItems(framework, runtimeId);
return (runtimeItems != null) ?
runtimeItems.Items.Select(ci => ci.Path) :
Enumerable.Empty<string>();
}
public static void FixCriteria(SelectionCriteria criteria)
{
// workaround https://github.com/NuGet/Home/issues/1457
foreach (var criterium in criteria.Entries)
{
if (criterium.Properties.ContainsKey(ManagedCodeConventions.PropertyNames.TargetFrameworkMoniker) &&
!criterium.Properties.ContainsKey(ManagedCodeConventions.PropertyNames.RuntimeIdentifier))
{
criterium.Properties.Add(ManagedCodeConventions.PropertyNames.RuntimeIdentifier, null);
}
}
}
public static IEnumerable<string> GetPackageTargetDirectories(ContentItemGroup contentGroup)
{
if (contentGroup == null)
{
yield break;
}
foreach (var contentItem in contentGroup.Items)
{
// package paths are standardized to '/'
int dirLength = contentItem.Path.LastIndexOf(Path.AltDirectorySeparatorChar);
if (dirLength == -1)
{
yield return "";
}
else
{
yield return contentItem.Path.Substring(0, dirLength);
}
}
}
public static void ExamineAssets(ILog logger, string assetType, string package, string target, IEnumerable<string> items, out bool hasRealAsset, out bool hasPlaceHolder)
{
hasPlaceHolder = false;
hasRealAsset = false;
StringBuilder assetLog = new StringBuilder($"{assetType} assets for {package} on {target}: ");
if (items != null && items.Any())
{
foreach (var runtimeItem in items)
{
assetLog.AppendLine();
assetLog.Append($" {runtimeItem}");
if (!hasRealAsset && NuGetAssetResolver.IsPlaceholder(runtimeItem))
{
hasPlaceHolder = true;
}
else
{
hasRealAsset = true;
hasPlaceHolder = false;
}
}
}
else
{
assetLog.AppendLine();
assetLog.Append(" <none>");
}
logger.LogMessage(LogImportance.Low, assetLog.ToString());
}
public static bool IsPlaceholder(string path)
{
return Path.GetFileName(path) == PlaceHolderFile;
}
}
public class AggregateNuGetAssetResolver
{
private ManagedCodeConventions _conventions;
private Dictionary<string, ContentItemCollection> _packages;
public const string PlaceHolderFile = "_._";
public AggregateNuGetAssetResolver(string runtimeFile)
{
RuntimeGraph runtimeGraph = null;
if (!String.IsNullOrEmpty(runtimeFile))
{
runtimeGraph = JsonRuntimeFormat.ReadRuntimeGraph(runtimeFile);
}
_conventions = new ManagedCodeConventions(runtimeGraph);
_packages = new Dictionary<string, ContentItemCollection>();
}
public void AddPackageItems(string packageId, IEnumerable<string> packageItems)
{
if (!_packages.ContainsKey(packageId))
{
_packages[packageId] = new ContentItemCollection();
}
_packages[packageId].Load(packageItems);
}
public IReadOnlyDictionary<string, ContentItemGroup> GetCompileItems(NuGetFramework framework)
{
// don't use the RID for compile assets.
var managedCriteria = _conventions.Criteria.ForFramework(framework);
NuGetAssetResolver.FixCriteria(managedCriteria);
Dictionary<string, ContentItemGroup> resolvedAssets = new Dictionary<string, ContentItemGroup>();
// compile falls back to runtime pattern in the case of lib with no ref, this won't fallback
// to a runtime asset since we have no RID passed in.
foreach (var package in _packages.Keys)
{
resolvedAssets.Add(package,
_packages[package].FindBestItemGroup(managedCriteria,
_conventions.Patterns.CompileRefAssemblies,
_conventions.Patterns.RuntimeAssemblies));
}
return resolvedAssets;
}
public IEnumerable<string> ResolveCompileAssets(NuGetFramework framework, string referencePackageId)
{
// we only care about compile items from this package, runtime packages will
// never contribute compile items since the runtime graph is only used for runtime assets.
var allCompileItems = GetCompileItems(framework);
ContentItemGroup thisPackageCompileItems = null;
allCompileItems.TryGetValue(referencePackageId, out thisPackageCompileItems);
return (thisPackageCompileItems != null) ?
thisPackageCompileItems.Items.Select(ci => AsPackageSpecificTargetPath(referencePackageId, ci.Path)) :
Enumerable.Empty<string>();
}
public IEnumerable<string> ResolveCompileAssets(NuGetFramework framework)
{
var allCompileItems = GetCompileItems(framework);
foreach (var packageId in allCompileItems.Keys)
{
var packageAssets = allCompileItems[packageId];
if (packageAssets == null)
{
continue;
}
foreach (var packageAsset in packageAssets.Items)
{
yield return AsPackageSpecificTargetPath(packageId, packageAsset.Path);
}
}
}
public IReadOnlyDictionary<string, ContentItemGroup> GetRuntimeItems(NuGetFramework framework, string runtimeIdentifier)
{
var managedCriteria = _conventions.Criteria.ForFrameworkAndRuntime(framework, runtimeIdentifier);
NuGetAssetResolver.FixCriteria(managedCriteria);
Dictionary<string, ContentItemGroup> resolvedAssets = new Dictionary<string, ContentItemGroup>();
foreach (var package in _packages.Keys)
{
resolvedAssets.Add(package,
_packages[package].FindBestItemGroup(managedCriteria,
_conventions.Patterns.RuntimeAssemblies));
}
return resolvedAssets;
}
public IReadOnlyDictionary<string, ContentItemGroup> GetNativeItems(NuGetFramework framework, string runtimeIdentifier)
{
var managedCriteria = _conventions.Criteria.ForFrameworkAndRuntime(framework, runtimeIdentifier);
NuGetAssetResolver.FixCriteria(managedCriteria);
Dictionary<string, ContentItemGroup> resolvedAssets = new Dictionary<string, ContentItemGroup>();
foreach (var package in _packages.Keys)
{
resolvedAssets.Add(package,
_packages[package].FindBestItemGroup(managedCriteria,
_conventions.Patterns.NativeLibraries));
}
return resolvedAssets;
}
[Obsolete]
public IReadOnlyDictionary<string, IEnumerable<ContentItemGroup>> GetAllRuntimeItems()
{
Dictionary<string, IEnumerable<ContentItemGroup>> resolvedAssets = new Dictionary<string, IEnumerable<ContentItemGroup>>();
foreach (var package in _packages.Keys)
{
var contentItemGroups = new List<ContentItemGroup>();
_packages[package].PopulateItemGroups(_conventions.Patterns.RuntimeAssemblies, contentItemGroups);
resolvedAssets.Add(package, contentItemGroups);
}
return resolvedAssets;
}
public IEnumerable<string> ResolveRuntimeAssets(NuGetFramework framework, string runtimeId)
{
var allRuntimeItems = GetRuntimeItems(framework, runtimeId);
foreach (var packageId in allRuntimeItems.Keys)
{
var packageAssets = allRuntimeItems[packageId];
if (packageAssets == null)
{
continue;
}
foreach (var packageAsset in packageAssets.Items)
{
yield return AsPackageSpecificTargetPath(packageId, packageAsset.Path);
}
}
}
public IEnumerable<string> ResolveNativeAssets(NuGetFramework framework, string runtimeId)
{
var allNativeItems = GetNativeItems(framework, runtimeId);
foreach (var packageId in allNativeItems.Keys)
{
var packageAssets = allNativeItems[packageId];
if (packageAssets == null)
{
continue;
}
foreach (var packageAsset in packageAssets.Items)
{
yield return AsPackageSpecificTargetPath(packageId, packageAsset.Path);
}
}
}
public static string AsPackageSpecificTargetPath(string packageId, string targetPath)
{
return $"{packageId}/{targetPath}";
}
}
}
|