| File: src\sdk\src\Resolvers\Microsoft.NET.Sdk.WorkloadManifestReader\WorkloadSet.cs | Web Access |
| Project: src\sdk\src\Tasks\Microsoft.NET.Build.Tasks\Microsoft.NET.Build.Tasks.csproj (Microsoft.NET.Build.Tasks) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Text.Json; using Microsoft.DotNet.MSBuildSdkResolver; using Strings = Microsoft.NET.Sdk.Localization.Strings; namespace Microsoft.NET.Sdk.WorkloadManifestReader { public class WorkloadSet { public Dictionary<ManifestId, (ManifestVersion Version, SdkFeatureBand FeatureBand)> ManifestVersions = new(); // TODO: Generate version from hash of manifest versions if not otherwise set public string? Version { get; set; } // Indicates that a workload set is a baseline workload set that was installed with the .NET SDK. // It should not be subject to normal garbage collection unless the SDK that installed it is removed public bool IsBaselineWorkloadSet { get; set; } public static WorkloadSet FromManifests(IEnumerable<WorkloadManifestInfo> manifests) { return new WorkloadSet() { ManifestVersions = manifests.ToDictionary(m => new ManifestId(m.Id), m => (new ManifestVersion(m.Version), new SdkFeatureBand(m.ManifestFeatureBand))) }; } public static WorkloadSet FromDictionaryForJson(IDictionary<string, string?> dictionary, SdkFeatureBand defaultFeatureBand) { var manifestVersions = dictionary .Select(manifest => { ManifestVersion manifestVersion; SdkFeatureBand manifestFeatureBand; var parts = manifest.Value?.Split('/'); string manifestVersionString = string.Empty; if (parts != null) { manifestVersionString = parts[0]; } if (!FXVersion.TryParse(manifestVersionString, out FXVersion? version)) { throw new FormatException(string.Format(Strings.InvalidVersionForWorkload, manifest.Key, manifestVersionString)); } manifestVersion = new ManifestVersion(parts?[0]); if (parts != null && parts.Length == 1) { manifestFeatureBand = defaultFeatureBand; } else { manifestFeatureBand = new SdkFeatureBand(parts?[1]); } return (id: new ManifestId(manifest.Key), manifestVersion, manifestFeatureBand); }).ToDictionary(t => t.id, t => (t.manifestVersion, t.manifestFeatureBand)); return new WorkloadSet() { ManifestVersions = manifestVersions }; } public static WorkloadSet FromJson(string json, SdkFeatureBand defaultFeatureBand) { return FromDictionaryForJson(JsonSerializer.Deserialize(json, WorkloadSetJsonSerializerContext.Default.IDictionaryStringString)!, defaultFeatureBand); } public static WorkloadSet? FromWorkloadSetFolder(string path, string workloadSetVersion, SdkFeatureBand defaultFeatureBand) { WorkloadSet? workloadSet = null; foreach (var jsonFile in Directory.GetFiles(path, "*.workloadset.json")) { var newWorkloadSet = WorkloadSet.FromJson(File.ReadAllText(jsonFile), defaultFeatureBand); if (workloadSet == null) { workloadSet = newWorkloadSet; } else { // If there are multiple workloadset.json files, merge them foreach (var kvp in newWorkloadSet.ManifestVersions) { if (workloadSet.ManifestVersions.ContainsKey(kvp.Key)) { throw new InvalidOperationException($"Workload set files in {path} defined the same manifest ({kvp.Key}) multiple times"); } workloadSet.ManifestVersions.Add(kvp.Key, kvp.Value); } } } if (workloadSet == null) { return null; } if (File.Exists(Path.Combine(path, "baseline.workloadset.json"))) { workloadSet.IsBaselineWorkloadSet = true; } workloadSet.Version = workloadSetVersion; return workloadSet; } public Dictionary<string, string> ToDictionaryForJson() { var dictionary = ManifestVersions.ToDictionary(kvp => kvp.Key.ToString(), kvp => kvp.Value.Version + "/" + kvp.Value.FeatureBand, StringComparer.OrdinalIgnoreCase); return dictionary; } public string ToJson() { var json = JsonSerializer.Serialize(ToDictionaryForJson(), WorkloadSetJsonSerializerContext.Default.DictionaryStringString); return json; } // Corresponding method for opposite direction is in WorkloadManifestUpdater, as its implementation depends on NuGetVersion, // which we'd like to avoid adding as a dependency here. public static string WorkloadSetVersionToWorkloadSetPackageVersion(string setVersion, out SdkFeatureBand sdkFeatureBand) { string[] sections = setVersion.Split(new char[] { '-', '+' }, 2); string versionCore = sections[0]; string? preReleaseOrBuild = sections.Length > 1 ? sections[1] : null; string[] coreComponents = versionCore.Split('.'); string major = coreComponents[0]; string minor = coreComponents[1]; string patch = coreComponents[2]; string packageVersion = $"{major}.{patch}."; if (coreComponents.Length == 3) { // No workload set patch version packageVersion += "0"; // Use preview specifier (if any) from workload set version as part of SDK feature band sdkFeatureBand = new SdkFeatureBand(setVersion); } else { // Workload set version has workload patch version (ie 4 components) packageVersion += coreComponents[3]; // Don't include any preview specifiers in SDK feature band sdkFeatureBand = new SdkFeatureBand($"{major}.{minor}.{patch}"); } if (preReleaseOrBuild != null) { // Figure out if we split on a '-' or '+' char separator = setVersion[sections[0].Length]; packageVersion += separator + preReleaseOrBuild; } return packageVersion; } public static SdkFeatureBand GetWorkloadSetFeatureBand(string setVersion) { WorkloadSetVersionToWorkloadSetPackageVersion(setVersion, out SdkFeatureBand sdkFeatureBand); return sdkFeatureBand; } } }