| File: GenerateRuntimeDependencies.cs | Web Access |
| Project: src\arcade\src\Microsoft.DotNet.Build.Tasks.Packaging\src\Microsoft.DotNet.Build.Tasks.Packaging.csproj (Microsoft.DotNet.Build.Tasks.Packaging) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using Microsoft.Build.Framework; using Newtonsoft.Json; using NuGet.RuntimeModel; using NuGet.Versioning; using System; using System.Collections.Generic; using System.IO; using System.Linq; namespace Microsoft.DotNet.Build.Tasks.Packaging { public class GenerateRuntimeDependencies : BuildTask { private const string c_emptyDependency = "none"; [Required] public ITaskItem[] Dependencies { get; set; } [Required] public string PackageId { get; set; } public ITaskItem RuntimeJsonTemplate { get; set; } [Required] public ITaskItem RuntimeJson { get; set; } public override bool Execute() { if (Dependencies == null || Dependencies.Length == 0) { Log.LogError("Dependencies argument must be specified"); return false; } if (String.IsNullOrEmpty(PackageId)) { Log.LogError("PackageID argument must be specified"); return false; } if (RuntimeJson == null) { Log.LogError("RuntimeJson argument must be specified"); return false; } string sourceRuntimeFilePath = null; if (RuntimeJsonTemplate != null) { sourceRuntimeFilePath = RuntimeJsonTemplate.GetMetadata("FullPath"); } string destRuntimeFilePath = RuntimeJson.GetMetadata("FullPath"); Dictionary<string, string> packageAliases = new Dictionary<string, string>(); foreach (var dependency in Dependencies) { string alias = dependency.GetMetadata("PackageAlias"); if (String.IsNullOrEmpty(alias)) { continue; } Log.LogMessage(LogImportance.Low, "Aliasing {0} -> {1}", alias, dependency.ItemSpec); packageAliases[alias] = dependency.ItemSpec; } var runtimeGroups = Dependencies.GroupBy(d => d.GetMetadata("TargetRuntime")); List<RuntimeDescription> runtimes = new List<RuntimeDescription>(); foreach (var runtimeGroup in runtimeGroups) { string targetRuntimeId = runtimeGroup.Key; if (String.IsNullOrEmpty(targetRuntimeId)) { Log.LogMessage(LogImportance.Low, "Skipping dependencies {0} since they don't have a TargetRuntime.", String.Join(", ", runtimeGroup.Select(d => d.ItemSpec))); continue; } if (runtimeGroup.Any(d => d.ItemSpec == c_emptyDependency)) { runtimes.Add(new RuntimeDescription(targetRuntimeId)); continue; } List<RuntimeDependencySet> runtimeDependencySets = new List<RuntimeDependencySet>(); var targetPackageGroups = runtimeGroup.GroupBy(d => GetTargetPackageId(d, packageAliases)); foreach (var targetPackageGroup in targetPackageGroups) { string targetPackageId = targetPackageGroup.Key; List<RuntimePackageDependency> runtimePackageDependencies = new List<RuntimePackageDependency>(); var dependencyGroups = targetPackageGroup.GroupBy(d => d.ItemSpec); foreach (var dependencyGroup in dependencyGroups) { string dependencyId = dependencyGroup.Key; var dependencyVersions = dependencyGroup.Select(d => GetDependencyVersion(d)); var maxDependencyVersion = dependencyVersions.Max(); runtimePackageDependencies.Add(new RuntimePackageDependency(dependencyId, new VersionRange(maxDependencyVersion))); } runtimeDependencySets.Add(new RuntimeDependencySet(targetPackageId, runtimePackageDependencies)); } runtimes.Add(new RuntimeDescription(targetRuntimeId, runtimeDependencySets)); } RuntimeGraph runtimeGraph = new RuntimeGraph(runtimes); // read in existing JSON, if it was provided so that we preserve any // hand authored #imports or dependencies if (!String.IsNullOrEmpty(sourceRuntimeFilePath)) { RuntimeGraph existingGraph = JsonRuntimeFormat.ReadRuntimeGraph(sourceRuntimeFilePath); runtimeGraph = RuntimeGraph.Merge(existingGraph, runtimeGraph); } string destRuntimeFileDir = Path.GetDirectoryName(destRuntimeFilePath); if (!String.IsNullOrEmpty(destRuntimeFileDir) && !Directory.Exists(destRuntimeFileDir)) { Directory.CreateDirectory(destRuntimeFileDir); } NuGetUtility.WriteRuntimeGraph(destRuntimeFilePath, runtimeGraph); return true; } private string GetTargetPackageId(ITaskItem dependency, IDictionary<string, string> packageAliases) { string targetPackageId = dependency.GetMetadata("TargetPackage"); string targetPackageAlias = dependency.GetMetadata("TargetPackageAlias"); if (!String.IsNullOrEmpty(targetPackageAlias) && !packageAliases.TryGetValue(targetPackageAlias, out targetPackageId)) { Log.LogWarning("Dependency {0} specified TargetPackageAlias {1} but no package was found defining this alias.", dependency.ItemSpec, targetPackageAlias); } else { Log.LogMessage(LogImportance.Low, "Using {0} for TargetPackageAlias {1}", targetPackageId, targetPackageAlias); } if (String.IsNullOrEmpty(targetPackageId)) { Log.LogMessage(LogImportance.Low, "Dependency {0} has no parent so will assume {1}.", dependency.ItemSpec, PackageId); targetPackageId = PackageId; } return targetPackageId; } private NuGetVersion GetDependencyVersion(ITaskItem dependency) { NuGetVersion dependencyVersion; string dependencyVersionString = dependency.GetMetadata("version"); if (String.IsNullOrEmpty(dependencyVersionString)) { Log.LogWarning("Dependency {0} has no version", dependency.ItemSpec); dependencyVersion = new NuGetVersion(0, 0, 0); } else if (!NuGetVersion.TryParse(dependencyVersionString, out dependencyVersion)) { Log.LogError("Dependency {0} has invalid version {1}", dependency.ItemSpec, dependencyVersionString); dependencyVersion = new NuGetVersion(0, 0, 0); } return dependencyVersion; } } }