Skip to content

Commit

Permalink
Merge pull request #304 from unoplatform/dev/jela/adjust-wasm
Browse files Browse the repository at this point in the history
fix: Adjust installed workloads detection
  • Loading branch information
jeromelaban authored Nov 7, 2024
2 parents d4e9b33 + ecc1765 commit 0d79f14
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 66 deletions.
64 changes: 34 additions & 30 deletions UnoCheck/Checkups/DotNetWorkloadsCheckup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ public DotNetWorkloadsCheckup(SharedState sharedState, string sdkVersion, Manife

SdkRoot = dotnet.DotNetSdkLocation.FullName;
SdkVersion = sdkVersion;
if (sharedState.TryGetState<TargetPlatform>(StateKey.EntryPoint, StateKey.TargetPlatforms, out var activeTargetPlatforms))
{
TargetPlatforms = activeTargetPlatforms;
}
if (sharedState.TryGetState<TargetPlatform>(StateKey.EntryPoint, StateKey.TargetPlatforms, out var activeTargetPlatforms))
{
TargetPlatforms = activeTargetPlatforms;
}
RequiredWorkloads = requiredWorkloads.Where(FilterPlatform).ToArray();
NuGetPackageSources = nugetPackageSources;
}
Expand All @@ -36,32 +36,32 @@ private bool FilterPlatform(Manifest.DotNetWorkload w)
var arch = Util.IsArm64 ? "arm64" : "x64";
var targetPlatform = Util.Platform + "/" + arch;

if (w.SupportedPlatforms?.Any(sp => sp == (sp.Contains("/") ? targetPlatform : Util.Platform.ToString())) ?? false)
{
switch (w.Id)
{
case "android" when TargetPlatforms.HasFlag(TargetPlatform.Android):
case "maui-android" when TargetPlatforms.HasFlag(TargetPlatform.Android):
case "maui" when (TargetPlatforms.HasFlag(TargetPlatform.Android)
if (w.SupportedPlatforms?.Any(sp => sp == (sp.Contains("/") ? targetPlatform : Util.Platform.ToString())) ?? false)
{
switch (w.Id)
{
case "android" when TargetPlatforms.HasFlag(TargetPlatform.Android):
case "maui-android" when TargetPlatforms.HasFlag(TargetPlatform.Android):
case "maui" when (TargetPlatforms.HasFlag(TargetPlatform.Android)
|| TargetPlatforms.HasFlag(TargetPlatform.iOS)
|| TargetPlatforms.HasFlag(TargetPlatform.macOS)):
case "ios" when TargetPlatforms.HasFlag(TargetPlatform.iOS):
case "macos" when TargetPlatforms.HasFlag(TargetPlatform.macOS):
case "maccatalyst" when TargetPlatforms.HasFlag(TargetPlatform.macOS):
case "wasm-tools" when TargetPlatforms.HasFlag(TargetPlatform.WebAssembly):
return true;
}
}

return false;
}
case "ios" when TargetPlatforms.HasFlag(TargetPlatform.iOS):
case "macos" when TargetPlatforms.HasFlag(TargetPlatform.macOS):
case "maccatalyst" when TargetPlatforms.HasFlag(TargetPlatform.macOS):
case "wasm-tools" when TargetPlatforms.HasFlag(TargetPlatform.WebAssembly):
return true;
}

}

return false;
}

public readonly string SdkRoot;
public readonly string SdkVersion;
public readonly string[] NuGetPackageSources;
public readonly Manifest.DotNetWorkload[] RequiredWorkloads;
public readonly TargetPlatform TargetPlatforms;
public readonly TargetPlatform TargetPlatforms;

public override IEnumerable<CheckupDependency> DeclareDependencies(IEnumerable<string> checkupIds)
=> new[] { new CheckupDependency("dotnet") };
Expand Down Expand Up @@ -92,7 +92,8 @@ public override async Task<DiagnosticResult> Examine(SharedState history)
var manager = new DotNetWorkloadManager(SdkRoot, SdkVersion, NuGetPackageSources);

