Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use install state in workload manifest provider #33872

Merged
merged 11 commits into from
Jul 9, 2023
Merged
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