Skip to content

Commit 018e421

Browse files
authored
Use install state in workload manifest provider (#33872)
2 parents f3729d4 + 8de4e03 commit 018e421

30 files changed

+1011
-260
lines changed

src/Cli/dotnet/commands/dotnet-workload/InstallType.cs

Lines changed: 0 additions & 20 deletions
This file was deleted.

src/Cli/dotnet/commands/dotnet-workload/WorkloadCommandParser.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,9 @@ internal static void ShowWorkloadsInfo(ParseResult parseResult = null, IWorkload
7878
reporter.WriteLine($" {workloadManifest.ManifestPath,align}");
7979

8080
reporter.Write($"{separator}{CommonStrings.WorkloadInstallTypeColumn}:");
81-
reporter.WriteLine($" {WorkloadInstallerFactory.GetWorkloadInstallType(new SdkFeatureBand(workloadFeatureBand), dotnetPath),align}"
81+
reporter.WriteLine($" {WorkloadInstallType.GetWorkloadInstallType(new SdkFeatureBand(workloadFeatureBand), dotnetPath).ToString(),align}"
8282
);
83+
reporter.WriteLine("");
8384
}
8485
}
8586

src/Cli/dotnet/commands/dotnet-workload/install/WorkloadInstallerFactory.cs

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public static IInstaller GetWorkloadInstaller(
2929
bool elevationRequired = true)
3030
{
3131
dotnetDir = string.IsNullOrWhiteSpace(dotnetDir) ? Path.GetDirectoryName(Environment.ProcessPath) : dotnetDir;
32-
var installType = GetWorkloadInstallType(sdkFeatureBand, dotnetDir);
32+
var installType = WorkloadInstallType.GetWorkloadInstallType(sdkFeatureBand, dotnetDir);
3333

3434
if (installType == InstallType.Msi)
3535
{
@@ -62,24 +62,6 @@ public static IInstaller GetWorkloadInstaller(
6262
restoreActionConfig: restoreActionConfig);
6363
}
6464

65-
/// <summary>
66-
/// Determines the <see cref="InstallType"/> associated with a specific SDK version.
67-
/// </summary>
68-
/// <param name="sdkFeatureBand">The SDK version to check.</param>
69-
/// <returns>The <see cref="InstallType"/> associated with the SDK.</returns>
70-
public static InstallType GetWorkloadInstallType(SdkFeatureBand sdkFeatureBand, string dotnetDir)
71-
{
72-
string installerTypePath = Path.Combine(dotnetDir, "metadata",
73-
"workloads", $"{sdkFeatureBand.ToStringWithoutPrerelease()}", "installertype");
74-
75-
if (File.Exists(Path.Combine(installerTypePath, "msi")))
76-
{
77-
return InstallType.Msi;
78-
}
79-
80-
return InstallType.FileBased;
81-
}
82-
8365
private static bool CanWriteToDotnetRoot(string dotnetDir = null)
8466
{
8567
dotnetDir = dotnetDir ?? Path.GetDirectoryName(Environment.ProcessPath);

src/Resolvers/Microsoft.NET.Sdk.WorkloadMSBuildSdkResolver/CachingWorkloadResolver.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ private static ResolutionResult Resolve(string sdkReferenceName, IWorkloadManife
139139
else if (sdkReferenceName.Equals("Microsoft.NET.SDK.WorkloadManifestTargetsLocator", StringComparison.OrdinalIgnoreCase))
140140
{
141141
List<string> workloadManifestPaths = new List<string>();
142-
foreach (var manifestDirectory in manifestProvider.GetManifestDirectories())
142+
foreach (var manifestDirectory in manifestProvider.GetManifests().Select(m => m.ManifestDirectory))
143143
{
144144
var workloadManifestTargetPath = Path.Combine(manifestDirectory, "WorkloadManifest.targets");
145145
if (File.Exists(workloadManifestTargetPath))

src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/IWorkloadManifestProvider.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@ public interface IWorkloadManifestProvider
1515
{
1616
IEnumerable<ReadableWorkloadManifest> GetManifests();
1717

18-
IEnumerable<string> GetManifestDirectories();
19-
2018
string GetSdkFeatureBand();
2119
}
2220
}

src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/ReadableWorkloadManifest.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,21 @@ namespace Microsoft.NET.Sdk.WorkloadManifestReader
1313
public class ReadableWorkloadManifest
1414
{
1515
public string ManifestId { get; }
16+
17+
public string ManifestDirectory { get; }
18+
1619
public string ManifestPath { get; }
1720

1821
readonly Func<Stream> _openManifestStreamFunc;
1922

2023

2124
readonly Func<Stream?> _openLocalizationStream;
2225

23-
public ReadableWorkloadManifest(string manifestId, string manifestPath, Func<Stream> openManifestStreamFunc, Func<Stream?> openLocalizationStream)
26+
public ReadableWorkloadManifest(string manifestId, string manifestDirectory, string manifestPath, Func<Stream> openManifestStreamFunc, Func<Stream?> openLocalizationStream)
2427
{
2528
ManifestId = manifestId;
2629
ManifestPath = manifestPath;
30+
ManifestDirectory = manifestDirectory;
2731
_openManifestStreamFunc = openManifestStreamFunc;
2832
_openLocalizationStream = openLocalizationStream;
2933
}

src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/SdkDirectoryWorkloadManifestProvider.GlobalJsonReader.cs

Lines changed: 9 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ public partial class SdkDirectoryWorkloadManifestProvider
2323
{
2424
static class GlobalJsonReader
2525
{
26-
public static string? GetWorkloadVersionFromGlobalJson(string globalJsonPath)
26+
public static string? GetWorkloadVersionFromGlobalJson(string? globalJsonPath)
2727
{
2828
if (string.IsNullOrEmpty(globalJsonPath))
2929
{
@@ -48,7 +48,7 @@ static class GlobalJsonReader
4848

4949
string? workloadVersion = null;
5050

51-
ConsumeToken(ref reader, JsonTokenType.StartObject);
51+
JsonReader.ConsumeToken(ref reader, JsonTokenType.StartObject);
5252
while (reader.Read())
5353
{
5454
switch (reader.TokenType)
@@ -57,7 +57,7 @@ static class GlobalJsonReader
5757
var propName = reader.GetString();
5858
if (string.Equals("sdk", propName, StringComparison.OrdinalIgnoreCase))
5959
{
60-
ConsumeToken(ref reader, JsonTokenType.StartObject);
60+
JsonReader.ConsumeToken(ref reader, JsonTokenType.StartObject);
6161

6262
bool readingSdk = true;
6363
while (readingSdk && reader.Read())
@@ -68,115 +68,36 @@ static class GlobalJsonReader
6868
var sdkPropName = reader.GetString();
6969
if (string.Equals("workloadVersion", sdkPropName, StringComparison.OrdinalIgnoreCase))
7070
{
71-
workloadVersion = ReadString(ref reader);
71+
workloadVersion = JsonReader.ReadString(ref reader);
7272
}
7373
else
7474
{
75-
ConsumeValue(ref reader);
75+
JsonReader.ConsumeValue(ref reader);
7676
}
7777
break;
7878
case JsonTokenType.EndObject:
7979
readingSdk = false;
8080
break;
8181
default:
82-
throw new GlobalJsonFormatException(Strings.UnexpectedTokenAtOffset, reader.TokenType, reader.TokenStartIndex);
82+
throw new JsonFormatException(Strings.UnexpectedTokenAtOffset, reader.TokenType, reader.TokenStartIndex);
8383
}
8484
}
8585
}
8686
else
8787
{
88-
ConsumeValue(ref reader);
88+
JsonReader.ConsumeValue(ref reader);
8989
}
9090
break;
9191

9292
case JsonTokenType.EndObject:
9393
return workloadVersion;
9494
default:
95-
throw new GlobalJsonFormatException(Strings.UnexpectedTokenAtOffset, reader.TokenType, reader.TokenStartIndex);
95+
throw new JsonFormatException(Strings.UnexpectedTokenAtOffset, reader.TokenType, reader.TokenStartIndex);
9696
}
9797
}
9898

99-
throw new GlobalJsonFormatException(Strings.IncompleteDocument);
99+
throw new JsonFormatException(Strings.IncompleteDocument);
100100
}
101-
102-
/// <summary>
103-
/// this expects the reader to be before the value token, and leaves it on the last token of the value
104-
/// </summary>
105-
private static bool ConsumeValue(ref Utf8JsonStreamReader reader)
106-
{
107-
if (!reader.Read())
108-
{
109-
return false;
110-
}
111-
112-
var tokenType = reader.TokenType;
113-
if (tokenType != JsonTokenType.StartArray && tokenType != JsonTokenType.StartObject)
114-
{
115-
return true;
116-
}
117-
118-
var depth = reader.CurrentDepth;
119-
do
120-
{
121-
if (!reader.Read())
122-
{
123-
return false;
124-
}
125-
} while (reader.CurrentDepth > depth);
126-
127-
return true;
128-
}
129-
130-
private static void ConsumeToken(ref Utf8JsonStreamReader reader, JsonTokenType expected)
131-
{
132-
if (reader.Read() && expected == reader.TokenType)
133-
{
134-
return;
135-
}
136-
ThrowUnexpectedTokenException(ref reader, expected);
137-
}
138-
139-
private static void ThrowUnexpectedTokenException(ref Utf8JsonStreamReader reader, JsonTokenType expected)
140-
{
141-
string key;
142-
if (expected.IsBool())
143-
{
144-
key = Strings.ExpectedBoolAtOffset;
145-
}
146-
else if (expected.IsInt())
147-
{
148-
key = Strings.ExpectedIntegerAtOffset;
149-
}
150-
else if (expected == JsonTokenType.String)
151-
{
152-
key = Strings.ExpectedStringAtOffset;
153-
}
154-
else
155-
{
156-
throw new GlobalJsonFormatException(Strings.ExpectedTokenAtOffset, expected, reader.TokenStartIndex);
157-
}
158-
159-
throw new GlobalJsonFormatException(key, reader.TokenStartIndex);
160-
}
161-
162-
private static string ReadString(ref Utf8JsonStreamReader reader)
163-
{
164-
ConsumeToken(ref reader, JsonTokenType.String);
165-
return reader.GetString();
166-
}
167-
}
168-
169-
[Serializable]
170-
internal class GlobalJsonFormatException : Exception
171-
{
172-
public GlobalJsonFormatException() { }
173-
public GlobalJsonFormatException(string messageFormat, params object?[] args) : base(string.Format(messageFormat, args)) { }
174-
public GlobalJsonFormatException(string message) : base(message) { }
175-
public GlobalJsonFormatException(string message, Exception inner) : base(message, inner) { }
176-
#if NET8_0_OR_GREATER
177-
[Obsolete(DiagnosticId = "SYSLIB0051")] // add this attribute to the serialization ctor
178-
#endif
179-
protected GlobalJsonFormatException(SerializationInfo info, StreamingContext context) : base(info, context) { }
180101
}
181102
}
182103
}
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
// Copyright (c) .NET Foundation and contributors. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
5+
using System;
6+
using System.Collections.Generic;
7+
using System.IO;
8+
using System.Linq;
9+
using Microsoft.NET.Sdk.Localization;
10+
using static Microsoft.NET.Sdk.WorkloadManifestReader.WorkloadManifestReader;
11+
using System.Runtime.Serialization;
12+
using Microsoft.Deployment.DotNet.Releases;
13+
14+
#if USE_SYSTEM_TEXT_JSON
15+
using System.Text.Json;
16+
#else
17+
using Newtonsoft.Json;
18+
using JsonTokenType = Newtonsoft.Json.JsonToken;
19+
#endif
20+
21+
namespace Microsoft.NET.Sdk.WorkloadManifestReader
22+
{
23+
public partial class SdkDirectoryWorkloadManifestProvider
24+
{
25+
class InstallState
26+
{
27+
public string? WorkloadSetVersion { get; set; }
28+
public WorkloadSet? Manifests { get; set; }
29+
}
30+
31+
static class InstallStateReader
32+
{
33+
public static InstallState ReadInstallState(string installStatePath)
34+
{
35+
using var fileStream = File.OpenRead(installStatePath);
36+
37+
#if USE_SYSTEM_TEXT_JSON
38+
var readerOptions = new JsonReaderOptions
39+
{
40+
AllowTrailingCommas = true,
41+
CommentHandling = JsonCommentHandling.Skip
42+
};
43+
var reader = new Utf8JsonStreamReader(fileStream, readerOptions);
44+
#else
45+
using var textReader = new StreamReader(fileStream, System.Text.Encoding.UTF8, true);
46+
using var jsonReader = new JsonTextReader(textReader);
47+
48+
var reader = new Utf8JsonStreamReader(jsonReader);
49+
#endif
50+
51+
InstallState installState = new();
52+
53+
JsonReader.ConsumeToken(ref reader, JsonTokenType.StartObject);
54+
while (reader.Read())
55+
{
56+
switch (reader.TokenType)
57+
{
58+
case JsonTokenType.PropertyName:
59+
var propName = reader.GetString();
60+
if (string.Equals("workloadVersion", propName, StringComparison.OrdinalIgnoreCase))
61+
{
62+
installState.WorkloadSetVersion = JsonReader.ReadString(ref reader);
63+
}
64+
else if (string.Equals("manifests", propName, StringComparison.OrdinalIgnoreCase))
65+
{
66+
installState.Manifests = ReadManifests(ref reader);
67+
}
68+
else
69+
{
70+
JsonReader.ConsumeValue(ref reader);
71+
}
72+
break;
73+
74+
case JsonTokenType.EndObject:
75+
return installState;
76+
default:
77+
throw new JsonFormatException(Strings.UnexpectedTokenAtOffset, reader.TokenType, reader.TokenStartIndex);
78+
}
79+
}
80+
81+
throw new JsonFormatException(Strings.IncompleteDocument);
82+
}
83+
84+
static WorkloadSet ReadManifests(ref Utf8JsonStreamReader reader)
85+
{
86+
JsonReader.ConsumeToken(ref reader, JsonTokenType.StartObject);
87+
Dictionary<string, string> workloadSetDict = new();
88+
89+
while (reader.Read())
90+
{
91+
switch (reader.TokenType)
92+
{
93+
case JsonTokenType.PropertyName:
94+
var propName = reader.GetString();
95+
var propValue = JsonReader.ReadString(ref reader);
96+
workloadSetDict[propName] = propValue;
97+
break;
98+
case JsonTokenType.EndObject:
99+
return WorkloadSet.FromDictionaryForJson(workloadSetDict, new SdkFeatureBand(new ReleaseVersion(0,0,0)));
100+
default:
101+
throw new JsonFormatException(Strings.UnexpectedTokenAtOffset, reader.TokenType, reader.TokenStartIndex);
102+
}
103+
}
104+
throw new JsonFormatException(Strings.IncompleteDocument);
105+
}
106+
}
107+
}
108+
}
109+

0 commit comments

Comments
 (0)