Skip to content

Commit 9265990

Browse files
authored
Fix userlocal (dotnet#41735)
2 parents 121f7a9 + 5e929bb commit 9265990

File tree

10 files changed

+63
-53
lines changed

10 files changed

+63
-53
lines changed

src/Cli/dotnet/commands/InstallingWorkloadCommand.cs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ internal abstract class InstallingWorkloadCommand : WorkloadCommandBase
3030
protected readonly string _downloadToCacheOption;
3131
protected readonly string _dotnetPath;
3232
protected readonly string _userProfileDir;
33+
protected readonly string _workloadRootDir;
3334
protected readonly bool _checkIfManifestExist;
3435
protected readonly ReleaseVersion _sdkVersion;
3536
protected readonly SdkFeatureBand _sdkFeatureBand;
@@ -92,8 +93,9 @@ public InstallingWorkloadCommand(
9293

9394
_dotnetPath = creationResult.DotnetPath;
9495
_userProfileDir = creationResult.UserProfileDir;
95-
_sdkVersion = creationResult.SdkVersion;
9696
_sdkFeatureBand = new SdkFeatureBand(creationResult.SdkVersion);
97+
_workloadRootDir = WorkloadFileBasedInstall.IsUserLocal(_dotnetPath, _sdkFeatureBand.ToString()) ? _userProfileDir : _dotnetPath;
98+
_sdkVersion = creationResult.SdkVersion;
9799
_workloadResolver = creationResult.WorkloadResolver;
98100
_targetSdkVersion ??= _sdkVersion;
99101

@@ -125,7 +127,7 @@ protected static Dictionary<string, string> GetInstallStateContents(IEnumerable<
125127

126128
InstallStateContents GetCurrentInstallState()
127129
{
128-
return GetCurrentInstallState(_sdkFeatureBand, _dotnetPath);
130+
return GetCurrentInstallState(_sdkFeatureBand, _workloadRootDir);
129131
}
130132

131133
static InstallStateContents GetCurrentInstallState(SdkFeatureBand sdkFeatureBand, string dotnetDir)
@@ -141,7 +143,7 @@ public static bool ShouldUseWorkloadSetMode(SdkFeatureBand sdkFeatureBand, strin
141143

142144
protected void UpdateWorkloadManifests(ITransactionContext context, DirectoryPath? offlineCache)
143145
{
144-
var updateToLatestWorkloadSet = ShouldUseWorkloadSetMode(_sdkFeatureBand, _dotnetPath);
146+
var updateToLatestWorkloadSet = ShouldUseWorkloadSetMode(_sdkFeatureBand, _workloadRootDir);
145147
if (UseRollback && updateToLatestWorkloadSet)
146148
{
147149
// Rollback files are only for loose manifests. Update the mode to be loose manifests.
@@ -157,7 +159,7 @@ protected void UpdateWorkloadManifests(ITransactionContext context, DirectoryPat
157159
// If a workload set version is specified, then switch to workload set update mode
158160
// Check to make sure the value needs to be changed, as updating triggers a UAC prompt
159161
// for MSI-based installs.
160-
if (!ShouldUseWorkloadSetMode(_sdkFeatureBand, _dotnetPath))
162+
if (!ShouldUseWorkloadSetMode(_sdkFeatureBand, _workloadRootDir))
161163
{
162164
_workloadInstaller.UpdateInstallMode(_sdkFeatureBand, true);
163165
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ internal static void ShowWorkloadsInfo(ParseResult parseResult = null, WorkloadI
6161
reporter.WriteLine($" Workload version: {workloadInfoHelper.ManifestProvider.GetWorkloadVersion()}");
6262
}
6363

64-
var useWorkloadSets = InstallStateContents.FromPath(Path.Combine(WorkloadInstallType.GetInstallStateFolder(workloadInfoHelper._currentSdkFeatureBand, workloadInfoHelper.DotnetPath), "default.json")).UseWorkloadSets;
64+
var useWorkloadSets = InstallStateContents.FromPath(Path.Combine(WorkloadInstallType.GetInstallStateFolder(workloadInfoHelper._currentSdkFeatureBand, workloadInfoHelper.UserLocalPath), "default.json")).UseWorkloadSets;
6565
var workloadSetsString = useWorkloadSets == true ? "workload sets" : "loose manifests";
6666
reporter.WriteLine(string.Format(CommonStrings.WorkloadManifestInstallationConfiguration, workloadSetsString));
6767

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ internal class WorkloadInfoHelper : IWorkloadInfoHelper
1818
public readonly SdkFeatureBand _currentSdkFeatureBand;
1919
private readonly string _targetSdkVersion;
2020
public string DotnetPath { get; }
21+
public string UserLocalPath { get; }
2122

2223
public WorkloadInfoHelper(
2324
bool isInteractive,
@@ -61,6 +62,8 @@ public WorkloadInfoHelper(
6162
shouldLog: false);
6263

6364
WorkloadRecordRepo = workloadRecordRepo ?? Installer.GetWorkloadInstallationRecordRepository();
65+
66+
UserLocalPath = dotnetDir ?? (WorkloadFileBasedInstall.IsUserLocal(DotnetPath, _currentSdkFeatureBand.ToString()) ? userProfileDir : DotnetPath);
6467
}
6568

6669
public IInstaller Installer { get; private init; }

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

Lines changed: 19 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ internal class FileBasedInstaller : IInstaller
2626
private const string InstalledWorkloadSetsDir = "InstalledWorkloadSets";
2727
protected readonly string _dotnetDir;
2828
protected readonly string _userProfileDir;
29+
protected readonly string _workloadRootDir;
2930
protected readonly DirectoryPath _tempPackagesDir;
3031
private readonly INuGetPackageDownloader _nugetPackageDownloader;
3132
private IWorkloadResolver _workloadResolver;
@@ -57,7 +58,8 @@ public FileBasedInstaller(IReporter reporter,
5758
new FirstPartyNuGetPackageSigningVerifier(), logger,
5859
restoreActionConfig: _restoreActionConfig);
5960
bool userLocal = WorkloadFileBasedInstall.IsUserLocal(_dotnetDir, sdkFeatureBand.ToString());
60-
_workloadMetadataDir = Path.Combine(userLocal ? _userProfileDir : _dotnetDir, "metadata", "workloads");
61+
_workloadRootDir = userLocal ? _userProfileDir : _dotnetDir;
62+
_workloadMetadataDir = Path.Combine(_workloadRootDir, "metadata", "workloads");
6163
_reporter = reporter;
6264
_sdkFeatureBand = sdkFeatureBand;
6365
_workloadResolver = workloadResolver;
@@ -92,7 +94,7 @@ public WorkloadSet InstallWorkloadSet(ITransactionContext context, string worklo
9294
string workloadSetPackageVersion = WorkloadSet.WorkloadSetVersionToWorkloadSetPackageVersion(workloadSetVersion, out workloadSetFeatureBand);
9395
var workloadSetPackageId = GetManifestPackageId(new ManifestId("Microsoft.NET.Workloads"), workloadSetFeatureBand);
9496

95-
var workloadSetPath = Path.Combine(_dotnetDir, "sdk-manifests", _sdkFeatureBand.ToString(), "workloadsets", workloadSetVersion);
97+
var workloadSetPath = Path.Combine(_workloadRootDir, "sdk-manifests", _sdkFeatureBand.ToString(), "workloadsets", workloadSetVersion);
9698

9799
try
98100
{
@@ -226,9 +228,7 @@ public void RepairWorkloads(IEnumerable<WorkloadId> workloadIds, SdkFeatureBand
226228

227229
string GetManifestInstallDirForFeatureBand(string sdkFeatureBand)
228230
{
229-
string rootInstallDir = WorkloadFileBasedInstall.IsUserLocal(_dotnetDir, _sdkFeatureBand.ToString()) ? _userProfileDir : _dotnetDir;
230-
var manifestInstallDir = Path.Combine(rootInstallDir, "sdk-manifests", sdkFeatureBand);
231-
return manifestInstallDir;
231+
return Path.Combine(_workloadRootDir, "sdk-manifests", sdkFeatureBand);
232232
}
233233

234234
public void InstallWorkloadManifest(ManifestVersionUpdate manifestUpdate, ITransactionContext transactionContext, DirectoryPath? offlineCache = null)
@@ -341,7 +341,7 @@ public IEnumerable<WorkloadDownload> GetDownloads(IEnumerable<WorkloadId> worklo
341341

342342
public void GarbageCollect(Func<string, IWorkloadResolver> getResolverForWorkloadSet, DirectoryPath? offlineCache = null, bool cleanAllPacks = false)
343343
{
344-
var garbageCollector = new WorkloadGarbageCollector(_dotnetDir, _sdkFeatureBand, _installationRecordRepository.GetInstalledWorkloads(_sdkFeatureBand), getResolverForWorkloadSet, Reporter.Verbose);
344+
var garbageCollector = new WorkloadGarbageCollector(_workloadRootDir, _sdkFeatureBand, _installationRecordRepository.GetInstalledWorkloads(_sdkFeatureBand), getResolverForWorkloadSet, Reporter.Verbose);
345345
garbageCollector.Collect();
346346

347347
var featureBandsWithWorkloadInstallRecords = _installationRecordRepository.GetFeatureBandsWithInstallationRecords();
@@ -479,46 +479,36 @@ public void GarbageCollect(Func<string, IWorkloadResolver> getResolverForWorkloa
479479

480480
public void AdjustWorkloadSetInInstallState(SdkFeatureBand sdkFeatureBand, string workloadVersion)
481481
{
482-
string path = Path.Combine(WorkloadInstallType.GetInstallStateFolder(_sdkFeatureBand, _dotnetDir), "default.json");
483-
Directory.CreateDirectory(Path.GetDirectoryName(path));
484-
var installStateContents = InstallStateContents.FromPath(path);
485-
installStateContents.WorkloadVersion = workloadVersion;
486-
File.WriteAllText(path, installStateContents.ToString());
482+
UpdateInstallState(sdkFeatureBand, contents => contents.WorkloadVersion = workloadVersion);
487483
}
488484

489485
public void RemoveManifestsFromInstallState(SdkFeatureBand sdkFeatureBand)
490486
{
491-
string path = Path.Combine(WorkloadInstallType.GetInstallStateFolder(_sdkFeatureBand, _dotnetDir), "default.json");
492-
493-
if (File.Exists(path))
494-
{
495-
var installStateContents = InstallStateContents.FromString(File.ReadAllText(path));
496-
installStateContents.Manifests = null;
497-
File.WriteAllText(path, installStateContents.ToString());
498-
}
487+
UpdateInstallState(sdkFeatureBand, contents => contents.Manifests = null);
499488
}
500489

501490
public void SaveInstallStateManifestVersions(SdkFeatureBand sdkFeatureBand, Dictionary<string, string> manifestContents)
502491
{
503-
string path = Path.Combine(WorkloadInstallType.GetInstallStateFolder(_sdkFeatureBand, _dotnetDir), "default.json");
504-
Directory.CreateDirectory(Path.GetDirectoryName(path));
505-
var installStateContents = InstallStateContents.FromPath(path);
506-
installStateContents.Manifests = manifestContents;
507-
File.WriteAllText(path, installStateContents.ToString());
492+
UpdateInstallState(sdkFeatureBand, contents => contents.Manifests = manifestContents);
508493
}
509494

510495
public void UpdateInstallMode(SdkFeatureBand sdkFeatureBand, bool? newMode)
511496
{
512-
string path = Path.Combine(WorkloadInstallType.GetInstallStateFolder(sdkFeatureBand, _dotnetDir), "default.json");
513-
Directory.CreateDirectory(Path.GetDirectoryName(path));
514-
var installStateContents = InstallStateContents.FromPath(path);
515-
installStateContents.UseWorkloadSets = newMode;
516-
File.WriteAllText(path, installStateContents.ToString());
497+
UpdateInstallState(sdkFeatureBand, contents => contents.UseWorkloadSets = newMode);
517498

518499
var newModeString = newMode == null ? "<null>" : (newMode.Value ? WorkloadConfigCommandParser.UpdateMode_WorkloadSet : WorkloadConfigCommandParser.UpdateMode_Manifests);
519500
_reporter.WriteLine(string.Format(LocalizableStrings.UpdatedWorkloadMode, newModeString));
520501
}
521502

503+
private void UpdateInstallState(SdkFeatureBand sdkFeatureBand, Action<InstallStateContents> update)
504+
{
505+
string path = Path.Combine(WorkloadInstallType.GetInstallStateFolder(sdkFeatureBand, _workloadRootDir), "default.json");
506+
Directory.CreateDirectory(Path.GetDirectoryName(path));
507+
var installStateContents = InstallStateContents.FromPath(path);
508+
update(installStateContents);
509+
File.WriteAllText(path, installStateContents.ToString());
510+
}
511+
522512
/// <summary>
523513
/// Remove all workload installation records that aren't from Visual Studio.
524514
/// </summary>

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ public override int Execute()
150150

151151
if (!_skipManifestUpdate)
152152
{
153-
var installStateFilePath = Path.Combine(WorkloadInstallType.GetInstallStateFolder(_sdkFeatureBand, _dotnetPath), "default.json");
153+
var installStateFilePath = Path.Combine(WorkloadInstallType.GetInstallStateFolder(_sdkFeatureBand, _workloadRootDir), "default.json");
154154
if (string.IsNullOrWhiteSpace(_fromRollbackDefinition) &&
155155
!SpecifiedWorkloadSetVersionOnCommandLine &&
156156
!SpecifiedWorkloadSetVersionInGlobalJson &&

src/Cli/dotnet/commands/dotnet-workload/list/WorkloadListCommand.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ public override int Execute()
7878
Reporter.WriteLine();
7979
var shouldPrintTable = globalJsonInformation?.WorkloadVersionInstalled != false;
8080
var shouldShowWorkloadSetVersion = globalJsonInformation is not null ||
81-
InstallStateContents.FromPath(Path.Combine(WorkloadInstallType.GetInstallStateFolder(_workloadListHelper._currentSdkFeatureBand, _workloadListHelper.DotnetPath), "default.json")).UseWorkloadSets == true;
81+
InstallStateContents.FromPath(Path.Combine(WorkloadInstallType.GetInstallStateFolder(_workloadListHelper._currentSdkFeatureBand, _workloadListHelper.UserLocalPath), "default.json")).UseWorkloadSets == true;
8282

8383
if (shouldShowWorkloadSetVersion)
8484
{

src/Cli/dotnet/commands/dotnet-workload/update/WorkloadUpdateCommand.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ public override int Execute()
8282
{
8383
_workloadManifestUpdater.UpdateAdvertisingManifestsAsync(
8484
_includePreviews,
85-
ShouldUseWorkloadSetMode(_sdkFeatureBand, _dotnetPath),
85+
ShouldUseWorkloadSetMode(_sdkFeatureBand, _workloadRootDir),
8686
string.IsNullOrWhiteSpace(_fromCacheOption) ?
8787
null :
8888
new DirectoryPath(_fromCacheOption))

src/Common/WorkloadFileBasedInstall.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
3+
using Microsoft.NET.Sdk.WorkloadManifestReader;
34

45
namespace Microsoft.DotNet.Workloads.Workload
56
{
@@ -34,7 +35,7 @@ static int Last2DigitsTo0(int versionBuild)
3435
sdkFeatureBand = $"{sdkVersionParsed.Major}.{sdkVersionParsed.Minor}.{Last2DigitsTo0(sdkVersionParsed.Build)}";
3536
}
3637

37-
return Path.Combine(dotnetDir, "metadata", "workloads", sdkFeatureBand, "userlocal");
38+
return Path.Combine(dotnetDir, "metadata", "workloads", new SdkFeatureBand(sdkFeatureBand).ToString(), "userlocal");
3839
}
3940
}
4041
}

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

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ public partial class SdkDirectoryWorkloadManifestProvider : IWorkloadManifestPro
1414
public const string WorkloadSetsFolderName = "workloadsets";
1515

1616
private readonly string _sdkRootPath;
17+
private readonly string _sdkOrUserLocalPath;
1718
private readonly SdkFeatureBand _sdkVersionBand;
1819
private readonly string[] _manifestRoots;
1920
private static HashSet<string> _outdatedManifestIds = new(StringComparer.OrdinalIgnoreCase) { "microsoft.net.workload.android", "microsoft.net.workload.blazorwebassembly", "microsoft.net.workload.ios",
@@ -67,6 +68,23 @@ internal SdkDirectoryWorkloadManifestProvider(string sdkRootPath, string sdkVers
6768
_workloadSetVersionFromConstructor = workloadSetVersion;
6869
_globalJsonPathFromConstructor = globalJsonPath;
6970

71+
string? userManifestsRoot = userProfileDir is null ? null : Path.Combine(userProfileDir, "sdk-manifests");
72+
string dotnetManifestRoot = Path.Combine(_sdkRootPath, "sdk-manifests");
73+
if (userManifestsRoot != null && WorkloadFileBasedInstall.IsUserLocal(_sdkRootPath, _sdkVersionBand.ToString()) && Directory.Exists(userManifestsRoot))
74+
{
75+
_sdkOrUserLocalPath = userProfileDir ?? _sdkRootPath;
76+
if (getEnvironmentVariable(EnvironmentVariableNames.WORKLOAD_MANIFEST_IGNORE_DEFAULT_ROOTS) == null)
77+
{
78+
_manifestRoots = new[] { userManifestsRoot, dotnetManifestRoot };
79+
}
80+
}
81+
else if (getEnvironmentVariable(EnvironmentVariableNames.WORKLOAD_MANIFEST_IGNORE_DEFAULT_ROOTS) == null)
82+
{
83+
_manifestRoots = new[] { dotnetManifestRoot };
84+
}
85+
86+
_sdkOrUserLocalPath ??= _sdkRootPath;
87+
7088
var knownManifestIdsFilePath = Path.Combine(_sdkRootPath, "sdk", sdkVersion, "KnownWorkloadManifests.txt");
7189
if (!File.Exists(knownManifestIdsFilePath))
7290
{
@@ -83,20 +101,6 @@ internal SdkDirectoryWorkloadManifestProvider(string sdkRootPath, string sdkVers
83101
}
84102
}
85103

86-
if (getEnvironmentVariable(EnvironmentVariableNames.WORKLOAD_MANIFEST_IGNORE_DEFAULT_ROOTS) == null)
87-
{
88-
string? userManifestsRoot = userProfileDir is null ? null : Path.Combine(userProfileDir, "sdk-manifests");
89-
string dotnetManifestRoot = Path.Combine(_sdkRootPath, "sdk-manifests");
90-
if (userManifestsRoot != null && WorkloadFileBasedInstall.IsUserLocal(_sdkRootPath, _sdkVersionBand.ToString()) && Directory.Exists(userManifestsRoot))
91-
{
92-
_manifestRoots = new[] { userManifestsRoot, dotnetManifestRoot };
93-
}
94-
else
95-
{
96-
_manifestRoots = new[] { dotnetManifestRoot };
97-
}
98-
}
99-
100104
var manifestDirectoryEnvironmentVariable = getEnvironmentVariable(EnvironmentVariableNames.WORKLOAD_MANIFEST_ROOTS);
101105
if (manifestDirectoryEnvironmentVariable != null)
102106
{
@@ -179,7 +183,7 @@ bool TryGetWorkloadSet(string workloadSetVersion, out WorkloadSet? workloadSet)
179183

180184
if (_workloadSet is null)
181185
{
182-
var installStateFilePath = Path.Combine(WorkloadInstallType.GetInstallStateFolder(_sdkVersionBand, _sdkRootPath), "default.json");
186+
var installStateFilePath = Path.Combine(WorkloadInstallType.GetInstallStateFolder(_sdkVersionBand, _sdkOrUserLocalPath), "default.json");
183187
if (File.Exists(installStateFilePath))
184188
{
185189
var installState = InstallStateContents.FromPath(installStateFilePath);

test/dotnet-workload-update.Tests/GivenDotnetWorkloadUpdate.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,17 @@ public void GivenWorkloadUpdateAcrossFeatureBandsItUpdatesPacks(bool userLocal)
161161
var updateParseResult = Parser.Instance.Parse(new string[] { "dotnet", "workload", "update", "--from-previous-sdk" });
162162
var updateCommand = new WorkloadUpdateCommand(updateParseResult, reporter: _reporter, workloadResolverFactory, nugetPackageDownloader: nugetDownloader,
163163
workloadManifestUpdater: manifestUpdater, tempDirPath: testDirectory);
164+
var installStatePath = Path.Combine(WorkloadInstallType.GetInstallStateFolder(new SdkFeatureBand(sdkFeatureVersion), installRoot), "default.json");
165+
var oldInstallState = InstallStateContents.FromPath(installStatePath);
166+
oldInstallState.Manifests = new Dictionary<string, string>()
167+
{
168+
{installingWorkload, $"6.0.102/{sdkFeatureVersion}" }
169+
};
170+
Directory.CreateDirectory(Path.GetDirectoryName(installStatePath));
171+
File.WriteAllText(installStatePath, oldInstallState.ToString());
164172
updateCommand.Execute();
173+
var newInstallState = InstallStateContents.FromPath(installStatePath);
174+
newInstallState.Manifests.Should().BeNull();
165175

166176
foreach (var pack in workloadPacks)
167177
{

0 commit comments

Comments
 (0)