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); } JsonRuntimeFormat.WriteRuntimeGraph(destRuntimeFilePath, runtimeGraph); return(true); }
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); } RuntimeFileFormatter formatter = new RuntimeFileFormatter(); RuntimeFile runtimeFile = null; string sourceRuntimeFilePath = null; if (RuntimeJsonTemplate != null) { sourceRuntimeFilePath = RuntimeJsonTemplate.GetMetadata("FullPath"); } string destRuntimeFilePath = RuntimeJson.GetMetadata("FullPath"); // read in existing JSON, if it was provided so that we preserve any // hand authored #imports or dependencies if (!String.IsNullOrEmpty(sourceRuntimeFilePath)) { runtimeFile = formatter.ReadRuntimeFile(sourceRuntimeFilePath); } else { runtimeFile = new RuntimeFile(); } 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; } foreach (var dependency in Dependencies) { string targetRuntimeId = dependency.GetMetadata("TargetRuntime"); string targetPackageId = dependency.GetMetadata("TargetPackage"); string targetPackageAlias = dependency.GetMetadata("TargetPackageAlias"); string dependencyId = dependency.ItemSpec; string dependencyVersion = dependency.GetMetadata("version"); if (String.IsNullOrEmpty(targetRuntimeId)) { Log.LogMessage(LogImportance.Low, "Skipping dependency {0} since it doesn't have a TargetRuntime.", dependency.ItemSpec); continue; } 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); } RuntimeSpec targetRuntime = null; if (!runtimeFile.Runtimes.TryGetValue(targetRuntimeId, out targetRuntime)) { targetRuntime = new RuntimeSpec() { Name = targetRuntimeId }; runtimeFile.Runtimes.Add(targetRuntimeId, targetRuntime); } if (String.IsNullOrEmpty(targetPackageId)) { Log.LogMessage(LogImportance.Low, "Dependency {0} has no parent so will assume {1}.", dependency.ItemSpec, PackageId); targetPackageId = PackageId; } DependencySpec targetPackage = null; if (!targetRuntime.Dependencies.TryGetValue(targetPackageId, out targetPackage)) { targetPackage = new DependencySpec() { Name = targetPackageId }; targetRuntime.Dependencies.Add(targetPackageId, targetPackage); } if (dependencyId == c_emptyDependency) { targetPackage.Implementations.Clear(); } else { if (String.IsNullOrEmpty(dependencyVersion)) { Log.LogWarning("Dependency {0} has no version", dependency.ItemSpec); } ImplementationSpec existing; if (targetPackage.Implementations.TryGetValue(dependencyId, out existing)) { string newVersion = CompareSemanticVersion(dependencyVersion, existing.Version) > 0 ? dependencyVersion : existing.Version; Log.LogMessage(LogImportance.Low, "Dependency {0} has been added more than once, {1}, {2}, using {3}", dependencyId, existing.Version, dependencyVersion, newVersion); dependencyVersion = newVersion; } targetPackage.Implementations[dependencyId] = new ImplementationSpec() { Name = dependencyId, Version = dependencyVersion }; } } if (EnsureBase) { // RID base is used to lift the library packages up to a baseline version // we don't want to obscure these associations or else we may bring in // old reference packages prior to an implementation package split // and thus, clashing implementations. // EG: Version 1 of System.Banana had a single implementation that was // windows specific. // Version 2 split the implementation to Windows and Unix // If Version 1 was referenced we'd get both the V1 windows implementation // and the V2 unix implementation when resolving for Unix // To avoid this problem we always ensure that we have the matching // reference package in the runtime graph. RuntimeSpec baseRuntime = null; if (runtimeFile.Runtimes.TryGetValue("base", out baseRuntime)) { // look at all sections other than base foreach (var runtime in runtimeFile.Runtimes.Values.Where(rt => rt != baseRuntime)) { // examine each dependency and copy the content from base, if it exists foreach (var dependency in runtime.Dependencies) { string packageName = dependency.Key; DependencySpec packageDependencies = dependency.Value; // are there any entries for this package in base? DependencySpec baseDependencies = null; if (!baseRuntime.Dependencies.TryGetValue(dependency.Key, out baseDependencies)) { continue; } // copy all entries from base to this runtime foreach (var baseImplementation in baseDependencies.Implementations) { packageDependencies.Implementations.Add(baseImplementation.Key, baseImplementation.Value); } } } } } string destRuntimeFileDir = Path.GetDirectoryName(destRuntimeFilePath); if (!String.IsNullOrEmpty(destRuntimeFileDir) && !Directory.Exists(destRuntimeFileDir)) { Directory.CreateDirectory(destRuntimeFileDir); } formatter.WriteRuntimeFile(destRuntimeFilePath, runtimeFile); return(true); }