var missingWorkloads = new List<Manifest.DotNetWorkload>();
var installedPackageWorkloads = await manager.GetInstalledWorkloads();
var installedWorkloads = await manager.GetInstalledWorkloads();
var availablePackageWorkloads = await manager.GetAvailableWorkloads();

foreach (var rp in RequiredWorkloads)
{
Expand All @@ -106,20 +107,23 @@ public override async Task<DiagnosticResult> Examine(SharedState history)

if (Util.Verbose)
{
foreach (var installedWorload in installedPackageWorkloads)
foreach (var installedWorload in availablePackageWorkloads)
{
ReportStatus($"Reported installed: {installedWorload.id}: {installedWorload.version}", null);
ReportStatus($"Available workload: {installedWorload.id}: {installedWorload.version}", null);
}
}

if (installedPackageWorkloads.FirstOrDefault(ip => ip.id.Equals(rp.WorkloadManifestId, StringComparison.OrdinalIgnoreCase) && NuGetVersion.TryParse(ip.version, out var ipVersion) && ipVersion >= rpVersion) is { id: not null } installed)
if (
availablePackageWorkloads.FirstOrDefault(ip => ip.id.Equals(rp.WorkloadManifestId, StringComparison.OrdinalIgnoreCase) && NuGetVersion.TryParse(ip.version, out var ipVersion) && ipVersion >= rpVersion) is { id: not null } available
&& installedWorkloads.Contains(rp.Id)
)
{
ReportStatus($"{installed.id} ({installed.version}/{installed.sdkVersion}) installed.", Status.Ok);
ReportStatus($"{available.id} ({available.version}/{available.sdkVersion}) is installed.", Status.Ok);
}
else
{
ReportStatus($"{rp.Id} ({rp.PackageId} : {rp.Version}) not installed.", Status.Error);
missingWorkloads.Add(rp);
ReportStatus($"{rp.Id} ({rp.PackageId} : {rp.Version}) is not installed.", Status.Error);
missingWorkloads.Add(rp);
}
}

