Skip to content

Commit

Permalink
Use install state in workload manifest provider (#33872)
Browse files Browse the repository at this point in the history
  • Loading branch information
dsplaisted authored Jul 9, 2023
2 parents f3729d4 + 8de4e03 commit 018e421
Show file tree
Hide file tree
Showing 30 changed files with 1,011 additions and 260 deletions.
20 changes: 0 additions & 20 deletions src/Cli/dotnet/commands/dotnet-workload/InstallType.cs

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,9 @@ internal static void ShowWorkloadsInfo(ParseResult parseResult = null, IWorkload
reporter.WriteLine($" {workloadManifest.ManifestPath,align}");

reporter.Write($"{separator}{CommonStrings.WorkloadInstallTypeColumn}:");
reporter.WriteLine($" {WorkloadInstallerFactory.GetWorkloadInstallType(new SdkFeatureBand(workloadFeatureBand), dotnetPath),align}"
reporter.WriteLine($" {WorkloadInstallType.GetWorkloadInstallType(new SdkFeatureBand(workloadFeatureBand), dotnetPath).ToString(),align}"
);
reporter.WriteLine("");
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public static IInstaller GetWorkloadInstaller(
bool elevationRequired = true)
{
dotnetDir = string.IsNullOrWhiteSpace(dotnetDir) ? Path.GetDirectoryName(Environment.ProcessPath) : dotnetDir;
var installType = GetWorkloadInstallType(sdkFeatureBand, dotnetDir);
var installType = WorkloadInstallType.GetWorkloadInstallType(sdkFeatureBand, dotnetDir);

if (installType == InstallType.Msi)
{
Expand Down Expand Up @@ -62,24 +62,6 @@ public static IInstaller GetWorkloadInstaller(
restoreActionConfig: restoreActionConfig);
}

/// <summary>
/// Determines the <see cref="InstallType"/> associated with a specific SDK version.
/// </summary>
/// <param name="sdkFeatureBand">The SDK version to check.</param>
/// <returns>The <see cref="InstallType"/> associated with the SDK.</returns>
public static InstallType GetWorkloadInstallType(SdkFeatureBand sdkFeatureBand, string dotnetDir)
{
string installerTypePath = Path.Combine(dotnetDir, "metadata",
"workloads", $"{sdkFeatureBand.ToStringWithoutPrerelease()}", "installertype");

if (File.Exists(Path.Combine(installerTypePath, "msi")))
{
return InstallType.Msi;
}

return InstallType.FileBased;
}

private static bool CanWriteToDotnetRoot(string dotnetDir = null)
{
dotnetDir = dotnetDir ?? Path.GetDirectoryName(Environment.ProcessPath);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ private static ResolutionResult Resolve(string sdkReferenceName, IWorkloadManife
else if (sdkReferenceName.Equals("Microsoft.NET.SDK.WorkloadManifestTargetsLocator", StringComparison.OrdinalIgnoreCase))
{
List<string> workloadManifestPaths = new List<string>();
foreach (var manifestDirectory in manifestProvider.GetManifestDirectories())
foreach (var manifestDirectory in manifestProvider.GetManifests().Select(m => m.ManifestDirectory))
{
var workloadManifestTargetPath = Path.Combine(manifestDirectory, "WorkloadManifest.targets");
if (File.Exists(workloadManifestTargetPath))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@ public interface IWorkloadManifestProvider
{
IEnumerable<ReadableWorkloadManifest> GetManifests();

IEnumerable<string> GetManifestDirectories();

string GetSdkFeatureBand();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,21 @@ namespace Microsoft.NET.Sdk.WorkloadManifestReader
public class ReadableWorkloadManifest
{
public string ManifestId { get; }

public string ManifestDirectory { get; }

public string ManifestPath { get; }

readonly Func<Stream> _openManifestStreamFunc;


readonly Func<Stream?> _openLocalizationStream;

public ReadableWorkloadManifest(string manifestId, string manifestPath, Func<Stream> openManifestStreamFunc, Func<Stream?> openLocalizationStream)
public ReadableWorkloadManifest(string manifestId, string manifestDirectory, string manifestPath, Func<Stream> openManifestStreamFunc, Func<Stream?> openLocalizationStream)
{
ManifestId = manifestId;
ManifestPath = manifestPath;
ManifestDirectory = manifestDirectory;
_openManifestStreamFunc = openManifestStreamFunc;
_openLocalizationStream = openLocalizationStream;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public partial class SdkDirectoryWorkloadManifestProvider
{
static class GlobalJsonReader
{
public static string? GetWorkloadVersionFromGlobalJson(string globalJsonPath)
public static string? GetWorkloadVersionFromGlobalJson(string? globalJsonPath)
{
if (string.IsNullOrEmpty(globalJsonPath))
{
Expand All @@ -48,7 +48,7 @@ static class GlobalJsonReader

string? workloadVersion = null;

ConsumeToken(ref reader, JsonTokenType.StartObject);
JsonReader.ConsumeToken(ref reader, JsonTokenType.StartObject);
while (reader.Read())
{
switch (reader.TokenType)
Expand All @@ -57,7 +57,7 @@ static class GlobalJsonReader
var propName = reader.GetString();
if (string.Equals("sdk", propName, StringComparison.OrdinalIgnoreCase))
{
ConsumeToken(ref reader, JsonTokenType.StartObject);
JsonReader.ConsumeToken(ref reader, JsonTokenType.StartObject);

bool readingSdk = true;
while (readingSdk && reader.Read())
Expand All @@ -68,115 +68,36 @@ static class GlobalJsonReader
var sdkPropName = reader.GetString();
if (string.Equals("workloadVersion", sdkPropName, StringComparison.OrdinalIgnoreCase))
{
workloadVersion = ReadString(ref reader);
workloadVersion = JsonReader.ReadString(ref reader);
}
else
{
ConsumeValue(ref reader);
JsonReader.ConsumeValue(ref reader);
}
break;
case JsonTokenType.EndObject:
readingSdk = false;
break;
default:
throw new GlobalJsonFormatException(Strings.UnexpectedTokenAtOffset, reader.TokenType, reader.TokenStartIndex);
throw new JsonFormatException(Strings.UnexpectedTokenAtOffset, reader.TokenType, reader.TokenStartIndex);
}
}
}
else
{
ConsumeValue(ref reader);
JsonReader.ConsumeValue(ref reader);
}
break;

case JsonTokenType.EndObject:
return workloadVersion;
default:
throw new GlobalJsonFormatException(Strings.UnexpectedTokenAtOffset, reader.TokenType, reader.TokenStartIndex);
throw new JsonFormatException(Strings.UnexpectedTokenAtOffset, reader.TokenType, reader.TokenStartIndex);
}
}

throw new GlobalJsonFormatException(Strings.IncompleteDocument);
throw new JsonFormatException(Strings.IncompleteDocument);
}

/// <summary>
/// this expects the reader to be before the value token, and leaves it on the last token of the value
/// </summary>
private static bool ConsumeValue(ref Utf8JsonStreamReader reader)
{
if (!reader.Read())
{
return false;
}

var tokenType = reader.TokenType;
if (tokenType != JsonTokenType.StartArray && tokenType != JsonTokenType.StartObject)
{
return true;
}

var depth = reader.CurrentDepth;
do
{
if (!reader.Read())
{
return false;
}
} while (reader.CurrentDepth > depth);

return true;
}

private static void ConsumeToken(ref Utf8JsonStreamReader reader, JsonTokenType expected)
{
if (reader.Read() && expected == reader.TokenType)
{
return;
}
ThrowUnexpectedTokenException(ref reader, expected);
}

private static void ThrowUnexpectedTokenException(ref Utf8JsonStreamReader reader, JsonTokenType expected)
{
string key;
if (expected.IsBool())
{
key = Strings.ExpectedBoolAtOffset;
}
else if (expected.IsInt())
{
key = Strings.ExpectedIntegerAtOffset;
}
else if (expected == JsonTokenType.String)
{
key = Strings.ExpectedStringAtOffset;
}
else
{
throw new GlobalJsonFormatException(Strings.ExpectedTokenAtOffset, expected, reader.TokenStartIndex);
}

throw new GlobalJsonFormatException(key, reader.TokenStartIndex);
}

private static string ReadString(ref Utf8JsonStreamReader reader)
{
ConsumeToken(ref reader, JsonTokenType.String);
return reader.GetString();
}
}

[Serializable]
internal class GlobalJsonFormatException : Exception
{
public GlobalJsonFormatException() { }
public GlobalJsonFormatException(string messageFormat, params object?[] args) : base(string.Format(messageFormat, args)) { }
public GlobalJsonFormatException(string message) : base(message) { }
public GlobalJsonFormatException(string message, Exception inner) : base(message, inner) { }
#if NET8_0_OR_GREATER
[Obsolete(DiagnosticId = "SYSLIB0051")] // add this attribute to the serialization ctor
#endif
protected GlobalJsonFormatException(SerializationInfo info, StreamingContext context) : base(info, context) { }
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.


using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Microsoft.NET.Sdk.Localization;
using static Microsoft.NET.Sdk.WorkloadManifestReader.WorkloadManifestReader;
using System.Runtime.Serialization;
using Microsoft.Deployment.DotNet.Releases;

#if USE_SYSTEM_TEXT_JSON
using System.Text.Json;
#else
using Newtonsoft.Json;
using JsonTokenType = Newtonsoft.Json.JsonToken;
#endif

namespace Microsoft.NET.Sdk.WorkloadManifestReader
{
public partial class SdkDirectoryWorkloadManifestProvider
{
class InstallState
{
public string? WorkloadSetVersion { get; set; }
public WorkloadSet? Manifests { get; set; }
}

static class InstallStateReader
{
public static InstallState ReadInstallState(string installStatePath)
{
using var fileStream = File.OpenRead(installStatePath);

#if USE_SYSTEM_TEXT_JSON
var readerOptions = new JsonReaderOptions
{
AllowTrailingCommas = true,
CommentHandling = JsonCommentHandling.Skip
};
var reader = new Utf8JsonStreamReader(fileStream, readerOptions);
#else
using var textReader = new StreamReader(fileStream, System.Text.Encoding.UTF8, true);
using var jsonReader = new JsonTextReader(textReader);

var reader = new Utf8JsonStreamReader(jsonReader);
#endif

InstallState installState = new();

JsonReader.ConsumeToken(ref reader, JsonTokenType.StartObject);
while (reader.Read())
{
switch (reader.TokenType)
{
case JsonTokenType.PropertyName:
var propName = reader.GetString();
if (string.Equals("workloadVersion", propName, StringComparison.OrdinalIgnoreCase))
{
installState.WorkloadSetVersion = JsonReader.ReadString(ref reader);
}
else if (string.Equals("manifests", propName, StringComparison.OrdinalIgnoreCase))
{
installState.Manifests = ReadManifests(ref reader);
}
else
{
JsonReader.ConsumeValue(ref reader);
}
break;

case JsonTokenType.EndObject:
return installState;
default:
throw new JsonFormatException(Strings.UnexpectedTokenAtOffset, reader.TokenType, reader.TokenStartIndex);
}
}

throw new JsonFormatException(Strings.IncompleteDocument);
}

static WorkloadSet ReadManifests(ref Utf8JsonStreamReader reader)
{
JsonReader.ConsumeToken(ref reader, JsonTokenType.StartObject);
Dictionary<string, string> workloadSetDict = new();

while (reader.Read())
{
switch (reader.TokenType)
{
case JsonTokenType.PropertyName:
var propName = reader.GetString();
var propValue = JsonReader.ReadString(ref reader);
workloadSetDict[propName] = propValue;
break;
case JsonTokenType.EndObject:
return WorkloadSet.FromDictionaryForJson(workloadSetDict, new SdkFeatureBand(new ReleaseVersion(0,0,0)));
default:
throw new JsonFormatException(Strings.UnexpectedTokenAtOffset, reader.TokenType, reader.TokenStartIndex);
}
}
throw new JsonFormatException(Strings.IncompleteDocument);
}
}
}
}

Loading

0 comments on commit 018e421

Please sign in to comment.