From 74c8369ad885e71e58f1e7732382172cfb654b13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Laban?= Date: Tue, 13 Feb 2024 13:27:54 -0500 Subject: [PATCH 1/6] chore: Bump to 8.0.200 --- manifests/uno.ui.manifest.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/manifests/uno.ui.manifest.json b/manifests/uno.ui.manifest.json index 70517b9c..aec0f918 100644 --- a/manifests/uno.ui.manifest.json +++ b/manifests/uno.ui.manifest.json @@ -3,12 +3,12 @@ "toolVersion": "1.14.0", "variables": { "OPENJDK_VERSION": "11.0.20.1", - "DOTNET_SDK_VERSION": "8.0.101", - "MACCATALYST_SDK_VERSION": "17.0.8478/8.0.100", - "IOS_SDK_VERSION": "17.0.8478/8.0.100", - "MACOS_SDK_VERSION": "14.0.8478/8.0.100", - "ANDROID_SDK_VERSION": "34.0.43/8.0.100", - "MAUI_VERSION": "8.0.3/8.0.100" + "DOTNET_SDK_VERSION": "8.0.200", + "MACCATALYST_SDK_VERSION": "17.2.8022/8.0.100", + "IOS_SDK_VERSION": "17.2.8022/8.0.100", + "MACOS_SDK_VERSION": "14.2.8022/8.0.100", + "ANDROID_SDK_VERSION": "34.0.79/8.0.100", + "MAUI_VERSION": "8.0.6/8.0.100" }, "variableMappers": [ ], From 107864af14340bb8d7a3eb6766fbc5c7195dbfad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Laban?= Date: Tue, 13 Feb 2024 17:19:22 -0500 Subject: [PATCH 2/6] chore: Remove dependency on SDK resolver --- UnoCheck.sln | 10 +- UnoCheck/AcquirePackagesCommand.cs | 325 ------------ UnoCheck/AcquirePackagesSettings.cs | 26 - UnoCheck/Checkups/DotNetCheckup.cs | 1 - UnoCheck/Checkups/DotNetWorkloadsCheckup.cs | 24 +- UnoCheck/DotNet/DotNetSdk.cs | 1 - UnoCheck/DotNet/DotNetWorkloadManager.cs | 167 ++---- .../DotNet/DotNetWorkloadManagerLegacy.cs | 500 ------------------ UnoCheck/Program.cs | 1 - UnoCheck/Properties/launchSettings.json | 2 +- .../DotNetWorkloadInstallSolution.cs | 74 --- 11 files changed, 52 insertions(+), 1079 deletions(-) delete mode 100644 UnoCheck/AcquirePackagesCommand.cs delete mode 100644 UnoCheck/AcquirePackagesSettings.cs delete mode 100644 UnoCheck/DotNet/DotNetWorkloadManagerLegacy.cs delete mode 100644 UnoCheck/Solutions/DotNetWorkloadInstallSolution.cs diff --git a/UnoCheck.sln b/UnoCheck.sln index 45b674a9..9aff8f5a 100644 --- a/UnoCheck.sln +++ b/UnoCheck.sln @@ -12,7 +12,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnoCheck", "UnoCheck\UnoCheck.csproj", "{AA2080B9-50D8-4FF8-A85D-DD952D955D22}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.DotNet.MSBuildSdkResolver", "UnoCheck.SdkResolver\Microsoft.DotNet.MSBuildSdkResolver.csproj", "{3DF4A47E-286E-470F-AB0B-C33BDA3722FF}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.DotNet.MSBuildSdkResolver", "UnoCheck.SdkResolver\Microsoft.DotNet.MSBuildSdkResolver.csproj", "{DD9F230A-D328-4F90-B030-D27035D365DA}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -24,10 +24,10 @@ Global {AA2080B9-50D8-4FF8-A85D-DD952D955D22}.Debug|Any CPU.Build.0 = Debug|Any CPU {AA2080B9-50D8-4FF8-A85D-DD952D955D22}.Release|Any CPU.ActiveCfg = Release|Any CPU {AA2080B9-50D8-4FF8-A85D-DD952D955D22}.Release|Any CPU.Build.0 = Release|Any CPU - {3DF4A47E-286E-470F-AB0B-C33BDA3722FF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {3DF4A47E-286E-470F-AB0B-C33BDA3722FF}.Debug|Any CPU.Build.0 = Debug|Any CPU - {3DF4A47E-286E-470F-AB0B-C33BDA3722FF}.Release|Any CPU.ActiveCfg = Release|Any CPU - {3DF4A47E-286E-470F-AB0B-C33BDA3722FF}.Release|Any CPU.Build.0 = Release|Any CPU + {DD9F230A-D328-4F90-B030-D27035D365DA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DD9F230A-D328-4F90-B030-D27035D365DA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DD9F230A-D328-4F90-B030-D27035D365DA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DD9F230A-D328-4F90-B030-D27035D365DA}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/UnoCheck/AcquirePackagesCommand.cs b/UnoCheck/AcquirePackagesCommand.cs deleted file mode 100644 index 023e761c..00000000 --- a/UnoCheck/AcquirePackagesCommand.cs +++ /dev/null @@ -1,325 +0,0 @@ -using DotNetCheck.DotNet; -using DotNetCheck.Models; -using Microsoft.NET.Sdk.WorkloadManifestReader; -using Newtonsoft.Json; -using NuGet.Common; -using NuGet.Configuration; -using NuGet.Packaging; -using NuGet.Packaging.Core; -using NuGet.Packaging.Signing; -using NuGet.Protocol; -using NuGet.Protocol.Core.Types; -using NuGet.Versioning; -using Spectre.Console; -using Spectre.Console.Cli; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using System.Text.RegularExpressions; -using System.Threading; -using System.Threading.Tasks; - -namespace DotNetCheck -{ - public class AcquirePackagesCommand : AsyncCommand - { - readonly static string[] WorkloadPackageMsiAliases = new[] - { - ".Msi.x86", - ".Msi.x64", - ".Msi.arm64" - }; - - internal static Dictionary nugetSources = new(); - - public override async Task ExecuteAsync(CommandContext context, AcquirePackagesSettings settings) - { - AnsiConsole.Markup($"[bold blue]{Icon.Thinking} Synchronizing configuration...[/]"); - - var manifest = await ToolInfo.LoadManifest(settings.Manifest, settings.GetManifestChannel()); - - if (!ToolInfo.Validate(manifest)) - { - ToolInfo.ExitPrompt(settings.NonInteractive); - return -1; - } - - AnsiConsole.MarkupLine(" ok"); - - var manifestDotNetSdk = manifest?.Check?.DotNet?.Sdks?.FirstOrDefault(); - - foreach (var s in manifestDotNetSdk.PackageSources) - { - var nugetSource = Repository.Factory.GetCoreV3(s); - var byIdRes = await nugetSource.GetResourceAsync(); - - nugetSources.Add(s, (nugetSource, byIdRes)); - } - - var dn = new DotNetSdk(new SharedState()); - var sdks = await dn.GetSdks(); - - DotNetSdkInfo bestSdk = null; - - foreach (var sdk in sdks) - { - if (bestSdk == null || sdk.Version >= bestSdk.Version) - { - bestSdk = sdk; - - if (bestSdk.Version == NuGetVersion.Parse(manifestDotNetSdk.Version)) - break; - } - } - - // Make sure the download dir exists - Directory.CreateDirectory(settings.DownloadDirectory); - - var sdkRoot = dn.DotNetSdkLocation.FullName; - var sdkVersion = bestSdk.Version.ToString(); - var cancelTokenSource = new CancellationTokenSource(); - - var nugetWorkloadManifestProvider = new NuGetManifestProvider(new NuGetVersion(sdkVersion)); - - foreach (var workload in manifestDotNetSdk.Workloads) - { - AnsiConsole.MarkupLine($"Acquiring Workload Manifest: {workload.PackageId} {workload.Version} ..."); - - await GetNuGetDependencyTree(settings.DownloadDirectory, workload.PackageId, new NuGetVersion(workload.Version), cancelTokenSource.Token, false); - - foreach (var msiAlias in WorkloadPackageMsiAliases) - { - var msiPackageId = $"{workload.PackageId}{msiAlias}"; - await GetNuGetDependencyTree(settings.DownloadDirectory, msiPackageId, new NuGetVersion(workload.Version), cancelTokenSource.Token, false); - } - } - - await nugetWorkloadManifestProvider.ParseManifestPackages(settings.DownloadDirectory, manifestDotNetSdk.Workloads, cancelTokenSource.Token); - - var items = new Dictionary(); - - try - { - var manifests = nugetWorkloadManifestProvider.GetManifests(); - foreach (var mfst in manifests) - { - AnsiConsole.MarkupLine($"Acquiring packages for: {mfst.ManifestId} ..."); - - var manifestReader = WorkloadManifestReader.ReadWorkloadManifest(mfst.ManifestId, mfst.OpenManifestStream(), mfst.ManifestPath); - - foreach (var wlPack in manifestReader.Packs) - { - if (wlPack.Value.IsAlias) - { - foreach (var wlPackAlias in wlPack.Value.AliasTo.Values.Distinct()) - { - var packageId = wlPackAlias.ToString(); - var packageVersion = wlPack.Value.Version; - - await GetNuGetDependencyTree(settings.DownloadDirectory, packageId, new NuGetVersion(packageVersion), cancelTokenSource.Token, true); - - foreach (var msiAlias in WorkloadPackageMsiAliases) - { - var msiPackageId = $"{packageId}{msiAlias}"; - await GetNuGetDependencyTree(settings.DownloadDirectory, msiPackageId, new NuGetVersion(packageVersion), cancelTokenSource.Token, true); - } - } - } - else - { - var packageId = wlPack.Value.Id; - var packageVersion = wlPack.Value.Version; - - await GetNuGetDependencyTree(settings.DownloadDirectory, packageId, new NuGetVersion(packageVersion), cancelTokenSource.Token, true); - - foreach (var msiAlias in WorkloadPackageMsiAliases) - { - var msiPackageId = $"{packageId}{msiAlias}"; - await GetNuGetDependencyTree(settings.DownloadDirectory, msiPackageId, new NuGetVersion(packageVersion), cancelTokenSource.Token, true); - } - } - } - } - } - catch (Exception ex) - { - Util.Exception(ex); - } - - ToolInfo.ExitPrompt(settings.NonInteractive); - return 0; - } - - - async Task GetNuGetDependencyTree(string destinationDir, string packageId, NuGetVersion packageVersion, CancellationToken cancelToken, bool includeDependencies) - { - var cache = new SourceCacheContext(); - cache.DirectDownload = true; - cache.NoCache = true; - - var logger = NullLogger.Instance; - - foreach (var src in nugetSources) - { - if (await DownloadPackage(destinationDir, src.Value.source, cache, logger, src.Value.byIdRes, packageId, packageVersion, cancelToken, includeDependencies)) - break; - } - } - - async Task DownloadPackage(string directory, SourceRepository nugetSource, SourceCacheContext cache, ILogger logger, FindPackageByIdResource byIdRes, string packageId, NuGetVersion packageVersion, CancellationToken cancelToken, bool includeDependencies) - { - var packageVersionsAvailable = await byIdRes.GetAllVersionsAsync(packageId, cache, logger, cancelToken); - - if (!(packageVersionsAvailable?.Any() ?? false)) - return false; - - // Require the exact version, otherwise we'll try other feeds - var matchingExplicitVersion = packageVersionsAvailable.FirstOrDefault(pv => pv == packageVersion); - if (matchingExplicitVersion == null) - return false; - - async Task download(string destFile, PackageIdentity pkgIdentity) - { - var tries = 0; - - while (tries <= 3) - { - tries++; - - try - { - if (!File.Exists(destFile) || tries > 1) - { - using var downloader = await byIdRes.GetPackageDownloaderAsync(pkgIdentity, cache, logger, cancelToken); - await downloader.CopyNupkgFileToAsync(destFile, cancelToken); - } - - return new PackageArchiveReader(File.OpenRead(destFile)); - } - catch (Exception ex) - { - Util.Exception(ex); - } - } - - return null; - } - - bool foundAll = false; - - if (await byIdRes.DoesPackageExistAsync(packageId, matchingExplicitVersion, cache, logger, cancelToken)) - { - foundAll = true; - - var destFile = Path.Combine(directory, $"{packageId}.{matchingExplicitVersion}.nupkg"); - - AnsiConsole.Markup($" -> {packageId} {matchingExplicitVersion} ... "); - - var packageReader = await download(destFile, new PackageIdentity(packageId, matchingExplicitVersion)); - - if (packageReader == null) - { - AnsiConsole.MarkupLine($"{Icon.Error}"); - return false; - } - - AnsiConsole.MarkupLine($"{Icon.Success}"); - - if (includeDependencies) - { - var dependencyGroups = new List(); - - dependencyGroups.AddRange(await packageReader.GetPackageDependenciesAsync(cancelToken)); - packageReader.Dispose(); - - foreach (var depGrp in dependencyGroups) - { - foreach (var depPkg in depGrp.Packages) - { - var version = depPkg.VersionRange.MinVersion; - if (!await DownloadPackage(directory, nugetSource, cache, logger, byIdRes, depPkg.Id, version, cancelToken, includeDependencies)) - foundAll = false; - } - } - } - } - - return foundAll; - } - - } - - class NuGetManifestProvider : IWorkloadManifestProvider - { - public NuGetManifestProvider(NuGetVersion sdkVersion) - { - SdkVersion = sdkVersion; - ManifestPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); - Directory.CreateDirectory(ManifestPath); - } - - public readonly NuGetVersion SdkVersion; - public readonly string ManifestPath; - - List<(string id, string dir, string file, string featureBand)> manifestDirs = new(); - - public async Task ParseManifestPackages(string directory, List workloads, CancellationToken cancelToken) - { - foreach (var workload in workloads) - { - AnsiConsole.MarkupLine($"Reading Workload Manifest: {workload.PackageId} {workload.Version} ..."); - - var manifestDirName = Regex.Replace( - workload.PackageId, - @"\.Manifest-\d+\.\d+\.\d+$", - string.Empty, - RegexOptions.Singleline | RegexOptions.IgnoreCase) - ?.ToLowerInvariant(); - - var manifestDir = Path.Combine(ManifestPath, manifestDirName); - - Directory.CreateDirectory(manifestDir); - - var nupkgFile = Path.Combine(directory, $"{workload.PackageId}.{workload.Version}.nupkg"); - - using (var sr = File.OpenRead(nupkgFile)) - using (var zipArchive = new System.IO.Compression.ZipArchive(sr, System.IO.Compression.ZipArchiveMode.Read)) - { - foreach (var zipEntry in zipArchive.Entries) - { - var entryName = zipEntry.FullName; - - if (!entryName.EndsWith("WorkloadManifest.json", StringComparison.Ordinal)) - continue; - - var workloadFile = Path.Combine(manifestDir, "WorkloadManifest.json"); - using (var manifestZipStream = zipEntry.Open()) - using (var manifestFileStream = File.Create(workloadFile)) - { - await manifestZipStream.CopyToAsync(manifestFileStream); - } - - manifestDirs.Add((workload.Id, manifestDir, workloadFile, workload.WorkloadManifestId)); - } - } - } - } - - public IEnumerable GetManifestDirectories() - => manifestDirs.Select(m => m.dir); - - public IEnumerable GetManifests() - => manifestDirs.Select(m => new ReadableWorkloadManifest( - m.id, - m.dir, - m.file, - m.featureBand, - new Func(() => File.OpenRead(m.file)), - new Func(() => null))); - - public string GetSdkFeatureBand() - => $"{SdkVersion.Major}.{SdkVersion.Minor}.{SdkVersion.Patch}"; - } -} diff --git a/UnoCheck/AcquirePackagesSettings.cs b/UnoCheck/AcquirePackagesSettings.cs deleted file mode 100644 index 52574b8a..00000000 --- a/UnoCheck/AcquirePackagesSettings.cs +++ /dev/null @@ -1,26 +0,0 @@ -using Spectre.Console.Cli; - -namespace DotNetCheck -{ - public class AcquirePackagesSettings : CommandSettings, IManifestChannelSettings - { - [CommandOption("-m|--manifest ")] - public string Manifest { get; set; } - - [CommandOption("--pre|--preview|-d|--dev")] - public bool Preview { get; set; } - - [CommandOption("--preview-major")] - public bool PreviewMajor { get; set; } - - [CommandOption("--main")] - public bool Main { get; set; } - - [CommandOption("-n|--non-interactive")] - public bool NonInteractive { get; set; } - - [CommandOption("--dir|--directory ")] - public string DownloadDirectory { get; set; } - - } -} diff --git a/UnoCheck/Checkups/DotNetCheckup.cs b/UnoCheck/Checkups/DotNetCheckup.cs index 6c816524..0f1d3ab2 100644 --- a/UnoCheck/Checkups/DotNetCheckup.cs +++ b/UnoCheck/Checkups/DotNetCheckup.cs @@ -6,7 +6,6 @@ using DotNetCheck.DotNet; using DotNetCheck.Models; using DotNetCheck.Solutions; -using Microsoft.NET.Sdk.WorkloadManifestReader; using Newtonsoft.Json.Linq; using NuGet.Versioning; diff --git a/UnoCheck/Checkups/DotNetWorkloadsCheckup.cs b/UnoCheck/Checkups/DotNetWorkloadsCheckup.cs index 7d01ba28..d77bf9db 100644 --- a/UnoCheck/Checkups/DotNetWorkloadsCheckup.cs +++ b/UnoCheck/Checkups/DotNetWorkloadsCheckup.cs @@ -5,7 +5,6 @@ using DotNetCheck.DotNet; using DotNetCheck.Models; using DotNetCheck.Solutions; -using Microsoft.NET.Sdk.WorkloadManifestReader; using NuGet.Versioning; namespace DotNetCheck.Checkups @@ -67,13 +66,10 @@ public override async Task Examine(SharedState history) var validWorkloads = RequiredWorkloads .ToArray(); - var workloadManagers = validWorkloads - .Select(w => w.Version.Split("/", StringSplitOptions.None).LastOrDefault() is { Length: > 0 } workloadSdkVersion ? workloadSdkVersion : sdkVersion) - .Concat(new[] { sdkVersion }) - .Distinct() - .ToDictionary(v => v, v => new DotNetWorkloadManager(SdkRoot, v, NuGetPackageSources)); + var manager = new DotNetWorkloadManager(SdkRoot, SdkVersion, NuGetPackageSources); var missingWorkloads = new List(); + var installedPackageWorkloads = await manager.GetInstalledWorkloads(); foreach (var rp in RequiredWorkloads) { @@ -81,12 +77,6 @@ public override async Task Examine(SharedState history) var workloadVersion = versionParts.First(); var workloadSdkVersion = versionParts.ElementAtOrDefault(1) is { Length: > 0 } v ? v : sdkVersion; - if (!workloadManagers.TryGetValue(workloadSdkVersion, out var workloadManager)) - { - throw new Exception($"Unable to find workload manager for version [{rp.Id}: {rp.Version}]"); - } - - var installedPackageWorkloads = workloadManager.GetInstalledWorkloads(); if (!NuGetVersion.TryParse(workloadVersion, out var rpVersion)) rpVersion = new NuGetVersion(0, 0, 0); @@ -98,16 +88,14 @@ public override async Task Examine(SharedState history) } #endif - // TODO: Eventually check actual workload resolver api for installed workloads and - // compare the manifest version once it has a string in it - if (!installedPackageWorkloads.Any(ip => ip.id.Equals(rp.Id, StringComparison.OrdinalIgnoreCase) && NuGetVersion.TryParse(ip.version, out var ipVersion) && ipVersion == rpVersion)) + if (installedPackageWorkloads.FirstOrDefault(ip => ip.id.Equals(rp.WorkloadManifestId, StringComparison.OrdinalIgnoreCase) && NuGetVersion.TryParse(ip.version, out var ipVersion) && ipVersion >= rpVersion) is { } installed) { - ReportStatus($"{rp.Id} ({rp.PackageId} : {rp.Version}) not installed.", Status.Error); - missingWorkloads.Add(rp); + ReportStatus($"{installed.id} ({installed.version}/{installed.sdkVersion}) installed.", Status.Ok); } else { - ReportStatus($"{rp.Id} ({rp.PackageId} : {rp.Version}) installed.", Status.Ok); + ReportStatus($"{rp.Id} ({rp.PackageId} : {rp.Version}) not installed.", Status.Error); + missingWorkloads.Add(rp); } } diff --git a/UnoCheck/DotNet/DotNetSdk.cs b/UnoCheck/DotNet/DotNetSdk.cs index 137a91d6..2cb5b300 100644 --- a/UnoCheck/DotNet/DotNetSdk.cs +++ b/UnoCheck/DotNet/DotNetSdk.cs @@ -7,7 +7,6 @@ using System.Threading; using System.Threading.Tasks; using DotNetCheck.Models; -using Microsoft.NET.Sdk.WorkloadManifestReader; using NuGet.Common; using NuGet.Packaging.Core; using NuGet.Protocol; diff --git a/UnoCheck/DotNet/DotNetWorkloadManager.cs b/UnoCheck/DotNet/DotNetWorkloadManager.cs index 5d7ca741..f0c14b95 100644 --- a/UnoCheck/DotNet/DotNetWorkloadManager.cs +++ b/UnoCheck/DotNet/DotNetWorkloadManager.cs @@ -1,6 +1,4 @@ -using Microsoft.DotNet.MSBuildSdkResolver; -using Microsoft.NET.Sdk.WorkloadManifestReader; -using NuGet.Common; +using NuGet.Common; using NuGet.Packaging; using NuGet.Packaging.Core; using NuGet.Packaging.Signing; @@ -21,7 +19,7 @@ using System.Xml; using Newtonsoft.Json.Linq; using DotNetCheck.Models; -using Microsoft.Deployment.DotNet.Releases; +using System.Text.Json; namespace DotNetCheck.DotNet { @@ -33,7 +31,7 @@ public DotNetWorkloadManager(string sdkRoot, string sdkVersion, params string[] SdkVersion = sdkVersion; NuGetPackageSources = nugetPackageSources; - DotNetCliWorkingDir = Path.Combine(Path.GetTempPath(), "maui-check-" + Guid.NewGuid().ToString("N").Substring(0, 8)); + DotNetCliWorkingDir = Path.Combine(Path.GetTempPath(), "uno-check-" + Guid.NewGuid().ToString("N").Substring(0, 8)); Directory.CreateDirectory(DotNetCliWorkingDir); var globalJson = new DotNetGlobalJson(); @@ -52,8 +50,6 @@ public DotNetWorkloadManager(string sdkRoot, string sdkVersion, params string[] public async Task Repair() { - RemoveOldMetadata(); - await CliRepair(); } @@ -61,14 +57,12 @@ public async Task Install(Manifest.DotNetWorkload[] workloads) { var rollbackFile = WriteRollbackFile(workloads); - RemoveOldMetadata(); - await CliInstallWithRollback(rollbackFile, workloads.Where(w => !w.Abstract).Select(w => w.Id)); } string WriteRollbackFile(Manifest.DotNetWorkload[] workloads) { - var workloadRollback = GetInstalledWorkloadManifestIdsAndVersions(); + var workloadRollback = new Dictionary(); foreach (var workload in workloads) workloadRollback[workload.WorkloadManifestId] = workload.Version; @@ -87,134 +81,53 @@ string WriteRollbackFile(Manifest.DotNetWorkload[] workloads) return rollbackFile; } - Dictionary GetInstalledWorkloadManifestIdsAndVersions() - { - var items = new Dictionary(); + const string RollbackOutputBeginMarker = "==workloadRollbackDefinitionJsonOutputStart=="; + const string RollbackOutputEndMarker = "==workloadRollbackDefinitionJsonOutputEnd=="; - var manifestProvider = new SdkDirectoryWorkloadManifestProvider(SdkRoot, SdkVersion, null, null); + public async Task<(string id, string version, string sdkVersion)[]> GetInstalledWorkloads() + { + // dotnet workload install id --skip-manifest-update --add-source x + var dotnetExe = Path.Combine(SdkRoot, DotNetSdk.DotNetExeName); - foreach (var manifestInfo in manifestProvider.GetManifests()) - { - using (var manifestStream = manifestInfo.OpenManifestStream()) - { - var m = WorkloadManifestReader.ReadWorkloadManifest(manifestInfo.ManifestId, manifestStream, manifestInfo.ManifestPath); - items[manifestInfo.ManifestId] = m.Version; - } - } + var args = new List + { + "workload", + "update", + "--print-rollback" + }; - return items; - } + var r = await Util.WrapShellCommandWithSudo(dotnetExe, DotNetCliWorkingDir, true, args.ToArray()); - public IEnumerable<(string id, string version)> GetInstalledWorkloads() - { - var manifestProvider = new SdkDirectoryWorkloadManifestProvider(SdkRoot, SdkVersion, null, SdkDirectoryWorkloadManifestProvider.GetGlobalJsonPath(Environment.CurrentDirectory)); + // Throw if this failed with a bad exit code + if (r.ExitCode != 0) + throw new Exception("Workload command failed: `dotnet " + string.Join(' ', args) + "`"); - var workloadResolver = WorkloadResolver.Create(manifestProvider, SdkRoot, SdkVersion, null); + var output = string.Join("", r.StandardOutput); + var startIndex = output.IndexOf(RollbackOutputBeginMarker); + var endIndex = output.IndexOf(RollbackOutputEndMarker); - foreach (var manifestInfo in GetAllManifests(manifestProvider)) - { - using (var manifestStream = manifestInfo.OpenManifestStream()) - { - var m = WorkloadManifestReader.ReadWorkloadManifest(manifestInfo.ManifestId, manifestStream, manifestInfo.ManifestPath); - - // Each workload manifest can have one or more workloads defined - foreach (var wl in m.Workloads) - { - if (wl.Value is WorkloadDefinition wd && !AreWorkloadPacksInstalled(wd, workloadResolver)) - { - continue; - } - - yield return (wl.Key.ToString(), m.Version); - } - } - } + if(startIndex >= 0 && endIndex >= 0) + { + var start = startIndex + RollbackOutputBeginMarker.Length; + var json = output.Substring(start, endIndex - start); - bool AreWorkloadPacksInstalled(WorkloadDefinition workload, WorkloadResolver workloadResolver) - { - foreach (var packId in workload.Packs ?? Enumerable.Empty()) - { - var pack = workloadResolver.TryGetPackInfo(packId); - - if (pack != null) - { - var packInstalled = - pack.Kind switch - { - WorkloadPackKind.Library or WorkloadPackKind.Template => File.Exists(pack.Path), - _ => Directory.Exists(pack.Path) - }; - - if (!packInstalled) - { - return false; - } - } - } - - return true; - } - } + var workloads = JsonSerializer.Deserialize>(json); - private static IEnumerable GetAllManifests(SdkDirectoryWorkloadManifestProvider manifestProvider) - { - // Enumerate all workload versions, including those not latest for the current band - // as they may have been pinned in 8.0.101 and later. https://github.com/dotnet/sdk/issues/37958 - foreach (var manifest in manifestProvider.GetManifests()) - { - var parentDirectory = Path.GetDirectoryName(manifest.ManifestDirectory); - - var manifestVersionDirectories = Directory.GetDirectories(parentDirectory) - .Where(dir => File.Exists(Path.Combine(dir, "WorkloadManifest.json"))) - .Select(dir => - { - ReleaseVersion.TryParse(Path.GetFileName(dir), out var releaseVersion); - return (directory: dir, version: releaseVersion); + return workloads + .Select(p => { + var versionParts = p.Value.Split("/", StringSplitOptions.None); + var workloadVersion = versionParts.First(); + var workloadSdkVersion = versionParts.ElementAtOrDefault(1) is { Length: > 0 } v ? v : ""; + + return (p.Key, workloadVersion, workloadSdkVersion); }) - .Where(t => t.version != null) - .OrderByDescending(t => t.version) - .ToList(); - - foreach(var otherManifest in manifestVersionDirectories) - { - var workloadManifestPath = Path.Combine(otherManifest.directory, "WorkloadManifest.json"); - - var readableManifest = new ReadableWorkloadManifest( - manifest.ManifestId, - otherManifest.directory, - workloadManifestPath, - manifestProvider.GetSdkFeatureBand(), - () => File.OpenRead(workloadManifestPath), - () => WorkloadManifestReader.TryOpenLocalizationCatalogForManifest(workloadManifestPath)); - - yield return readableManifest; - } + .ToArray(); } - } - - void RemoveOldMetadata() - { - var dir = GetInstalledWorkloadMetadataDir(); - - var oldWorkloadIds = new [] { - "microsoft-android-sdk-full", - "microsoft-ios-sdk-full", - "microsoft-maccatalyst-sdk-full", - "microsoft-macos-sdk-full", - "microsoft-tvos-sdk-full" - }; - - foreach (var owid in oldWorkloadIds) + else { - try - { - var f = Path.Combine(dir, owid); - if (File.Exists(f)) - File.Delete(f); - } - catch { } - } - } + throw new Exception("Workload command output cannot be parsed: `dotnet " + string.Join(' ', args) + "`"); + } + } async Task CliInstallWithRollback(string rollbackFile, IEnumerable workloadIds) { diff --git a/UnoCheck/DotNet/DotNetWorkloadManagerLegacy.cs b/UnoCheck/DotNet/DotNetWorkloadManagerLegacy.cs deleted file mode 100644 index 2ea0527e..00000000 --- a/UnoCheck/DotNet/DotNetWorkloadManagerLegacy.cs +++ /dev/null @@ -1,500 +0,0 @@ -using Microsoft.DotNet.MSBuildSdkResolver; -using Microsoft.NET.Sdk.WorkloadManifestReader; -using NuGet.Common; -using NuGet.Packaging; -using NuGet.Packaging.Core; -using NuGet.Packaging.Signing; -using NuGet.Protocol; -using NuGet.Protocol.Core.Types; -using NuGet.Versioning; -using Polly; -using System; -using System.Collections.Generic; -using System.IO; -using System.IO.Compression; -using System.Linq; -using System.Reflection; -using System.Text; -using System.Text.RegularExpressions; -using System.Threading; -using System.Threading.Tasks; -using System.Xml; -using Newtonsoft.Json.Linq; -using DotNetCheck.Models; - -namespace DotNetCheck.DotNet -{ - public class DotNetWorkloadManagerLegacy - - { - public DotNetWorkloadManagerLegacy(string sdkRoot, string sdkVersion, params string[] nugetPackageSources) - { - SdkRoot = sdkRoot; - SdkVersion = sdkVersion; - NuGetPackageSources = nugetPackageSources; - - CleanEmptyWorkloadDirectories(sdkRoot, sdkVersion); - - DotNetCliWorkingDir = Path.Combine(Path.GetTempPath(), "maui-check-net-working-dir"); - Directory.CreateDirectory(DotNetCliWorkingDir); - - var globalJson = new DotNetGlobalJson(); - globalJson.Sdk.Version = sdkVersion; - globalJson.Sdk.RollForward = "disable"; - globalJson.Sdk.AllowPrerelease = true; - File.WriteAllText(Path.Combine(DotNetCliWorkingDir, "global.json"), globalJson.ToJson()); - } - - public readonly string SdkRoot; - public readonly string SdkVersion; - - public readonly string[] NuGetPackageSources; - - readonly string DotNetCliWorkingDir; - - void CleanEmptyWorkloadDirectories(string sdkRoot, string sdkVersion) - { - if (NuGetVersion.TryParse(sdkVersion, out var v)) - { - var sdkBand = $"{v.Major}.{v.Minor}.{v.Patch}"; - - var manifestsDir = Path.Combine(sdkRoot, "sdk-manifests", sdkBand); - - if (Directory.Exists(manifestsDir)) - { - foreach (var dir in Directory.GetDirectories(manifestsDir)) - { - var manifestFile = Path.Combine(dir, "WorkloadManifest.json"); - - if (!File.Exists(manifestFile)) - { - try { Util.Delete(dir, false); } - catch { } - } - } - } - } - } - - async Task DeleteExistingWorkloads(string sdkRoot, string sdkVersion, string workloadIdentifier) - { - // Run dotnet workload uninstall first on the workload id - try - { - Util.Log($"Running workload uninstall for {workloadIdentifier}"); - - var dotnetExe = Path.Combine(sdkRoot, DotNetSdk.DotNetExeName); - - var args = new[] { "workload", "uninstall", workloadIdentifier }; - - await Util.WrapShellCommandWithSudo(dotnetExe, DotNetCliWorkingDir, true, args.ToArray()); - } - catch (Exception ex) - { - Util.Exception(ex); - } - - if (NuGetVersion.TryParse(sdkVersion, out var v)) - { - var sdkBand = $"{v.Major}.{v.Minor}.{v.Patch}"; - - // Try and clean up the metadata dir too - var metadataMarkerFile = Path.Combine(sdkRoot, "metadata", "workloads", sdkBand, "InstalledWorkloads", workloadIdentifier); - - if (File.Exists(metadataMarkerFile)) - { - try { File.Delete(metadataMarkerFile); } - catch { } - } - - var manifestsDir = Path.Combine(sdkRoot, "sdk-manifests", sdkBand); - - if (Directory.Exists(manifestsDir)) - { - foreach (var dir in Directory.GetDirectories(manifestsDir)) - { - var delete = false; - var manifestFile = Path.Combine(dir, "WorkloadManifest.json"); - - if (File.Exists(manifestFile)) - { - var json = JObject.Parse(File.ReadAllText(manifestFile)); - var workloadsJson = json["workloads"]; - - foreach (var wj in workloadsJson.Children()) - { - var wid = (wj as JProperty)?.Name; - - if (wid == workloadIdentifier) - { - delete = true; - break; - } - } - - if (delete) - { - Util.Log($"Existing workload with id: {workloadIdentifier} found, deleting..."); - - try { Util.Delete(dir, false); } - catch { } - } - } - } - } - } - } - - public IEnumerable<(string id, string version)> GetInstalledWorkloads() - { - var manifestProvider = new SdkDirectoryWorkloadManifestProvider(SdkRoot, SdkVersion, null, null); - - foreach (var manifestInfo in manifestProvider.GetManifests()) - { - using (var manifestStream = manifestInfo.OpenManifestStream()) - { - var m = WorkloadManifestReader.ReadWorkloadManifest(manifestInfo.ManifestId, manifestStream, manifestInfo.ManifestPath); - - // Each workload manifest can have one or more workloads defined - foreach (var wl in m.Workloads) - yield return (wl.Key.ToString(), m.Version); - } - } - } - - public IEnumerable GetPacksInWorkload(string workloadId) - { - var workloadResolver = WorkloadResolver.Create(new SdkDirectoryWorkloadManifestProvider(SdkRoot, SdkVersion, null, null), SdkRoot, SdkVersion, null); - - var wid = new Microsoft.NET.Sdk.WorkloadManifestReader.WorkloadId(workloadId); - var packs = workloadResolver.GetPacksInWorkload(wid); - foreach (var p in packs) - { - var packInfo = workloadResolver.TryGetPackInfo(p); - if (packInfo != null) - yield return packInfo; - } - } - - public async Task CliInstall(IEnumerable workloadIds) - { - // dotnet workload install id --skip-manifest-update --add-source x - var dotnetExe = Path.Combine(SdkRoot, DotNetSdk.DotNetExeName); - - // Arg switched to --source in >= preview 7 - var addSourceArg = "--source"; - if (NuGetVersion.Parse(SdkVersion) <= DotNetCheck.Manifest.DotNetSdk.Version6Preview6) - addSourceArg = "--add-source"; - - var args = new List(); - args.Add("workload"); - args.Add("install"); - args.AddRange(workloadIds); - args.Add("--skip-manifest-update"); - args.AddRange(NuGetPackageSources.Select(ps => $"{addSourceArg} \"{ps}\"")); - - var r = await Util.WrapShellCommandWithSudo(dotnetExe, DotNetCliWorkingDir, true, args.ToArray()); - - // Throw if this failed with a bad exit code - if (r.ExitCode != 0) - { - throw new Exception("Failed to install workload: " + string.Join(", ", workloadIds)); - } - } - - public async Task UninstallTemplate(string templatePackId) - { - // dotnet new --uninstall