Expand Down
97 changes: 61 additions & 36 deletions UnoCheck/DotNet/DotNetWorkloadManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ namespace DotNetCheck.DotNet
{
public class DotNetWorkloadManager
{
private record WorkloadListResult(string[] installed);

public DotNetWorkloadManager(string sdkRoot, string sdkVersion, params string[] nugetPackageSources)
{
SdkRoot = sdkRoot;
Expand Down Expand Up @@ -81,18 +83,23 @@ string WriteRollbackFile(Manifest.DotNetWorkload[] workloads)
return rollbackFile;
}

const string RollbackOutputBeginMarker = "==workloadRollbackDefinitionJsonOutputStart==";
const string RollbackOutputEndMarker = "==workloadRollbackDefinitionJsonOutputEnd==";
private (string begin, string end) RollbackOutputMarker = (
"==workloadRollbackDefinitionJsonOutputStart==",
"==workloadRollbackDefinitionJsonOutputEnd==");

private (string begin, string end) ListOutputMarker = (
"==workloadListJsonOutputStart==",
"==workloadListJsonOutputEnd==");

public async Task<(string id, string version, string sdkVersion)[]> GetInstalledWorkloads()
public async Task<string[]> GetInstalledWorkloads()
{
var dotnetExe = Path.Combine(SdkRoot, DotNetSdk.DotNetExeName);

var args = new List<string>
{
"workload",
"update",
"--print-rollback"
"list",
"--machine-readable"
};

var r = await Util.WrapShellCommandWithSudo(dotnetExe, DotNetCliWorkingDir, Util.Verbose, args.ToArray());
Expand All @@ -101,33 +108,32 @@ string WriteRollbackFile(Manifest.DotNetWorkload[] workloads)
if (r.ExitCode != 0)
throw new Exception("Workload command failed: `dotnet " + string.Join(' ', args) + "`");

var output = string.Join(" ", r.StandardOutput);
var output = FilterWorkloadCommandOutput(string.Join(" ", r.StandardOutput), ListOutputMarker);

var isNet8OrBelow = NuGetVersion.Parse(SdkVersion) < DotNetCheck.Manifest.DotNetSdk.Version9Preview3;
// example of output {"installed":["wasm-tools"],"updateAvailable":[]}
var workloads = JsonSerializer.Deserialize<WorkloadListResult>(output);

if(isNet8OrBelow)
{
var startIndex = output.IndexOf(RollbackOutputBeginMarker);
var endIndex = output.IndexOf(RollbackOutputEndMarker);

if (startIndex >= 0 && endIndex >= 0)
{
// net8 and earlier use markers
var start = startIndex + RollbackOutputBeginMarker.Length;
output = output.Substring(start, endIndex - start);
}
}
else
return workloads.installed;
}

public async Task<(string id, string version, string sdkVersion)[]> GetAvailableWorkloads()
{
var dotnetExe = Path.Combine(SdkRoot, DotNetSdk.DotNetExeName);

var args = new List<string>
{
// This is needed to match the output of
// https://github.com/dotnet/sdk/blob/9a965db906ca70f57c4d44df1e0da09a5b662441/src/Cli/dotnet/commands/dotnet-workload/WorkloadIntegrityChecker.cs#L43
var startIndex = output.IndexOf("{");
"workload",
"update",
"--print-rollback"
};

if (startIndex >= 0)
{
output = output.Substring(startIndex);
}
}
var r = await Util.WrapShellCommandWithSudo(dotnetExe, DotNetCliWorkingDir, Util.Verbose, args.ToArray());

// Throw if this failed with a bad exit code
if (r.ExitCode != 0)
throw new Exception("Workload command failed: `dotnet " + string.Join(' ', args) + "`");

var output = FilterWorkloadCommandOutput(string.Join(" ", r.StandardOutput), RollbackOutputMarker);

var workloads = JsonSerializer.Deserialize<Dictionary<string, string>>(output);

Expand Down Expand Up @@ -194,17 +200,36 @@ async Task CliRepair()
throw new Exception("Workload Repair failed: `dotnet " + string.Join(' ', args) + "`");
}

string GetInstalledWorkloadMetadataDir()
private string FilterWorkloadCommandOutput(string output, (string begin, string end) marker)
{
int last2DigitsTo0(int versionBuild)
=> versionBuild / 100 * 100;
var isNet8OrBelow = NuGetVersion.Parse(SdkVersion) < DotNetCheck.Manifest.DotNetSdk.Version9Preview3;

if (!Version.TryParse(SdkVersion.Split('-')[0], out var result))
throw new ArgumentException("Invalid 'SdkVersion' version: " + SdkVersion);
if (isNet8OrBelow)
{
var startIndex = output.IndexOf(marker.begin);
var endIndex = output.IndexOf(marker.end);

var sdkVersionBand = $"{result.Major}.{result.Minor}.{last2DigitsTo0(result.Build)}";

return Path.Combine(SdkRoot, "metadata", "workloads", sdkVersionBand, "InstalledWorkloads");
if (startIndex >= 0 && endIndex >= 0)
{
// net8 and earlier use markers
var start = startIndex + marker.begin.Length;
output = output.Substring(start, endIndex - start);
}
}
else
{
// This is needed to match the output of
// https://github.com/dotnet/sdk/blob/9a965db906ca70f57c4d44df1e0da09a5b662441/src/Cli/dotnet/commands/dotnet-workload/WorkloadIntegrityChecker.cs#L43
var startIndex = output.IndexOf("{");

if (startIndex >= 0)
{
output = output.Substring(startIndex);
}
}

return output;
}

}
}

0 comments on commit 0d79f14

Please sign in to comment.