diff --git a/src/Cli/Microsoft.DotNet.Cli.Utils/PathUtility.cs b/src/Cli/Microsoft.DotNet.Cli.Utils/PathUtility.cs
index 1957a49a1739..9bbecf9b7ed1 100644
--- a/src/Cli/Microsoft.DotNet.Cli.Utils/PathUtility.cs
+++ b/src/Cli/Microsoft.DotNet.Cli.Utils/PathUtility.cs
@@ -102,7 +102,7 @@ public static bool TryDeleteDirectory(string directoryPath)
/// and continues to its parent until it fails. Returns whether it succeeded
/// in deleting the file it was intended to delete.
///
- public static bool DeleteFileAndEmptyParents(string path)
+ public static bool DeleteFileAndEmptyParents(string path, int maxDirectoriesToDelete = int.MaxValue)
{
if (!File.Exists(path))
{
@@ -112,9 +112,13 @@ public static bool DeleteFileAndEmptyParents(string path)
File.Delete(path);
var dir = Path.GetDirectoryName(path);
- while (!Directory.EnumerateFileSystemEntries(dir).Any())
+ int directoriesDeleted = 0;
+
+ while (!Directory.EnumerateFileSystemEntries(dir).Any() &&
+ directoriesDeleted < maxDirectoriesToDelete)
{
Directory.Delete(dir);
+ directoriesDeleted++;
dir = Path.GetDirectoryName(dir);
}
diff --git a/src/Cli/dotnet/Installer/Windows/InstallMessageDispatcher.cs b/src/Cli/dotnet/Installer/Windows/InstallMessageDispatcher.cs
index 538bae6d1a46..4a06ca945d13 100644
--- a/src/Cli/dotnet/Installer/Windows/InstallMessageDispatcher.cs
+++ b/src/Cli/dotnet/Installer/Windows/InstallMessageDispatcher.cs
@@ -183,7 +183,7 @@ public InstallResponseMessage SendSaveInstallStateManifestVersions(SdkFeatureBan
/// The SDK feature band of the install state file to write
/// Whether to use workload sets or not
///
- public InstallResponseMessage SendUpdateWorkloadModeRequest(SdkFeatureBand sdkFeatureBand, bool newMode)
+ public InstallResponseMessage SendUpdateWorkloadModeRequest(SdkFeatureBand sdkFeatureBand, bool? newMode)
{
return Send(new InstallRequestMessage
{
diff --git a/src/Cli/dotnet/Installer/Windows/InstallRequestMessage.cs b/src/Cli/dotnet/Installer/Windows/InstallRequestMessage.cs
index 962bdd90dd9f..7a074df68614 100644
--- a/src/Cli/dotnet/Installer/Windows/InstallRequestMessage.cs
+++ b/src/Cli/dotnet/Installer/Windows/InstallRequestMessage.cs
@@ -123,7 +123,7 @@ public string WorkloadId
///
/// The new mode to use: workloadset or loosemanifests
///
- public bool UseWorkloadSets
+ public bool? UseWorkloadSets
{
get; set;
}
diff --git a/src/Cli/dotnet/commands/InstallingWorkloadCommand.cs b/src/Cli/dotnet/commands/InstallingWorkloadCommand.cs
index c266ba56be2f..8a0ae321c37f 100644
--- a/src/Cli/dotnet/commands/InstallingWorkloadCommand.cs
+++ b/src/Cli/dotnet/commands/InstallingWorkloadCommand.cs
@@ -14,6 +14,7 @@
using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.ToolPackage;
using Microsoft.DotNet.Workloads.Workload.Install;
+using Microsoft.DotNet.Workloads.Workload.Update;
using Microsoft.Extensions.EnvironmentAbstractions;
using Microsoft.NET.Sdk.WorkloadManifestReader;
using NuGet.Versioning;
@@ -34,7 +35,8 @@ internal abstract class InstallingWorkloadCommand : WorkloadCommandBase
protected readonly SdkFeatureBand _sdkFeatureBand;
protected readonly ReleaseVersion _targetSdkVersion;
protected readonly string _fromRollbackDefinition;
- protected string _workloadSetVersion;
+ protected string _workloadSetVersionFromCommandLine;
+ protected string _globalJsonPath;
protected string _workloadSetVersionFromGlobalJson;
protected readonly PackageSourceLocation _packageSourceLocation;
protected readonly IWorkloadResolverFactory _workloadResolverFactory;
@@ -44,6 +46,10 @@ internal abstract class InstallingWorkloadCommand : WorkloadCommandBase
protected IInstaller _workloadInstaller;
protected IWorkloadManifestUpdater _workloadManifestUpdater;
+ protected bool UseRollback => !string.IsNullOrWhiteSpace(_fromRollbackDefinition);
+ protected bool SpecifiedWorkloadSetVersionOnCommandLine => !string.IsNullOrWhiteSpace(_workloadSetVersionFromCommandLine);
+ protected bool SpecifiedWorkloadSetVersionInGlobalJson => !string.IsNullOrWhiteSpace(_workloadSetVersionFromGlobalJson);
+
public InstallingWorkloadCommand(
ParseResult parseResult,
IReporter reporter,
@@ -60,6 +66,8 @@ public InstallingWorkloadCommand(
_downloadToCacheOption = parseResult.GetValue(InstallingWorkloadCommandParser.DownloadToCacheOption);
_fromRollbackDefinition = parseResult.GetValue(InstallingWorkloadCommandParser.FromRollbackFileOption);
+ _workloadSetVersionFromCommandLine = parseResult.GetValue(InstallingWorkloadCommandParser.WorkloadSetVersionOption);
+
var configOption = parseResult.GetValue(InstallingWorkloadCommandParser.ConfigOption);
var sourceOption = parseResult.GetValue(InstallingWorkloadCommandParser.SourceOption);
_packageSourceLocation = string.IsNullOrEmpty(configOption) && (sourceOption == null || !sourceOption.Any()) ? null :
@@ -91,6 +99,23 @@ public InstallingWorkloadCommand(
_workloadInstallerFromConstructor = workloadInstaller;
_workloadManifestUpdaterFromConstructor = workloadManifestUpdater;
+
+ _globalJsonPath = SdkDirectoryWorkloadManifestProvider.GetGlobalJsonPath(Environment.CurrentDirectory);
+ _workloadSetVersionFromGlobalJson = SdkDirectoryWorkloadManifestProvider.GlobalJsonReader.GetWorkloadVersionFromGlobalJson(_globalJsonPath);
+
+ if (SpecifiedWorkloadSetVersionInGlobalJson && (SpecifiedWorkloadSetVersionOnCommandLine || UseRollback))
+ {
+ throw new GracefulException(string.Format(Strings.CannotSpecifyVersionOnCommandLineAndInGlobalJson, _globalJsonPath), isUserError: true);
+ }
+
+ if (SpecifiedWorkloadSetVersionOnCommandLine && UseRollback)
+ {
+ throw new GracefulException(string.Format(Update.LocalizableStrings.CannotCombineOptions,
+ InstallingWorkloadCommandParser.FromRollbackFileOption.Name,
+ InstallingWorkloadCommandParser.WorkloadSetVersionOption.Name), isUserError: true);
+ }
+
+ // At this point, at most one of SpecifiedWorkloadSetVersionOnCommandLine, UseRollback, and SpecifiedWorkloadSetVersionInGlobalJson is true
}
protected static Dictionary GetInstallStateContents(IEnumerable manifestVersionUpdates) =>
@@ -98,63 +123,138 @@ protected static Dictionary GetInstallStateContents(IEnumerable<
manifestVersionUpdates.Select(update => new WorkloadManifestInfo(update.ManifestId.ToString(), update.NewVersion.ToString(), /* We don't actually use the directory here */ string.Empty, update.NewFeatureBand))
).ToDictionaryForJson();
- public static bool ShouldUseWorkloadSetMode(SdkFeatureBand sdkFeatureBand, string dotnetDir)
+ InstallStateContents GetCurrentInstallState()
{
- string path = Path.Combine(WorkloadInstallType.GetInstallStateFolder(sdkFeatureBand, dotnetDir), "default.json");
- var installStateContents = File.Exists(path) ? InstallStateContents.FromString(File.ReadAllText(path)) : new InstallStateContents();
- return installStateContents.UseWorkloadSets ?? false;
+ return GetCurrentInstallState(_sdkFeatureBand, _dotnetPath);
}
- protected void ErrorIfGlobalJsonAndCommandLineMismatch(string globaljsonPath)
+ static InstallStateContents GetCurrentInstallState(SdkFeatureBand sdkFeatureBand, string dotnetDir)
{
- if (!string.IsNullOrWhiteSpace(_workloadSetVersionFromGlobalJson) && !string.IsNullOrWhiteSpace(_workloadSetVersion) && !_workloadSetVersion.Equals(_workloadSetVersionFromGlobalJson))
- {
- throw new Exception(string.Format(Strings.CannotSpecifyVersionOnCommandLineAndInGlobalJson, globaljsonPath));
- }
+ string path = Path.Combine(WorkloadInstallType.GetInstallStateFolder(sdkFeatureBand, dotnetDir), "default.json");
+ return InstallStateContents.FromPath(path);
}
- protected bool TryHandleWorkloadUpdateFromVersion(ITransactionContext context, DirectoryPath? offlineCache, out IEnumerable updates)
+ public static bool ShouldUseWorkloadSetMode(SdkFeatureBand sdkFeatureBand, string dotnetDir)
{
- // Ensure workload set mode is set to 'workloadset'
- // Do not skip checking the mode first, as setting it triggers
- // an admin authorization popup for MSI-based installs.
- if (!ShouldUseWorkloadSetMode(_sdkFeatureBand, _dotnetPath))
- {
- _workloadInstaller.UpdateInstallMode(_sdkFeatureBand, true);
- }
-
- _workloadManifestUpdater.DownloadWorkloadSet(_workloadSetVersionFromGlobalJson ?? _workloadSetVersion, offlineCache);
- return TryInstallWorkloadSet(context, out updates, throwOnFailure: true);
+ return GetCurrentInstallState(sdkFeatureBand, dotnetDir).UseWorkloadSets ?? false;
}
- public bool TryInstallWorkloadSet(ITransactionContext context, out IEnumerable updates, bool throwOnFailure = false)
+ protected void UpdateWorkloadManifests(ITransactionContext context, DirectoryPath? offlineCache)
{
- var advertisingPackagePath = Path.Combine(_userProfileDir, "sdk-advertising", _sdkFeatureBand.ToString(), "microsoft.net.workloads");
- if (File.Exists(Path.Combine(advertisingPackagePath, Constants.workloadSetVersionFileName)))
+ var updateToLatestWorkloadSet = ShouldUseWorkloadSetMode(_sdkFeatureBand, _dotnetPath);
+ if (UseRollback && updateToLatestWorkloadSet)
{
- // This file isn't created in tests.
- var version = File.ReadAllText(Path.Combine(advertisingPackagePath, Constants.workloadSetVersionFileName));
- PrintWorkloadSetTransition(version);
+ // Rollback files are only for loose manifests. Update the mode to be loose manifests.
+ Reporter.WriteLine(Update.LocalizableStrings.UpdateFromRollbackSwitchesModeToLooseManifests);
+ _workloadInstaller.UpdateInstallMode(_sdkFeatureBand, false);
+ updateToLatestWorkloadSet = false;
}
- else if (_workloadInstaller is FileBasedInstaller || _workloadInstaller is NetSdkMsiInstallerClient)
+
+ if (SpecifiedWorkloadSetVersionOnCommandLine)
{
- // No workload sets found
- if (throwOnFailure)
+ updateToLatestWorkloadSet = false;
+
+ // If a workload set version is specified, then switch to workload set update mode
+ // Check to make sure the value needs to be changed, as updating triggers a UAC prompt
+ // for MSI-based installs.
+ if (!ShouldUseWorkloadSetMode(_sdkFeatureBand, _dotnetPath))
{
- throw new NuGetPackageNotFoundException(string.Format(Update.LocalizableStrings.WorkloadVersionRequestedNotFound, _workloadSetVersionFromGlobalJson ?? _workloadSetVersion));
+ _workloadInstaller.UpdateInstallMode(_sdkFeatureBand, true);
}
- else
+ }
+
+ string resolvedWorkloadSetVersion = _workloadSetVersionFromGlobalJson ??_workloadSetVersionFromCommandLine;
+ if (string.IsNullOrWhiteSpace(resolvedWorkloadSetVersion) && !UseRollback)
+ {
+ _workloadManifestUpdater.UpdateAdvertisingManifestsAsync(_includePreviews, updateToLatestWorkloadSet, offlineCache).Wait();
+ if (updateToLatestWorkloadSet)
{
- Reporter.WriteLine(Update.LocalizableStrings.NoWorkloadUpdateFound);
+ resolvedWorkloadSetVersion = _workloadManifestUpdater.GetAdvertisedWorkloadSetVersion();
}
- updates = null;
- return false;
}
- var workloadSetPath = _workloadInstaller.InstallWorkloadSet(context, advertisingPackagePath);
- var files = Directory.EnumerateFiles(workloadSetPath, "*.workloadset.json");
- updates = _workloadManifestUpdater.ParseRollbackDefinitionFiles(files);
- return true;
+ if (updateToLatestWorkloadSet && resolvedWorkloadSetVersion == null)
+ {
+ Reporter.WriteLine(Update.LocalizableStrings.NoWorkloadUpdateFound);
+ return;
+ }
+
+ IEnumerable manifestsToUpdate;
+ if (resolvedWorkloadSetVersion != null)
+ {
+ manifestsToUpdate = InstallWorkloadSet(context, resolvedWorkloadSetVersion);
+ }
+ else
+ {
+ manifestsToUpdate = UseRollback ? _workloadManifestUpdater.CalculateManifestRollbacks(_fromRollbackDefinition) :
+ _workloadManifestUpdater.CalculateManifestUpdates().Select(m => m.ManifestUpdate);
+ }
+
+ InstallStateContents oldInstallState = GetCurrentInstallState();
+
+ context.Run(
+ action: () =>
+ {
+ foreach (var manifestUpdate in manifestsToUpdate)
+ {
+ _workloadInstaller.InstallWorkloadManifest(manifestUpdate, context, offlineCache);
+ }
+
+ if (!SpecifiedWorkloadSetVersionInGlobalJson)
+ {
+ if (UseRollback)
+ {
+ _workloadInstaller.SaveInstallStateManifestVersions(_sdkFeatureBand, GetInstallStateContents(manifestsToUpdate));
+ }
+ else if (SpecifiedWorkloadSetVersionOnCommandLine)
+ {
+ _workloadInstaller.AdjustWorkloadSetInInstallState(_sdkFeatureBand, resolvedWorkloadSetVersion);
+ }
+ else if (this is WorkloadUpdateCommand)
+ {
+ // For workload updates, if you don't specify a rollback file, or a workload version then we should update to a new version of the manifests or workload set, and
+ // should remove the install state that pins to the other version
+ _workloadInstaller.RemoveManifestsFromInstallState(_sdkFeatureBand);
+ _workloadInstaller.AdjustWorkloadSetInInstallState(_sdkFeatureBand, null);
+ }
+ }
+
+ _workloadResolver.RefreshWorkloadManifests();
+ },
+ rollback: () =>
+ {
+ // Reset install state
+ var currentInstallState = GetCurrentInstallState();
+ if (currentInstallState.UseWorkloadSets != oldInstallState.UseWorkloadSets)
+ {
+ _workloadInstaller.UpdateInstallMode(_sdkFeatureBand, oldInstallState.UseWorkloadSets);
+ }
+
+ if ((currentInstallState.Manifests == null && oldInstallState.Manifests != null) ||
+ (currentInstallState.Manifests != null && oldInstallState.Manifests == null) ||
+ (currentInstallState.Manifests != null && oldInstallState.Manifests != null &&
+ (currentInstallState.Manifests.Count != oldInstallState.Manifests.Count ||
+ !currentInstallState.Manifests.All(m => oldInstallState.Manifests.TryGetValue(m.Key, out var val) && val.Equals(m.Value)))))
+ {
+ _workloadInstaller.SaveInstallStateManifestVersions(_sdkFeatureBand, oldInstallState.Manifests);
+ }
+
+ if (currentInstallState.WorkloadVersion != oldInstallState.WorkloadVersion)
+ {
+ _workloadInstaller.AdjustWorkloadSetInInstallState(_sdkFeatureBand, oldInstallState.WorkloadVersion);
+ }
+
+ // We will refresh the workload manifests to make sure that the resolver has the updated state after the rollback
+ _workloadResolver.RefreshWorkloadManifests();
+ });
+ }
+
+ private IEnumerable InstallWorkloadSet(ITransactionContext context, string workloadSetVersion)
+ {
+ PrintWorkloadSetTransition(workloadSetVersion);
+ var workloadSet = _workloadInstaller.InstallWorkloadSet(context, workloadSetVersion);
+
+ return _workloadManifestUpdater.CalculateManifestUpdatesForWorkloadSet(workloadSet);
}
private void PrintWorkloadSetTransition(string newVersion)
@@ -258,6 +358,17 @@ protected IEnumerable GetInstalledWorkloads(bool fromPreviousSdk)
return workloads ?? Enumerable.Empty();
}
}
+
+ protected IEnumerable WriteSDKInstallRecordsForVSWorkloads(IEnumerable workloadsWithExistingInstallRecords)
+ {
+#if !DOT_NET_BUILD_FROM_SOURCE
+ if (OperatingSystem.IsWindows())
+ {
+ return VisualStudioWorkloads.WriteSDKInstallRecordsForVSWorkloads(_workloadInstaller, _workloadResolver, workloadsWithExistingInstallRecords, Reporter);
+ }
+#endif
+ return workloadsWithExistingInstallRecords;
+ }
}
internal static class InstallingWorkloadCommandParser
diff --git a/src/Cli/dotnet/commands/dotnet-workload/install/FileBasedInstaller.cs b/src/Cli/dotnet/commands/dotnet-workload/install/FileBasedInstaller.cs
index 800078f10e37..caeb77562da4 100644
--- a/src/Cli/dotnet/commands/dotnet-workload/install/FileBasedInstaller.cs
+++ b/src/Cli/dotnet/commands/dotnet-workload/install/FileBasedInstaller.cs
@@ -23,6 +23,7 @@ internal class FileBasedInstaller : IInstaller
private readonly string _workloadMetadataDir;
private const string InstalledPacksDir = "InstalledPacks";
private const string InstalledManifestsDir = "InstalledManifests";
+ private const string InstalledWorkloadSetsDir = "InstalledWorkloadSets";
protected readonly string _dotnetDir;
protected readonly string _userProfileDir;
protected readonly DirectoryPath _tempPackagesDir;
@@ -85,29 +86,33 @@ IEnumerable GetPacksInWorkloads(IEnumerable workloadIds)
return packs;
}
- public string InstallWorkloadSet(ITransactionContext context, string advertisingPackagePath)
+ public WorkloadSet InstallWorkloadSet(ITransactionContext context, string workloadSetVersion, DirectoryPath? offlineCache = null)
{
- var workloadVersion = File.ReadAllText(Path.Combine(advertisingPackagePath, Constants.workloadSetVersionFileName));
- var workloadSetPath = Path.Combine(_dotnetDir, "sdk-manifests", _sdkFeatureBand.ToString(), "workloadsets", workloadVersion);
- context.Run(
- action: () =>
- {
- Directory.CreateDirectory(workloadSetPath);
+ SdkFeatureBand workloadSetFeatureBand;
+ string workloadSetPackageVersion = WorkloadSet.WorkloadSetVersionToWorkloadSetPackageVersion(workloadSetVersion, out workloadSetFeatureBand);
+ var workloadSetPackageId = GetManifestPackageId(new ManifestId("Microsoft.NET.Workloads"), workloadSetFeatureBand);
- foreach (var file in Directory.EnumerateFiles(advertisingPackagePath))
+ var workloadSetPath = Path.Combine(_dotnetDir, "sdk-manifests", _sdkFeatureBand.ToString(), "workloadsets", workloadSetVersion);
+
+ try
+ {
+ InstallPackage(workloadSetPackageId, workloadSetPackageVersion, workloadSetPath, context, offlineCache);
+ context.Run(
+ action: () =>
{
- File.Copy(file, Path.Combine(workloadSetPath, Path.GetFileName(file)), overwrite: true);
- }
- },
- rollback: () =>
- {
- foreach (var file in Directory.EnumerateFiles(workloadSetPath))
+ WriteWorkloadSetInstallationRecord(workloadSetVersion, workloadSetFeatureBand, _sdkFeatureBand);
+ },
+ rollback: () =>
{
- PathUtility.DeleteFileAndEmptyParents(file);
- }
- });
+ RemoveWorkloadSetInstallationRecord(workloadSetVersion, workloadSetFeatureBand, _sdkFeatureBand);
+ });
+ }
+ catch (Exception ex)
+ {
+ throw new Exception(string.Format(LocalizableStrings.FailedToInstallWorkloadSet, workloadSetVersion, ex.Message), ex);
+ }
- return workloadSetPath;
+ return WorkloadSet.FromWorkloadSetFolder(workloadSetPath, workloadSetVersion, _sdkFeatureBand);
}
public void InstallWorkloads(IEnumerable workloadIds, SdkFeatureBand sdkFeatureBand, ITransactionContext transactionContext, DirectoryPath? offlineCache = null)
@@ -226,86 +231,101 @@ string GetManifestInstallDirForFeatureBand(string sdkFeatureBand)
return manifestInstallDir;
}
- public void InstallWorkloadManifest(ManifestVersionUpdate manifestUpdate, ITransactionContext transactionContext, DirectoryPath? offlineCache = null, bool isRollback = false)
+ public void InstallWorkloadManifest(ManifestVersionUpdate manifestUpdate, ITransactionContext transactionContext, DirectoryPath? offlineCache = null)
{
- string packagePath = null;
- string tempBackupDir = null;
-
var newManifestPath = Path.Combine(GetManifestInstallDirForFeatureBand(manifestUpdate.NewFeatureBand), manifestUpdate.ManifestId.ToString(), manifestUpdate.NewVersion.ToString());
_reporter.WriteLine(string.Format(LocalizableStrings.InstallingWorkloadManifest, manifestUpdate.ManifestId, manifestUpdate.NewVersion));
try
{
+ var newManifestPackageId = GetManifestPackageId(manifestUpdate.ManifestId, new SdkFeatureBand(manifestUpdate.NewFeatureBand));
+
+ InstallPackage(newManifestPackageId, manifestUpdate.NewVersion.ToString(), newManifestPath, transactionContext, offlineCache);
+
transactionContext.Run(
action: () =>
{
- var newManifestPackageId = GetManifestPackageId(manifestUpdate.ManifestId, new SdkFeatureBand(manifestUpdate.NewFeatureBand));
- if (offlineCache == null || !offlineCache.HasValue)
- {
- packagePath = _nugetPackageDownloader.DownloadPackageAsync(newManifestPackageId,
- new NuGetVersion(manifestUpdate.NewVersion.ToString()), _packageSourceLocation).GetAwaiter().GetResult();
- }
- else
- {
- packagePath = Path.Combine(offlineCache.Value.Value, $"{newManifestPackageId}.{manifestUpdate.NewVersion}.nupkg");
- if (!File.Exists(packagePath))
- {
- throw new Exception(string.Format(LocalizableStrings.CacheMissingPackage, newManifestPackageId, manifestUpdate.NewVersion, offlineCache));
- }
- }
-
- // If target directory already exists, back it up in case we roll back
- if (Directory.Exists(newManifestPath) && Directory.GetFileSystemEntries(newManifestPath).Any())
- {
- tempBackupDir = Path.Combine(_tempPackagesDir.Value, $"{manifestUpdate.ManifestId}-{manifestUpdate.ExistingVersion}-backup");
- if (Directory.Exists(tempBackupDir))
- {
- Directory.Delete(tempBackupDir, true);
- }
- FileAccessRetrier.RetryOnMoveAccessFailure(() => DirectoryPath.MoveDirectory(newManifestPath, tempBackupDir));
- }
-
- ExtractManifestAsync(packagePath, newManifestPath).GetAwaiter().GetResult();
-
WriteManifestInstallationRecord(manifestUpdate.ManifestId, manifestUpdate.NewVersion, new SdkFeatureBand(manifestUpdate.NewFeatureBand), _sdkFeatureBand);
},
rollback: () =>
{
- if (!string.IsNullOrEmpty(tempBackupDir) && Directory.Exists(tempBackupDir))
- {
- FileAccessRetrier.RetryOnMoveAccessFailure(() => DirectoryPath.MoveDirectory(tempBackupDir, newManifestPath));
- }
- },
- cleanup: () =>
+ RemoveManifestInstallationRecord(manifestUpdate.ManifestId, manifestUpdate.NewVersion, new SdkFeatureBand(manifestUpdate.NewFeatureBand), _sdkFeatureBand);
+ });
+ }
+ catch (Exception e)
+ {
+ throw new Exception(string.Format(LocalizableStrings.FailedToInstallWorkloadManifest, manifestUpdate.ManifestId, manifestUpdate.NewVersion, e.Message), e);
+ }
+ }
+
+ void InstallPackage(PackageId packageId, string packageVersion, string targetFolder, ITransactionContext transactionContext, DirectoryPath? offlineCache)
+ {
+ string packagePath = null;
+ string tempBackupDir = null;
+
+ transactionContext.Run(
+ action: () =>
+ {
+ if (offlineCache == null || !offlineCache.HasValue)
{
- // Delete leftover dirs and files
- if (!string.IsNullOrEmpty(packagePath) && File.Exists(packagePath) && (offlineCache == null || !offlineCache.HasValue))
+ packagePath = _nugetPackageDownloader.DownloadPackageAsync(packageId,
+ new NuGetVersion(packageVersion), _packageSourceLocation).GetAwaiter().GetResult();
+ }
+ else
+ {
+ packagePath = Path.Combine(offlineCache.Value.Value, $"{packageId}.{packageVersion}.nupkg");
+ if (!File.Exists(packagePath))
{
- File.Delete(packagePath);
+ throw new Exception(string.Format(LocalizableStrings.CacheMissingPackage, packageId, packageVersion, offlineCache));
}
+ }
- var versionDir = Path.GetDirectoryName(packagePath);
- if (Directory.Exists(versionDir) && !Directory.GetFileSystemEntries(versionDir).Any())
+ // If target directory already exists, back it up in case we roll back
+ if (Directory.Exists(targetFolder) && Directory.GetFileSystemEntries(targetFolder).Any())
+ {
+ tempBackupDir = Path.Combine(_tempPackagesDir.Value, $"{packageId} - {packageVersion}-backup");
+ if (Directory.Exists(tempBackupDir))
{
- Directory.Delete(versionDir);
- var idDir = Path.GetDirectoryName(versionDir);
- if (Directory.Exists(idDir) && !Directory.GetFileSystemEntries(idDir).Any())
- {
- Directory.Delete(idDir);
- }
+ Directory.Delete(tempBackupDir, true);
}
+ FileAccessRetrier.RetryOnMoveAccessFailure(() => DirectoryPath.MoveDirectory(targetFolder, tempBackupDir));
+ }
+
+ ExtractManifestAsync(packagePath, targetFolder).GetAwaiter().GetResult();
+
+ },
+ rollback: () =>
+ {
+ if (!string.IsNullOrEmpty(tempBackupDir) && Directory.Exists(tempBackupDir))
+ {
+ FileAccessRetrier.RetryOnMoveAccessFailure(() => DirectoryPath.MoveDirectory(tempBackupDir, targetFolder));
+ }
+ },
+ cleanup: () =>
+ {
+ // Delete leftover dirs and files
+ if (!string.IsNullOrEmpty(packagePath) && File.Exists(packagePath) && (offlineCache == null || !offlineCache.HasValue))
+ {
+ File.Delete(packagePath);
+ }
- if (!string.IsNullOrEmpty(tempBackupDir) && Directory.Exists(tempBackupDir))
+ var versionDir = Path.GetDirectoryName(packagePath);
+ if (Directory.Exists(versionDir) && !Directory.GetFileSystemEntries(versionDir).Any())
+ {
+ Directory.Delete(versionDir);
+ var idDir = Path.GetDirectoryName(versionDir);
+ if (Directory.Exists(idDir) && !Directory.GetFileSystemEntries(idDir).Any())
{
- Directory.Delete(tempBackupDir, true);
+ Directory.Delete(idDir);
}
- });
- }
- catch (Exception e)
- {
- throw new Exception(string.Format(LocalizableStrings.FailedToInstallWorkloadManifest, manifestUpdate.ManifestId, manifestUpdate.NewVersion, e.Message), e);
- }
+ }
+
+ if (!string.IsNullOrEmpty(tempBackupDir) && Directory.Exists(tempBackupDir))
+ {
+ Directory.Delete(tempBackupDir, true);
+ }
+ });
}
public IEnumerable GetDownloads(IEnumerable workloadIds, SdkFeatureBand sdkFeatureBand, bool includeInstalledItems)
@@ -376,37 +396,17 @@ public void GarbageCollect(Func getResolverForWorkloa
}
}
- string installationRecordPath = null;
foreach (var featureBandToRemove in featureBandsToRemove)
{
- installationRecordPath = GetManifestInstallRecordPath(manifestId, manifestVersion, manifestFeatureBand, featureBandToRemove);
- File.Delete(installationRecordPath);
+ RemoveManifestInstallationRecord(manifestId, manifestVersion, manifestFeatureBand, featureBandToRemove);
}
- if (installationRecordPath != null)
+ if (featureBandsToRemove.Count == manifestInstallRecords[(manifestId, manifestVersion, manifestFeatureBand)].Count)
{
- var installationRecordDirectory = Path.GetDirectoryName(installationRecordPath);
- if (!Directory.GetFileSystemEntries(installationRecordDirectory).Any())
- {
- // There are no installation records for the workload manifest anymore, so we can delete the manifest
- _reporter.WriteLine(string.Format(LocalizableStrings.DeletingWorkloadManifest, manifestId, $"{manifestVersion}/{manifestFeatureBand}"));
- var manifestPath = Path.Combine(GetManifestInstallDirForFeatureBand(manifestFeatureBand.ToString()), manifestId.ToString(), manifestVersion.ToString());
- Directory.Delete(manifestPath, true);
-
- // Delete empty manifest installation record directory, and walk up tree deleting empty directories to clean up
- Directory.Delete(installationRecordDirectory);
-
- var manifestVersionDirectory = Path.GetDirectoryName(installationRecordDirectory);
- if (!Directory.GetFileSystemEntries(manifestVersionDirectory).Any())
- {
- Directory.Delete(manifestVersionDirectory);
- var manifestIdDirectory = Path.GetDirectoryName(manifestVersionDirectory);
- if (!Directory.GetFileSystemEntries(manifestIdDirectory).Any())
- {
- Directory.Delete(manifestIdDirectory);
- }
- }
- }
+ // All installation records for the manifest were removed, so we can delete the manifest
+ _reporter.WriteLine(string.Format(LocalizableStrings.DeletingWorkloadManifest, manifestId, $"{manifestVersion}/{manifestFeatureBand}"));
+ var manifestPath = Path.Combine(GetManifestInstallDirForFeatureBand(manifestFeatureBand.ToString()), manifestId.ToString(), manifestVersion.ToString());
+ Directory.Delete(manifestPath, true);
}
}
@@ -507,14 +507,16 @@ public void SaveInstallStateManifestVersions(SdkFeatureBand sdkFeatureBand, Dict
File.WriteAllText(path, installStateContents.ToString());
}
- public void UpdateInstallMode(SdkFeatureBand sdkFeatureBand, bool newMode)
+ public void UpdateInstallMode(SdkFeatureBand sdkFeatureBand, bool? newMode)
{
string path = Path.Combine(WorkloadInstallType.GetInstallStateFolder(sdkFeatureBand, _dotnetDir), "default.json");
Directory.CreateDirectory(Path.GetDirectoryName(path));
var installStateContents = InstallStateContents.FromPath(path);
installStateContents.UseWorkloadSets = newMode;
File.WriteAllText(path, installStateContents.ToString());
- _reporter.WriteLine(string.Format(LocalizableStrings.UpdatedWorkloadMode, newMode ? WorkloadConfigCommandParser.UpdateMode_WorkloadSet : WorkloadConfigCommandParser.UpdateMode_Manifests));
+
+ var newModeString = newMode == null ? "" : (newMode.Value ? WorkloadConfigCommandParser.UpdateMode_WorkloadSet : WorkloadConfigCommandParser.UpdateMode_Manifests);
+ _reporter.WriteLine(string.Format(LocalizableStrings.UpdatedWorkloadMode, newModeString));
}
///
@@ -616,8 +618,25 @@ private void DeletePack(PackInfo packInfo)
}
- // Workload manifests have a feature band which is essentially part of their version, and may be installed by a later feature band of the SDK. So there are two potentially different
- // Feature bands as part of the installation record
+ // Workload sets and workload manifests have a feature band which is essentially part of their version, and may be installed by a later feature band of the SDK.
+ // So there are two potentially different feature bands as part of the installation record
+ string GetWorkloadSetInstallRecordPath(string workloadSetVersion, SdkFeatureBand workloadSetFeatureBand, SdkFeatureBand referencingFeatureBand) =>
+ Path.Combine(_workloadMetadataDir, InstalledWorkloadSetsDir, "v1", workloadSetVersion, workloadSetFeatureBand.ToString(), referencingFeatureBand.ToString());
+
+ void WriteWorkloadSetInstallationRecord(string workloadSetVersion, SdkFeatureBand workloadSetFeatureBand, SdkFeatureBand referencingFeatureBand)
+ {
+ var path = GetWorkloadSetInstallRecordPath(workloadSetVersion, workloadSetFeatureBand, referencingFeatureBand);
+ Directory.CreateDirectory(Path.GetDirectoryName(path));
+
+ using var _ = File.Create(path);
+ }
+
+ void RemoveWorkloadSetInstallationRecord(string workloadSetVersion, SdkFeatureBand workloadSetFeatureBand, SdkFeatureBand referencingFeatureBand)
+ {
+ var path = GetWorkloadSetInstallRecordPath(workloadSetVersion, workloadSetFeatureBand, referencingFeatureBand);
+ PathUtility.DeleteFileAndEmptyParents(path, maxDirectoriesToDelete: 2);
+ }
+
private string GetManifestInstallRecordPath(ManifestId manifestId, ManifestVersion manifestVersion, SdkFeatureBand featureBand, SdkFeatureBand referencingFeatureBand) =>
Path.Combine(_workloadMetadataDir, InstalledManifestsDir, "v1", manifestId.ToString(), manifestVersion.ToString(), featureBand.ToString(), referencingFeatureBand.ToString());
@@ -629,6 +648,12 @@ void WriteManifestInstallationRecord(ManifestId manifestId, ManifestVersion mani
using var _ = File.Create(path);
}
+ void RemoveManifestInstallationRecord(ManifestId manifestId, ManifestVersion manifestVersion, SdkFeatureBand featureBand, SdkFeatureBand referencingFeatureBand)
+ {
+ var installationRecordPath = GetManifestInstallRecordPath(manifestId, manifestVersion, featureBand, referencingFeatureBand);
+ PathUtility.DeleteFileAndEmptyParents(installationRecordPath, maxDirectoriesToDelete: 3);
+ }
+
private Dictionary<(ManifestId manifestId, ManifestVersion manifestVersion, SdkFeatureBand manifestFeatureBand), List> GetAllManifestInstallRecords()
{
Dictionary<(ManifestId manifestId, ManifestVersion manifestVersion, SdkFeatureBand manifestFeatureBand), List> records = new();
diff --git a/src/Cli/dotnet/commands/dotnet-workload/install/IInstaller.cs b/src/Cli/dotnet/commands/dotnet-workload/install/IInstaller.cs
index 275d5ecbcdce..d6d13a21d0fb 100644
--- a/src/Cli/dotnet/commands/dotnet-workload/install/IInstaller.cs
+++ b/src/Cli/dotnet/commands/dotnet-workload/install/IInstaller.cs
@@ -13,15 +13,15 @@ internal interface IInstaller : IWorkloadManifestInstaller
{
int ExitCode { get; }
- string InstallWorkloadSet(ITransactionContext context, string advertisingPackagePath);
-
void InstallWorkloads(IEnumerable workloadIds, SdkFeatureBand sdkFeatureBand, ITransactionContext transactionContext, DirectoryPath? offlineCache = null);
void RepairWorkloads(IEnumerable workloadIds, SdkFeatureBand sdkFeatureBand, DirectoryPath? offlineCache = null);
void GarbageCollect(Func getResolverForWorkloadSet, DirectoryPath? offlineCache = null, bool cleanAllPacks = false);
- void InstallWorkloadManifest(ManifestVersionUpdate manifestUpdate, ITransactionContext transactionContext, DirectoryPath? offlineCache = null, bool isRollback = false);
+ WorkloadSet InstallWorkloadSet(ITransactionContext context, string workloadSetVersion, DirectoryPath? offlineCache = null);
+
+ void InstallWorkloadManifest(ManifestVersionUpdate manifestUpdate, ITransactionContext transactionContext, DirectoryPath? offlineCache = null);
IWorkloadInstallationRecordRepository GetWorkloadInstallationRecordRepository();
@@ -51,7 +51,7 @@ internal interface IInstaller : IWorkloadManifestInstaller
/// The JSON contents describing the install state.
void SaveInstallStateManifestVersions(SdkFeatureBand sdkFeatureBand, Dictionary manifestContents);
- void UpdateInstallMode(SdkFeatureBand sdkFeatureBand, bool newMode);
+ void UpdateInstallMode(SdkFeatureBand sdkFeatureBand, bool? newMode);
}
// Interface to pass to workload manifest updater
diff --git a/src/Cli/dotnet/commands/dotnet-workload/install/IWorkloadManifestUpdater.cs b/src/Cli/dotnet/commands/dotnet-workload/install/IWorkloadManifestUpdater.cs
index 49af91545c87..e5b63a936b16 100644
--- a/src/Cli/dotnet/commands/dotnet-workload/install/IWorkloadManifestUpdater.cs
+++ b/src/Cli/dotnet/commands/dotnet-workload/install/IWorkloadManifestUpdater.cs
@@ -14,16 +14,15 @@ internal interface IWorkloadManifestUpdater
IEnumerable CalculateManifestUpdates();
+ string GetAdvertisedWorkloadSetVersion();
IEnumerable CalculateManifestRollbacks(string rollbackDefinitionFilePath);
- IEnumerable ParseRollbackDefinitionFiles(IEnumerable files);
+ IEnumerable CalculateManifestUpdatesForWorkloadSet(WorkloadSet workloadSet);
Task> GetManifestPackageDownloadsAsync(bool includePreviews, SdkFeatureBand providedSdkFeatureBand, SdkFeatureBand installedSdkFeatureBand);
IEnumerable GetUpdatableWorkloadsToAdvertise(IEnumerable installedWorkloads);
void DeleteUpdatableWorkloadsFile();
-
- void DownloadWorkloadSet(string version, DirectoryPath? offlineCache);
}
internal record ManifestUpdateWithWorkloads(ManifestVersionUpdate ManifestUpdate, WorkloadCollection Workloads);
diff --git a/src/Cli/dotnet/commands/dotnet-workload/install/LocalizableStrings.resx b/src/Cli/dotnet/commands/dotnet-workload/install/LocalizableStrings.resx
index a0d9a26d1129..7e6b6dd5018d 100644
--- a/src/Cli/dotnet/commands/dotnet-workload/install/LocalizableStrings.resx
+++ b/src/Cli/dotnet/commands/dotnet-workload/install/LocalizableStrings.resx
@@ -237,9 +237,6 @@
Advertising manifest not updated. Manifest package for {0} doesn't exist.
-
- No manifest with ID {0} exists.
-
Failed to install manifest {0} version {1}: {2}.
@@ -325,11 +322,18 @@
Cannot use the {0} and {1} options together. If installing from a rollback file, remove {0}. Otherwise, remove {1}
+
+ Cannot use the {0} and {1} options together. Remove one of the options.
+
+
+ Cannot use the {0} option when workload version is specified in global.json. Remove the {0} option, or remove the 'workloadVersion' element from {1}.
+ "workloadVersion" and "global.json" are literal values and should not be translated.
+
Skip signature verification of workload packages and installers.
- Checking for updated workload manifests.
+ Checking for updated workload version.Error parsing version '{1}' for workload manifest ID '{0}'
@@ -355,4 +359,7 @@
Successfully updated workload install mode to use {0}.
+
+ Failed to install workload version {0}: {1}
+
diff --git a/src/Cli/dotnet/commands/dotnet-workload/install/MsiInstallerBase.cs b/src/Cli/dotnet/commands/dotnet-workload/install/MsiInstallerBase.cs
index 8f3b0ca4d4e2..cec0aec9e08b 100644
--- a/src/Cli/dotnet/commands/dotnet-workload/install/MsiInstallerBase.cs
+++ b/src/Cli/dotnet/commands/dotnet-workload/install/MsiInstallerBase.cs
@@ -198,7 +198,7 @@ protected uint RepairMsi(string productCode, string logFile)
/// Full path of the log file
/// Error code indicating the result of the operation
///
- protected void UpdateInstallMode(SdkFeatureBand sdkFeatureBand, bool newMode)
+ protected void UpdateInstallMode(SdkFeatureBand sdkFeatureBand, bool? newMode)
{
string path = Path.Combine(WorkloadInstallType.GetInstallStateFolder(sdkFeatureBand, DotNetHome), "default.json");
var installStateContents = InstallStateContents.FromPath(path);
diff --git a/src/Cli/dotnet/commands/dotnet-workload/install/NetSdkMsiInstallerClient.cs b/src/Cli/dotnet/commands/dotnet-workload/install/NetSdkMsiInstallerClient.cs
index 12fb761e7c29..769ac4c1ad97 100644
--- a/src/Cli/dotnet/commands/dotnet-workload/install/NetSdkMsiInstallerClient.cs
+++ b/src/Cli/dotnet/commands/dotnet-workload/install/NetSdkMsiInstallerClient.cs
@@ -258,62 +258,71 @@ public void GarbageCollect(Func getResolverForWorkloa
}
}
- // advertisingPackagePath is the path to the workload set MSI nupkg in the advertising package.
- public string InstallWorkloadSet(ITransactionContext context, string advertisingPackagePath)
+ public WorkloadSet InstallWorkloadSet(ITransactionContext context, string workloadSetVersion, DirectoryPath? offlineCache)
{
- var pathToReturn = string.Empty;
+ ReportPendingReboot();
+
+ var (msi, msiPackageId, installationFolder) = GetWorkloadSetPayload(workloadSetVersion, offlineCache);
+
context.Run(
action: () =>
{
- pathToReturn = ModifyWorkloadSet(advertisingPackagePath, InstallAction.Install);
+ DetectState state = DetectPackage(msi.ProductCode, out Version installedVersion);
+ InstallAction plannedAction = PlanPackage(msi, state, InstallAction.Install, installedVersion);
+
+ if (plannedAction == InstallAction.Install)
+ {
+ Elevate();
+
+ ExecutePackage(msi, plannedAction, msiPackageId);
+
+ // Update the reference count against the MSI.
+ UpdateDependent(InstallRequestType.AddDependent, msi.Manifest.ProviderKeyName, _dependent);
+ }
},
rollback: () =>
{
- ModifyWorkloadSet(advertisingPackagePath, InstallAction.Uninstall);
+ DetectState state = DetectPackage(msi.ProductCode, out Version installedVersion);
+ InstallAction plannedAction = PlanPackage(msi, state, InstallAction.Uninstall, installedVersion);
+
+ if (plannedAction == InstallAction.Uninstall)
+ {
+ Elevate();
+
+ // Update the reference count against the MSI.
+ UpdateDependent(InstallRequestType.RemoveDependent, msi.Manifest.ProviderKeyName, _dependent);
+
+ ExecutePackage(msi, plannedAction, msiPackageId);
+ }
});
- return pathToReturn;
+ return WorkloadSet.FromWorkloadSetFolder(installationFolder, workloadSetVersion, _sdkFeatureBand);
}
- private string ModifyWorkloadSet(string advertisingPackagePath, InstallAction requestedAction)
+ (MsiPayload msi, string msiPackageId, string installationFolder) GetWorkloadSetPayload(string workloadSetVersion, DirectoryPath? offlineCache)
{
- ReportPendingReboot();
-
- // Resolve the package ID for the manifest payload package
- var featureBand = Path.GetFileName(Path.GetDirectoryName(advertisingPackagePath));
- var workloadSetVersion = File.ReadAllText(Path.Combine(advertisingPackagePath, Constants.workloadSetVersionFileName));
- string msiPackageId = GetManifestPackageId(new ManifestId("Microsoft.NET.Workloads"), new SdkFeatureBand(featureBand)).ToString();
- string msiPackageVersion = WorkloadManifestUpdater.WorkloadSetVersionToWorkloadSetPackageVersion(workloadSetVersion);
+ SdkFeatureBand workloadSetFeatureBand;
+ string msiPackageVersion = WorkloadSet.WorkloadSetVersionToWorkloadSetPackageVersion(workloadSetVersion, out workloadSetFeatureBand);
+ string msiPackageId = GetManifestPackageId(new ManifestId("Microsoft.NET.Workloads"), workloadSetFeatureBand).ToString();
Log?.LogMessage($"Resolving Microsoft.NET.Workloads ({workloadSetVersion}) to {msiPackageId} ({msiPackageVersion}).");
// Retrieve the payload from the MSI package cache.
- MsiPayload msi = GetCachedMsiPayload(msiPackageId, msiPackageVersion, null);
- VerifyPackage(msi);
- DetectState state = DetectPackage(msi.ProductCode, out Version installedVersion);
-
- InstallAction plannedAction = PlanPackage(msi, state, requestedAction, installedVersion);
-
- if (plannedAction == InstallAction.Uninstall)
+ MsiPayload msi;
+ try
{
- Elevate();
-
- // Update the reference count against the MSI.
- UpdateDependent(InstallRequestType.RemoveDependent, msi.Manifest.ProviderKeyName, _dependent);
-
- ExecutePackage(msi, plannedAction, msiPackageId);
+ msi = GetCachedMsiPayload(msiPackageId, msiPackageVersion, offlineCache);
}
- else if (plannedAction != InstallAction.None)
+ // Unwrap AggregateException caused by switch from async to sync
+ catch (Exception ex) when (ex is NuGetPackageNotFoundException || ex.InnerException is NuGetPackageNotFoundException)
{
- Elevate();
-
- ExecutePackage(msi, plannedAction, msiPackageId);
-
- // Update the reference count against the MSI.
- UpdateDependent(InstallRequestType.AddDependent, msi.Manifest.ProviderKeyName, _dependent);
+ throw new GracefulException(string.Format(Update.LocalizableStrings.WorkloadVersionRequestedNotFound, workloadSetVersion), ex is NuGetPackageNotFoundException ? ex : ex.InnerException);
}
+ VerifyPackage(msi);
+
+ string installationFolder = Path.Combine(DotNetHome, "sdk-manifests", workloadSetFeatureBand.ToString(), "workloadsets", workloadSetVersion);
- return Path.Combine(DotNetHome, "sdk-manifests", _sdkFeatureBand.ToString(), "workloadsets", workloadSetVersion);
+ return (msi, msiPackageId, installationFolder);
}
///
@@ -455,18 +464,18 @@ private void DeleteAllWorkloadInstallationRecords()
public IWorkloadInstallationRecordRepository GetWorkloadInstallationRecordRepository() => RecordRepository;
- public void InstallWorkloadManifest(ManifestVersionUpdate manifestUpdate, ITransactionContext transactionContext, DirectoryPath? offlineCache = null, bool isRollback = false)
+ public void InstallWorkloadManifest(ManifestVersionUpdate manifestUpdate, ITransactionContext transactionContext, DirectoryPath? offlineCache = null)
{
try
{
transactionContext.Run(
action: () =>
{
- InstallWorkloadManifestImplementation(manifestUpdate, offlineCache, isRollback);
+ InstallWorkloadManifestImplementation(manifestUpdate, offlineCache);
},
rollback: () =>
{
- InstallWorkloadManifestImplementation(manifestUpdate, offlineCache: null, isRollback: true, action: InstallAction.Uninstall);
+ InstallWorkloadManifestImplementation(manifestUpdate, offlineCache: null, action: InstallAction.Uninstall);
});
}
catch (Exception e)
@@ -476,14 +485,14 @@ public void InstallWorkloadManifest(ManifestVersionUpdate manifestUpdate, ITrans
}
}
- void InstallWorkloadManifestImplementation(ManifestVersionUpdate manifestUpdate, DirectoryPath? offlineCache = null, bool isRollback = false, InstallAction action = InstallAction.Install)
+ void InstallWorkloadManifestImplementation(ManifestVersionUpdate manifestUpdate, DirectoryPath? offlineCache = null, InstallAction action = InstallAction.Install)
{
ReportPendingReboot();
// Rolling back a manifest update after a successful install is essentially a downgrade, which is blocked so we have to
// treat it as a special case and is different from the install failing and rolling that back, though depending where the install
// failed, it may have removed the old product already.
- Log?.LogMessage($"Installing manifest: Id: {manifestUpdate.ManifestId}, version: {manifestUpdate.NewVersion}, feature band: {manifestUpdate.NewFeatureBand}, rollback: {isRollback}.");
+ Log?.LogMessage($"Installing manifest: Id: {manifestUpdate.ManifestId}, version: {manifestUpdate.NewVersion}, feature band: {manifestUpdate.NewFeatureBand}.");
// Resolve the package ID for the manifest payload package
string msiPackageId = GetManifestPackageId(manifestUpdate.ManifestId, new SdkFeatureBand(manifestUpdate.NewFeatureBand)).ToString();
@@ -1085,10 +1094,11 @@ private void OnProcessExit(object sender, EventArgs e)
}
}
- void IInstaller.UpdateInstallMode(SdkFeatureBand sdkFeatureBand, bool newMode)
+ void IInstaller.UpdateInstallMode(SdkFeatureBand sdkFeatureBand, bool? newMode)
{
UpdateInstallMode(sdkFeatureBand, newMode);
- Reporter.WriteLine(string.Format(LocalizableStrings.UpdatedWorkloadMode, newMode ? WorkloadConfigCommandParser.UpdateMode_WorkloadSet : WorkloadConfigCommandParser.UpdateMode_Manifests));
+ string newModeString = newMode == null ? "" : newMode.Value ? WorkloadConfigCommandParser.UpdateMode_WorkloadSet : WorkloadConfigCommandParser.UpdateMode_Manifests;
+ Reporter.WriteLine(string.Format(LocalizableStrings.UpdatedWorkloadMode, newModeString));
}
}
}
diff --git a/src/Cli/dotnet/commands/dotnet-workload/install/NetSdkMsiInstallerServer.cs b/src/Cli/dotnet/commands/dotnet-workload/install/NetSdkMsiInstallerServer.cs
index b2522e50e2d6..36fa7c397d56 100644
--- a/src/Cli/dotnet/commands/dotnet-workload/install/NetSdkMsiInstallerServer.cs
+++ b/src/Cli/dotnet/commands/dotnet-workload/install/NetSdkMsiInstallerServer.cs
@@ -105,7 +105,7 @@ public void Run()
case InstallRequestType.AdjustWorkloadMode:
UpdateInstallMode(new SdkFeatureBand(request.SdkFeatureBand), request.UseWorkloadSets);
- string newMode = request.UseWorkloadSets ? "workload sets" : "loose manifests";
+ string newMode = request.UseWorkloadSets == null ? "" : request.UseWorkloadSets.Value ? "workload sets" : "loose manifests";
Dispatcher.ReplySuccess($"Updated install mode to use {newMode}.");
break;
diff --git a/src/Cli/dotnet/commands/dotnet-workload/install/WorkloadGarbageCollector.cs b/src/Cli/dotnet/commands/dotnet-workload/install/WorkloadGarbageCollector.cs
index 88f0bda5a856..62d7e16cac48 100644
--- a/src/Cli/dotnet/commands/dotnet-workload/install/WorkloadGarbageCollector.cs
+++ b/src/Cli/dotnet/commands/dotnet-workload/install/WorkloadGarbageCollector.cs
@@ -77,6 +77,7 @@ void GarbageCollectWorkloadSets()
foreach (var set in installedWorkloadSets.Keys)
{
WorkloadSetsToKeep.Add(set);
+ _verboseReporter.WriteLine($"GC: Keeping workload set version {set} because workload set GC isn't implemented yet.");
}
var installStateFilePath = Path.Combine(WorkloadInstallType.GetInstallStateFolder(_sdkFeatureBand, _dotnetDir), "default.json");
diff --git a/src/Cli/dotnet/commands/dotnet-workload/install/WorkloadInstallCommand.cs b/src/Cli/dotnet/commands/dotnet-workload/install/WorkloadInstallCommand.cs
index a03d3500e138..621c7c47d365 100644
--- a/src/Cli/dotnet/commands/dotnet-workload/install/WorkloadInstallCommand.cs
+++ b/src/Cli/dotnet/commands/dotnet-workload/install/WorkloadInstallCommand.cs
@@ -17,7 +17,7 @@ namespace Microsoft.DotNet.Workloads.Workload.Install
{
internal class WorkloadInstallCommand : InstallingWorkloadCommand
{
- private readonly bool _skipManifestUpdate;
+ private bool _skipManifestUpdate;
private readonly IReadOnlyCollection _workloadIds;
public WorkloadInstallCommand(
@@ -43,8 +43,6 @@ public WorkloadInstallCommand(
_workloadManifestUpdater = _workloadManifestUpdaterFromConstructor ?? new WorkloadManifestUpdater(Reporter, _workloadResolver, PackageDownloader, _userProfileDir,
_workloadInstaller.GetWorkloadInstallationRecordRepository(), _workloadInstaller, _packageSourceLocation, displayManifestUpdates: Verbosity.IsDetailedOrDiagnostic());
-
- _workloadSetVersion = parseResult.GetValue(InstallingWorkloadCommandParser.WorkloadSetVersionOption);
}
private void ValidateWorkloadIdsInput()
@@ -108,60 +106,96 @@ public override int Execute()
WorkloadInstallCommandParser.SkipManifestUpdateOption.Name, InstallingWorkloadCommandParser.FromRollbackFileOption.Name,
WorkloadInstallCommandParser.SkipManifestUpdateOption.Name, InstallingWorkloadCommandParser.FromRollbackFileOption.Name), isUserError: true);
}
+ else if (_skipManifestUpdate && SpecifiedWorkloadSetVersionOnCommandLine)
+ {
+ throw new GracefulException(string.Format(LocalizableStrings.CannotCombineSkipManifestAndVersion,
+ WorkloadInstallCommandParser.SkipManifestUpdateOption.Name, InstallingWorkloadCommandParser.VersionOption.Name), isUserError: true);
+ }
+ else if (_skipManifestUpdate && SpecifiedWorkloadSetVersionInGlobalJson)
+ {
+ throw new GracefulException(string.Format(LocalizableStrings.CannotUseSkipManifestWithGlobalJsonWorkloadVersion,
+ WorkloadInstallCommandParser.SkipManifestUpdateOption.Name, _globalJsonPath), isUserError: true);
+ }
else
{
- var globaljsonPath = SdkDirectoryWorkloadManifestProvider.GetGlobalJsonPath(Environment.CurrentDirectory);
- _workloadSetVersionFromGlobalJson = SdkDirectoryWorkloadManifestProvider.GlobalJsonReader.GetWorkloadVersionFromGlobalJson(globaljsonPath);
-
try
{
- ErrorIfGlobalJsonAndCommandLineMismatch(globaljsonPath);
-
// Normally we want to validate that the workload IDs specified were valid. However, if there is a global.json file with a workload
- // set version specified, and we might update the workload version, then we don't do that check here, because we might not have the right
+ // set version specified, and we might install that workload version, then we don't do that check here, because we might not have the right
// workload set installed yet, and trying to list the available workloads would throw an error
if (_skipManifestUpdate || string.IsNullOrEmpty(_workloadSetVersionFromGlobalJson))
{
ValidateWorkloadIdsInput();
}
- if (string.IsNullOrWhiteSpace(_workloadSetVersion) && string.IsNullOrWhiteSpace(_workloadSetVersionFromGlobalJson))
- {
- var installStateFilePath = Path.Combine(WorkloadInstallType.GetInstallStateFolder(_sdkFeatureBand, _dotnetPath), "default.json");
- if (File.Exists(installStateFilePath))
- {
- var installStateContents = InstallStateContents.FromPath(installStateFilePath);
- _workloadSetVersion = installStateContents.WorkloadVersion;
- }
- }
+ Reporter.WriteLine();
DirectoryPath? offlineCache = string.IsNullOrWhiteSpace(_fromCacheOption) ? null : new DirectoryPath(_fromCacheOption);
var workloadIds = _workloadIds.Select(id => new WorkloadId(id));
- if (string.IsNullOrWhiteSpace(_workloadSetVersion) && string.IsNullOrWhiteSpace(_workloadSetVersionFromGlobalJson))
+
+ // Add workload Ids that already exist to our collection to later trigger an update in those installed workloads
+ var installedWorkloads = _workloadInstaller.GetWorkloadInstallationRecordRepository().GetInstalledWorkloads(_sdkFeatureBand);
+ var previouslyInstalledWorkloads = installedWorkloads.Intersect(workloadIds);
+ if (previouslyInstalledWorkloads.Any())
{
- InstallWorkloads(
- workloadIds,
- _skipManifestUpdate,
- _includePreviews,
- offlineCache);
+ Reporter.WriteLine(string.Format(LocalizableStrings.WorkloadAlreadyInstalled, string.Join(" ", previouslyInstalledWorkloads)).Yellow());
}
- else
+ workloadIds = workloadIds.Concat(installedWorkloads).Distinct();
+ workloadIds = WriteSDKInstallRecordsForVSWorkloads(workloadIds);
+
+ if (!_skipManifestUpdate)
{
- RunInNewTransaction(context =>
+ var installStateFilePath = Path.Combine(WorkloadInstallType.GetInstallStateFolder(_sdkFeatureBand, _dotnetPath), "default.json");
+ if (string.IsNullOrWhiteSpace(_fromRollbackDefinition) &&
+ !SpecifiedWorkloadSetVersionOnCommandLine &&
+ !SpecifiedWorkloadSetVersionInGlobalJson &&
+ InstallStateContents.FromPath(installStateFilePath) is InstallStateContents installState &&
+ (installState.Manifests != null || installState.WorkloadVersion != null))
{
- if (!TryHandleWorkloadUpdateFromVersion(context, offlineCache, out var manifests))
+ // If the workload version is pinned in the install state, then we don't want to automatically update workloads when a workload is installed
+ // To update to a new version, the user would need to run "dotnet workload update"
+ _skipManifestUpdate = true;
+ }
+ }
+
+ RunInNewTransaction(context =>
+ {
+ if (!_skipManifestUpdate)
+ {
+ if (Verbosity != VerbosityOptions.quiet && Verbosity != VerbosityOptions.q)
{
- return;
+ Reporter.WriteLine(LocalizableStrings.CheckForUpdatedWorkloadManifests);
}
- InstallWorkloadsWithInstallRecord(context, _workloadInstaller, workloadIds, _sdkFeatureBand, manifests, offlineCache, false);
- });
+ UpdateWorkloadManifests(context, offlineCache);
+ }
+ _workloadInstaller.InstallWorkloads(workloadIds, _sdkFeatureBand, context, offlineCache);
+
+ // Write workload installation records
+ var recordRepo = _workloadInstaller.GetWorkloadInstallationRecordRepository();
+ var newWorkloadInstallRecords = workloadIds.Except(recordRepo.GetInstalledWorkloads(_sdkFeatureBand));
+ context.Run(
+ action: () =>
+ {
+ foreach (var workloadId in newWorkloadInstallRecords)
+ {
+ recordRepo.WriteWorkloadInstallationRecord(workloadId, _sdkFeatureBand);
+ }
+ },
+ rollback: () =>
+ {
+ foreach (var workloadId in newWorkloadInstallRecords)
+ {
+ recordRepo.DeleteWorkloadInstallationRecord(workloadId, _sdkFeatureBand);
+ }
+ });
TryRunGarbageCollection(_workloadInstaller, Reporter, Verbosity, workloadSetVersion => _workloadResolverFactory.CreateForWorkloadSet(_dotnetPath, _sdkVersion.ToString(), _userProfileDir, workloadSetVersion), offlineCache);
Reporter.WriteLine();
- Reporter.WriteLine(string.Format(LocalizableStrings.InstallationSucceeded, string.Join(" ", workloadIds)));
+ Reporter.WriteLine(string.Format(LocalizableStrings.InstallationSucceeded, string.Join(" ", newWorkloadInstallRecords)));
Reporter.WriteLine();
- }
+
+ });
}
catch (Exception e)
{
@@ -174,74 +208,6 @@ public override int Execute()
return _workloadInstaller.ExitCode;
}
- public void InstallWorkloads(IEnumerable workloadIds, bool skipManifestUpdate = false, bool includePreviews = false, DirectoryPath? offlineCache = null)
- {
- Reporter.WriteLine();
-
- var manifestsToUpdate = Enumerable.Empty();
- var useRollback = false;
-
- WriteSDKInstallRecordsForVSWorkloads();
-
- if (!skipManifestUpdate)
- {
- var installStateFilePath = Path.Combine(WorkloadInstallType.GetInstallStateFolder(_sdkFeatureBand, _dotnetPath), "default.json");
- var installState = InstallStateContents.FromPath(installStateFilePath);
- if (string.IsNullOrWhiteSpace(_fromRollbackDefinition) && string.IsNullOrWhiteSpace(_workloadSetVersion) && string.IsNullOrWhiteSpace(_workloadSetVersionFromGlobalJson) &&
- (installState?.Manifests is not null || installState?.WorkloadVersion is not null))
- {
- // If there is a rollback state file, then we don't want to automatically update workloads when a workload is installed
- // To update to a new version, the user would need to run "dotnet workload update"
- skipManifestUpdate = true;
- }
- }
-
- RunInNewTransaction(context =>
- {
- if (!skipManifestUpdate)
- {
- if (Verbosity != VerbosityOptions.quiet && Verbosity != VerbosityOptions.q)
- {
- Reporter.WriteLine(LocalizableStrings.CheckForUpdatedWorkloadManifests);
- }
- // Add workload Ids that already exist to our collection to later trigger an update in those installed workloads
- var installedWorkloads = _workloadInstaller.GetWorkloadInstallationRecordRepository().GetInstalledWorkloads(_sdkFeatureBand);
- var previouslyInstalledWorkloads = installedWorkloads.Intersect(workloadIds);
- if (previouslyInstalledWorkloads.Any())
- {
- Reporter.WriteLine(string.Format(LocalizableStrings.WorkloadAlreadyInstalled, string.Join(" ", previouslyInstalledWorkloads)).Yellow());
- }
- workloadIds = workloadIds.Concat(installedWorkloads).Distinct();
-
- var useWorkloadSets = ShouldUseWorkloadSetMode(_sdkFeatureBand, _dotnetPath);
- useRollback = !string.IsNullOrWhiteSpace(_fromRollbackDefinition);
-
- _workloadManifestUpdater.UpdateAdvertisingManifestsAsync(includePreviews, useWorkloadSets, offlineCache).Wait();
-
- if (useWorkloadSets)
- {
- if (!TryInstallWorkloadSet(context, out manifestsToUpdate))
- {
- return;
- }
- }
- else
- {
- manifestsToUpdate = useRollback ? _workloadManifestUpdater.CalculateManifestRollbacks(_fromRollbackDefinition) :
- _workloadManifestUpdater.CalculateManifestUpdates().Select(m => m.ManifestUpdate);
- }
- }
-
- InstallWorkloadsWithInstallRecord(context, _workloadInstaller, workloadIds, _sdkFeatureBand, manifestsToUpdate, offlineCache, useRollback);
- });
-
- TryRunGarbageCollection(_workloadInstaller, Reporter, Verbosity, workloadSetVersion => _workloadResolverFactory.CreateForWorkloadSet(_dotnetPath, _sdkVersion.ToString(), _userProfileDir, workloadSetVersion), offlineCache);
-
- Reporter.WriteLine();
- Reporter.WriteLine(string.Format(LocalizableStrings.InstallationSucceeded, string.Join(" ", workloadIds)));
- Reporter.WriteLine();
- }
-
internal static void TryRunGarbageCollection(IInstaller workloadInstaller, IReporter reporter, VerbosityOptions verbosity, Func getResolverForWorkloadSet, DirectoryPath? offlineCache = null)
{
try
@@ -256,76 +222,6 @@ internal static void TryRunGarbageCollection(IInstaller workloadInstaller, IRepo
}
}
- private void WriteSDKInstallRecordsForVSWorkloads()
- {
-#if !DOT_NET_BUILD_FROM_SOURCE
- if (OperatingSystem.IsWindows())
- {
- // The 'workload restore' command relies on this happening through the existing chain of logic, if this is massively refactored please ensure this is called.
- VisualStudioWorkloads.WriteSDKInstallRecordsForVSWorkloads(_workloadInstaller, _workloadResolver, GetInstalledWorkloads(false), Reporter);
- }
-#endif
- }
-
- private void InstallWorkloadsWithInstallRecord(
- ITransactionContext context,
- IInstaller installer,
- IEnumerable workloadIds,
- SdkFeatureBand sdkFeatureBand,
- IEnumerable manifestsToUpdate,
- DirectoryPath? offlineCache,
- bool usingRollback)
- {
- IEnumerable workloadPackToInstall = new List();
- IEnumerable newWorkloadInstallRecords = new List();
-
- context.Run(
- action: () =>
- {
- bool rollback = !string.IsNullOrWhiteSpace(_fromRollbackDefinition);
-
- foreach (var manifestUpdate in manifestsToUpdate)
- {
- installer.InstallWorkloadManifest(manifestUpdate, context, offlineCache, rollback);
- }
-
- if (usingRollback)
- {
- installer.SaveInstallStateManifestVersions(sdkFeatureBand, GetInstallStateContents(manifestsToUpdate));
- }
-
- if (string.IsNullOrWhiteSpace(_workloadSetVersionFromGlobalJson))
- {
- installer.AdjustWorkloadSetInInstallState(sdkFeatureBand, string.IsNullOrWhiteSpace(_workloadSetVersion) ? null : _workloadSetVersion);
- }
-
- _workloadResolver.RefreshWorkloadManifests();
-
- installer.InstallWorkloads(workloadIds, sdkFeatureBand, context, offlineCache);
-
- var recordRepo = installer.GetWorkloadInstallationRecordRepository();
- newWorkloadInstallRecords = workloadIds.Except(recordRepo.GetInstalledWorkloads(sdkFeatureBand));
- foreach (var workloadId in newWorkloadInstallRecords)
- {
- recordRepo.WriteWorkloadInstallationRecord(workloadId, sdkFeatureBand);
- }
- },
- rollback: () =>
- {
- // InstallWorkloadManifest and InstallWorkloadPacks already handle rolling back their actions, so here we only
- // need to delete the installation records
- foreach (var workloadId in newWorkloadInstallRecords)
- {
- installer.GetWorkloadInstallationRecordRepository()
- .DeleteWorkloadInstallationRecord(workloadId, sdkFeatureBand);
- }
-
- // Refresh the workload manifests to make sure that the resolver has the updated state after the rollback
- _workloadResolver.RefreshWorkloadManifests();
- });
-
- }
-
private async Task> GetPackageDownloadUrlsAsync(IEnumerable workloadIds, bool skipManifestUpdate, bool includePreview)
{
var downloads = await GetDownloads(workloadIds, skipManifestUpdate, includePreview);
diff --git a/src/Cli/dotnet/commands/dotnet-workload/install/WorkloadManifestUpdater.cs b/src/Cli/dotnet/commands/dotnet-workload/install/WorkloadManifestUpdater.cs
index e2a311ac7d96..1919eb36d600 100644
--- a/src/Cli/dotnet/commands/dotnet-workload/install/WorkloadManifestUpdater.cs
+++ b/src/Cli/dotnet/commands/dotnet-workload/install/WorkloadManifestUpdater.cs
@@ -19,6 +19,8 @@ namespace Microsoft.DotNet.Workloads.Workload.Install
{
internal class WorkloadManifestUpdater : IWorkloadManifestUpdater
{
+ readonly string WorkloadSetManifestId = "Microsoft.NET.Workloads";
+
private readonly IReporter _reporter;
private readonly IWorkloadResolver _workloadResolver;
private readonly INuGetPackageDownloader _nugetPackageDownloader;
@@ -89,12 +91,6 @@ public async Task UpdateAdvertisingManifestsAsync(bool includePreviews, bool use
}
}
- public void DownloadWorkloadSet(string version, DirectoryPath? offlineCache = null)
- {
- var correctedVersion = WorkloadSetVersionToWorkloadSetPackageVersion(version);
- Task.Run(() => UpdateManifestWithVersionAsync("Microsoft.NET.Workloads", includePreviews: true, _sdkFeatureBand, new NuGetVersion(correctedVersion), offlineCache)).Wait();
- }
-
public async static Task BackgroundUpdateAdvertisingManifestsAsync(string userProfileDir)
{
try
@@ -156,14 +152,8 @@ public void DeleteUpdatableWorkloadsFile()
}
}
- public static string WorkloadSetVersionToWorkloadSetPackageVersion(string setVersion)
- {
- var nugetVersion = new NuGetVersion(setVersion);
- var patch = nugetVersion.Revision;
- var release = string.IsNullOrWhiteSpace(nugetVersion.Release) ? string.Empty : $"-{nugetVersion.Release}";
- return $"{nugetVersion.Major}.{nugetVersion.Patch}.{patch}{release}";
- }
-
+ // Corresponding method for opposite direction is in WorkloadSet class. This version is kept here as implementation
+ // depends on NuGetVersion
public static string WorkloadSetPackageVersionToWorkloadSetVersion(SdkFeatureBand sdkFeatureBand, string packageVersion)
{
var nugetVersion = new NuGetVersion(packageVersion);
@@ -195,6 +185,17 @@ public static void AdvertiseWorkloadUpdates()
}
}
+ public string GetAdvertisedWorkloadSetVersion()
+ {
+ var advertisedPath = GetAdvertisingManifestPath(_sdkFeatureBand, new ManifestId(WorkloadSetManifestId));
+ var workloadSetVersionFilePath = Path.Combine(advertisedPath, Constants.workloadSetVersionFileName);
+ if (File.Exists(workloadSetVersionFilePath))
+ {
+ return File.ReadAllText(workloadSetVersionFilePath);
+ }
+ return null;
+ }
+
public IEnumerable CalculateManifestUpdates()
{
var currentManifestIds = GetInstalledManifestIds();
@@ -211,7 +212,7 @@ public IEnumerable CalculateManifestUpdates()
if ((adVersion.CompareTo(installedVersion) > 0 && adBand.Equals(installedBand)) ||
adBand.CompareTo(installedBand) > 0)
{
- var update = new ManifestVersionUpdate(manifestId, installedVersion, installedBand.ToString(), adVersion, adBand.ToString());
+ var update = new ManifestVersionUpdate(manifestId, adVersion, adBand.ToString());
yield return new(update, adWorkloads);
}
}
@@ -261,8 +262,7 @@ private IEnumerable CalculateManifestRollbacks(IEnumerabl
return versionUpdates.Select(manifest =>
{
var (id, (version, band)) = manifest;
- var (installedVersion, installedBand) = GetInstalledManifestVersion(id);
- return new ManifestVersionUpdate(id, installedVersion, installedBand.ToString(), version, band.ToString());
+ return new ManifestVersionUpdate(id, version, band.ToString());
});
}
@@ -346,7 +346,7 @@ private async Task UpdateManifestWithVersionAsync(string id, bool includeP
// add file that contains the advertised manifest feature band so GetAdvertisingManifestVersionAndWorkloads will use correct feature band, regardless of if rollback occurred or not
File.WriteAllText(Path.Combine(adManifestPath, "AdvertisedManifestFeatureBand.txt"), band.ToString());
- if (id.Equals("Microsoft.NET.Workloads"))
+ if (id.Equals(WorkloadSetManifestId))
{
// Create version file later used as part of installing the workload set in the file-based installer and in the msi-based installer
using PackageArchiveReader packageReader = new(packagePath);
@@ -438,12 +438,7 @@ private async Task UpdateAdvertisingManifestAsync(WorkloadManifestInfo manifest,
private ManifestVersionWithBand GetInstalledManifestVersion(ManifestId manifestId)
{
- var manifest = _workloadResolver.GetInstalledManifests().FirstOrDefault(manifest => manifest.Id.ToLowerInvariant().Equals(manifestId.ToString()));
- if (manifest == null)
- {
- throw new Exception(string.Format(LocalizableStrings.ManifestDoesNotExist, manifestId.ToString()));
- }
- return new(new ManifestVersion(manifest.Version), new SdkFeatureBand(manifest.ManifestFeatureBand));
+ return new(new ManifestVersion(_workloadResolver.GetManifestVersion(manifestId.ToString())), new SdkFeatureBand(_workloadResolver.GetManifestFeatureBand(manifestId.ToString())));
}
private bool AdManifestSentinelIsDueForUpdate()
@@ -469,6 +464,7 @@ private bool AdManifestSentinelIsDueForUpdate()
private async Task UpdatedAdManifestPackagesExistAsync()
{
var manifests = GetInstalledManifestIds();
+ // TODO: This doesn't seem to account for differing feature bands
var availableUpdates = await Task.WhenAll(manifests.Select(manifest => NewerManifestPackageExists(manifest))).ConfigureAwait(false);
return availableUpdates.Any();
}
@@ -487,37 +483,9 @@ private async Task NewerManifestPackageExists(ManifestId manifest)
}
}
- public IEnumerable ParseRollbackDefinitionFiles(IEnumerable rollbackFilePaths)
+ public IEnumerable CalculateManifestUpdatesForWorkloadSet(WorkloadSet workloadSet)
{
- var zeroVersion = new ManifestVersion("0.0.0");
- if (rollbackFilePaths.Count() == 1)
- {
- return ParseRollbackDefinitionFile(rollbackFilePaths.Single(), _sdkFeatureBand).Select(manifest =>
- {
- var (id, (version, band)) = manifest;
- return new ManifestVersionUpdate(id, zeroVersion, band.ToString(), version, band.ToString());
- });
- }
-
- // Create a single workload set that includes all the others
- List<(ManifestId, ManifestVersionWithBand)> fullSet = new();
- foreach (var rollbackFile in rollbackFilePaths)
- {
- fullSet.AddRange(ParseRollbackDefinitionFile(rollbackFile, _sdkFeatureBand));
- }
-
- var reducedFullSet = fullSet.DistinctBy<(ManifestId, ManifestVersionWithBand), ManifestId>(update => update.Item1).ToList();
- if (fullSet.Count != reducedFullSet.Count)
- {
- var duplicates = reducedFullSet.Where(manifest => fullSet.Where(m => m.Item1.Equals(manifest.Item1)).Count() > 1);
- throw new ArgumentException("There were duplicates of the following manifests between the workload set files: " + string.Join(", ", duplicates));
- }
-
- return fullSet.Select(manifest =>
- {
- var (id, (version, band)) = manifest;
- return new ManifestVersionUpdate(id, zeroVersion, band.ToString(), version, band.ToString());
- });
+ return CalculateManifestRollbacks(workloadSet.ManifestVersions.Select(kvp => (kvp.Key, new ManifestVersionWithBand(kvp.Value.Version, kvp.Value.FeatureBand))));
}
private static IEnumerable<(ManifestId Id, ManifestVersionWithBand ManifestWithBand)> ParseRollbackDefinitionFile(string rollbackDefinitionFilePath, SdkFeatureBand featureBand)
diff --git a/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.cs.xlf b/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.cs.xlf
index 7340264b19d8..c183619d1c2d 100644
--- a/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.cs.xlf
+++ b/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.cs.xlf
@@ -22,14 +22,24 @@
Možnosti {0} a {1} nelze použít společně. Při instalaci ze souboru vráceného zpět odeberte {0}. V opačném případě odeberte {1}.
+
+ Cannot use the {0} and {1} options together. Remove one of the options.
+ Cannot use the {0} and {1} options together. Remove one of the options.
+
+ Cannot specify a particular workload version on the command line via --version or --from-history when there is already a version specified in global.json file {0}. To update the globally installed workload version, run the command outside of the path containing that global.json file or update the version specified in the global.json file and run "dotnet workload update."Na příkazovém řádku nelze pomocí možnosti --version nebo --from-history zadat konkrétní verzi úlohy, pokud je již verze zadána v souboru global.json {0}. Pokud chcete aktualizovat globálně nainstalovanou verzi úlohy, spusťte příkaz mimo cestu obsahující daný soubor global.json nebo aktualizujte verzi uvedenou v souboru global.json a spusťte příkaz dotnet workload update.
+
+ Cannot use the {0} option when workload version is specified in global.json. Remove the {0} option, or remove the 'workloadVersion' element from {1}.
+ Cannot use the {0} option when workload version is specified in global.json. Remove the {0} option, or remove the 'workloadVersion' element from {1}.
+ "workloadVersion" and "global.json" are literal values and should not be translated.
+
- Checking for updated workload manifests.
- Kontrolují se aktualizované manifesty úloh.
+ Checking for updated workload version.
+ Kontrolují se aktualizované manifesty úloh.
@@ -82,6 +92,11 @@
Nepodařilo se nainstalovat manifest {0} verze {1}: {2}.
+
+ Failed to install workload version {0}: {1}
+ Failed to install workload version {0}: {1}
+
+ DIRECTORYADRESÁŘ
@@ -157,11 +172,6 @@
Cílová architektura, pro kterou se má úloha nainstalovat
-
- No manifest with ID {0} exists.
- Neexistuje žádný manifest s ID {0}.
-
- Manifest MSI not found in NuGet package {0}Instalační služba MSI manifestu se nenašla v balíčku NuGet {0}.
diff --git a/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.de.xlf b/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.de.xlf
index 69347ea91ace..9a0ef4029414 100644
--- a/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.de.xlf
+++ b/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.de.xlf
@@ -22,14 +22,24 @@
Die Optionen {0} und {1} können nicht zusammen verwendet werden. Entfernen Sie bei der Installation aus einer Rollbackdatei {0}. Entfernen Sie andernfalls {1}
+
+ Cannot use the {0} and {1} options together. Remove one of the options.
+ Cannot use the {0} and {1} options together. Remove one of the options.
+
+ Cannot specify a particular workload version on the command line via --version or --from-history when there is already a version specified in global.json file {0}. To update the globally installed workload version, run the command outside of the path containing that global.json file or update the version specified in the global.json file and run "dotnet workload update."Eine bestimmte Workload-Version kann in der Befehlszeile nicht über „--version“ oder „--from-history“ angegeben werden, wenn bereits eine Version in der global.json-Datei „{0}“ angegeben ist. Um die global installierte Workload-Version zu aktualisieren, führen Sie den Befehl außerhalb des Pfads aus, der diese global.json-Datei enthält, oder aktualisieren Sie die in der global.json Datei angegebene Version, und führen Sie „dotnet workload update“ aus.
+
+ Cannot use the {0} option when workload version is specified in global.json. Remove the {0} option, or remove the 'workloadVersion' element from {1}.
+ Cannot use the {0} option when workload version is specified in global.json. Remove the {0} option, or remove the 'workloadVersion' element from {1}.
+ "workloadVersion" and "global.json" are literal values and should not be translated.
+
- Checking for updated workload manifests.
- Es wird nach aktualisierten Workloadmanifesten gesucht.
+ Checking for updated workload version.
+ Es wird nach aktualisierten Workloadmanifesten gesucht.
@@ -82,6 +92,11 @@
Fehler beim Installieren des Manifests "{0}", Version {1}: {2}.
+
+ Failed to install workload version {0}: {1}
+ Failed to install workload version {0}: {1}
+
+ DIRECTORYVERZEICHNIS
@@ -157,11 +172,6 @@
Das Zielframework, für das die Workload installiert wird.
-
- No manifest with ID {0} exists.
- Es ist kein Manifest mit der ID {0} vorhanden.
-
- Manifest MSI not found in NuGet package {0}Manifest-MSI wurde im NuGet-Paket {0} nicht gefunden.
diff --git a/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.es.xlf b/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.es.xlf
index 044a776d23c3..1c36327c0f7e 100644
--- a/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.es.xlf
+++ b/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.es.xlf
@@ -22,14 +22,24 @@
No se pueden usar las opciones {0} y {1} juntas. Si se instala desde un archivo de reversión, quite {0}. De lo contrario, quite {1}
+
+ Cannot use the {0} and {1} options together. Remove one of the options.
+ Cannot use the {0} and {1} options together. Remove one of the options.
+
+ Cannot specify a particular workload version on the command line via --version or --from-history when there is already a version specified in global.json file {0}. To update the globally installed workload version, run the command outside of the path containing that global.json file or update the version specified in the global.json file and run "dotnet workload update."No se puede especificar una versión de carga de trabajo determinada en la línea de comandos mediante --version o --from-history cuando ya hay una versión especificada en el archivo global.json {0}. Para actualizar la versión de carga de trabajo instalada globalmente, ejecute el comando fuera de la ruta de acceso que contiene ese archivo global.json o actualice la versión especificada en el archivo global.json y ejecute "dotnet workload update".
+
+ Cannot use the {0} option when workload version is specified in global.json. Remove the {0} option, or remove the 'workloadVersion' element from {1}.
+ Cannot use the {0} option when workload version is specified in global.json. Remove the {0} option, or remove the 'workloadVersion' element from {1}.
+ "workloadVersion" and "global.json" are literal values and should not be translated.
+
- Checking for updated workload manifests.
- Comprobando si hay manifiestos de carga de trabajo actualizados.
+ Checking for updated workload version.
+ Comprobando si hay manifiestos de carga de trabajo actualizados.
@@ -82,6 +92,11 @@
No se pudo instalar el manifiesto {0}, versión {1}: {2}.
+
+ Failed to install workload version {0}: {1}
+ Failed to install workload version {0}: {1}
+
+ DIRECTORYDIRECTORIO
@@ -157,11 +172,6 @@
La plataforma de destino para la que se instala la carga de trabajo.
-
- No manifest with ID {0} exists.
- No existe ningún manifiesto con id. {0}.
-
- Manifest MSI not found in NuGet package {0}No se encontró el MSI del manifiesto en el paquete NuGet {0}
diff --git a/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.fr.xlf b/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.fr.xlf
index 487850c153ea..262d1fd57515 100644
--- a/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.fr.xlf
+++ b/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.fr.xlf
@@ -22,14 +22,24 @@
Impossible d’utiliser les options {0} et {1} ensemble. Si vous installez à partir d’un fichier de restauration, supprimez {0}. Sinon, supprimez {1}.
+
+ Cannot use the {0} and {1} options together. Remove one of the options.
+ Cannot use the {0} and {1} options together. Remove one of the options.
+
+ Cannot specify a particular workload version on the command line via --version or --from-history when there is already a version specified in global.json file {0}. To update the globally installed workload version, run the command outside of the path containing that global.json file or update the version specified in the global.json file and run "dotnet workload update."Impossible de spécifier une version de charge de travail particulière sur la ligne de commande via --version ou --from-history lorsqu’une version est déjà spécifiée dans global.json fichier {0}. Pour mettre à jour la version de la charge de travail installée globalement, exécutez la commande en dehors du chemin contenant ce fichier global.json ou mettez à jour la version spécifiée dans le fichier global.json et exécutez « dotnet workload update »
+
+ Cannot use the {0} option when workload version is specified in global.json. Remove the {0} option, or remove the 'workloadVersion' element from {1}.
+ Cannot use the {0} option when workload version is specified in global.json. Remove the {0} option, or remove the 'workloadVersion' element from {1}.
+ "workloadVersion" and "global.json" are literal values and should not be translated.
+
- Checking for updated workload manifests.
- Recherche de manifestes de charge de travail mis à jour
+ Checking for updated workload version.
+ Recherche de manifestes de charge de travail mis à jour
@@ -82,6 +92,11 @@
Impossible d'installer la {0} version de manifeste {1}: {2}
+
+ Failed to install workload version {0}: {1}
+ Failed to install workload version {0}: {1}
+
+ DIRECTORYRÉPERTOIRE
@@ -157,11 +172,6 @@
Framework cible pour lequel la charge de travail doit être installée.
-
- No manifest with ID {0} exists.
- Aucun manifeste ayant l’ID {0} existe.
-
- Manifest MSI not found in NuGet package {0}MSI de manifeste introuvable dans le package NuGet {0}
diff --git a/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.it.xlf b/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.it.xlf
index 98347b10c943..08486a0f1f6f 100644
--- a/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.it.xlf
+++ b/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.it.xlf
@@ -22,14 +22,24 @@
Impossibile utilizzare contemporaneamente le opzioni {0} e {1}. Se si esegue l'installazione da un file di rollback, rimuovere {0}. In caso contrario, rimuovere {1}
+
+ Cannot use the {0} and {1} options together. Remove one of the options.
+ Cannot use the {0} and {1} options together. Remove one of the options.
+
+ Cannot specify a particular workload version on the command line via --version or --from-history when there is already a version specified in global.json file {0}. To update the globally installed workload version, run the command outside of the path containing that global.json file or update the version specified in the global.json file and run "dotnet workload update."Impossibile specificare una determinata versione del carico di lavoro nella riga di comando tramite --version o --from-history quando è già specificata una versione nel file global.json {0}. Per aggiornare la versione del carico di lavoro installata a livello globale, eseguire il comando all'esterno del percorso contenente tale file global.json o aggiornare la versione specificata nel file di global.json ed eseguire "dotnet workload update".
+
+ Cannot use the {0} option when workload version is specified in global.json. Remove the {0} option, or remove the 'workloadVersion' element from {1}.
+ Cannot use the {0} option when workload version is specified in global.json. Remove the {0} option, or remove the 'workloadVersion' element from {1}.
+ "workloadVersion" and "global.json" are literal values and should not be translated.
+
- Checking for updated workload manifests.
- Verifica della disponibilità di manifesti del carico di lavoro aggiornati.
+ Checking for updated workload version.
+ Verifica della disponibilità di manifesti del carico di lavoro aggiornati.
@@ -82,6 +92,11 @@
Non è stato possibile installare il manifesto {0}, versione {1}: {2}.
+
+ Failed to install workload version {0}: {1}
+ Failed to install workload version {0}: {1}
+
+ DIRECTORYDIRECTORY
@@ -157,11 +172,6 @@
Framework di destinazione per cui installare il carico di lavoro.
-
- No manifest with ID {0} exists.
- Non esiste alcun manifesto con ID {0}.
-
- Manifest MSI not found in NuGet package {0}L'identità del servizio gestita del manifesto non è stata trovata nel pacchetto NuGet {0}
diff --git a/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.ja.xlf b/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.ja.xlf
index d53564fc72e0..69625b03d4a3 100644
--- a/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.ja.xlf
+++ b/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.ja.xlf
@@ -22,14 +22,24 @@
{0} オプションと {1} オプションを併用することはできません。ロールバック ファイルからインストールする場合、{0} を削除してください。その他の場合には、{1} を削除します
+
+ Cannot use the {0} and {1} options together. Remove one of the options.
+ Cannot use the {0} and {1} options together. Remove one of the options.
+
+ Cannot specify a particular workload version on the command line via --version or --from-history when there is already a version specified in global.json file {0}. To update the globally installed workload version, run the command outside of the path containing that global.json file or update the version specified in the global.json file and run "dotnet workload update."global.json ファイル {0} に既にバージョンが指定されている場合は、コマンド ラインで --version または --from-history を使用して特定のワークロード バージョンを指定することはできません。グローバルにインストールされたワークロード バージョンを更新するには、その global.json ファイルを含むパスの外部でコマンドを実行するか、global.json ファイルで指定されたバージョンを更新して、"dotnet workload update" を実行します。
+
+ Cannot use the {0} option when workload version is specified in global.json. Remove the {0} option, or remove the 'workloadVersion' element from {1}.
+ Cannot use the {0} option when workload version is specified in global.json. Remove the {0} option, or remove the 'workloadVersion' element from {1}.
+ "workloadVersion" and "global.json" are literal values and should not be translated.
+
- Checking for updated workload manifests.
- 更新されたワークロード マニフェストを確認しています。
+ Checking for updated workload version.
+ 更新されたワークロード マニフェストを確認しています。
@@ -82,6 +92,11 @@
マニフェスト {0} のバージョン {1} をインストールできませんでした: {2}。
+
+ Failed to install workload version {0}: {1}
+ Failed to install workload version {0}: {1}
+
+ DIRECTORYディレクトリ
@@ -157,11 +172,6 @@
ワークロードをインストールするターゲット フレームワーク。
-
- No manifest with ID {0} exists.
- ID を持つ {0} マニフェストが存在しません。
-
- Manifest MSI not found in NuGet package {0}NuGet パッケージ {0} にマニフェスト MSI が見つかりません
diff --git a/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.ko.xlf b/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.ko.xlf
index 32603d599221..67bc55e9f64d 100644
--- a/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.ko.xlf
+++ b/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.ko.xlf
@@ -22,14 +22,24 @@
{0} 및 {1} 옵션을 함께 사용할 수 없습니다. 롤백 파일에서 설치하는 경우 {0}을(를) 제거합니다. 그렇지 않으면 {1}을(를) 제거합니다.
+
+ Cannot use the {0} and {1} options together. Remove one of the options.
+ Cannot use the {0} and {1} options together. Remove one of the options.
+
+ Cannot specify a particular workload version on the command line via --version or --from-history when there is already a version specified in global.json file {0}. To update the globally installed workload version, run the command outside of the path containing that global.json file or update the version specified in the global.json file and run "dotnet workload update."global.json 파일 {0}에 지정된 버전이 이미 있는 경우 --version 또는 --from-history를 통해 명령줄에서 특정 워크로드 버전을 지정할 수 없습니다. 전역으로 설치된 워크로드 버전을 업데이트하려면 해당 global.json 파일이 포함된 경로 외부에서 명령을 실행하거나 global.json 파일에 지정된 버전을 업데이트하고 "dotnet 워크로드 업데이트"를 실행합니다.
+
+ Cannot use the {0} option when workload version is specified in global.json. Remove the {0} option, or remove the 'workloadVersion' element from {1}.
+ Cannot use the {0} option when workload version is specified in global.json. Remove the {0} option, or remove the 'workloadVersion' element from {1}.
+ "workloadVersion" and "global.json" are literal values and should not be translated.
+
- Checking for updated workload manifests.
- 업데이트된 워크로드 매니페스트를 확인하는 중입니다.
+ Checking for updated workload version.
+ 업데이트된 워크로드 매니페스트를 확인하는 중입니다.
@@ -82,6 +92,11 @@
매니페스트 {0} 버전 {1}: {2}을 설치하지 못했습니다.
+
+ Failed to install workload version {0}: {1}
+ Failed to install workload version {0}: {1}
+
+ DIRECTORY디렉터리
@@ -157,11 +172,6 @@
워크로드를 설치할 대상 프레임워크입니다.
-
- No manifest with ID {0} exists.
- ID가 {0}인 매니페스트가 없습니다.
-
- Manifest MSI not found in NuGet package {0}NuGet 패키지 {0}에서 매니페스트 MSI를 찾을 수 없습니다.
diff --git a/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.pl.xlf b/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.pl.xlf
index 739bb0ad5089..732f158db201 100644
--- a/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.pl.xlf
+++ b/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.pl.xlf
@@ -22,14 +22,24 @@
Nie można jednocześnie używać poleceń {0} i {1}. W przypadku instalowania z pliku wycofywania usuń polecenie {0}. W przeciwnym razie usuń polecenie {1}
+
+ Cannot use the {0} and {1} options together. Remove one of the options.
+ Cannot use the {0} and {1} options together. Remove one of the options.
+
+ Cannot specify a particular workload version on the command line via --version or --from-history when there is already a version specified in global.json file {0}. To update the globally installed workload version, run the command outside of the path containing that global.json file or update the version specified in the global.json file and run "dotnet workload update."Nie można określić określonej wersji obciążenia w wierszu polecenia za pomocą opcji --version lub --from-history, jeśli istnieje już wersja określona w pliku global.json {0}. Aby zaktualizować wersję obciążenia zainstalowaną globalnie, uruchom polecenie poza ścieżką zawierającą ten plik global.json lub zaktualizuj wersję określoną w pliku global.json i uruchom polecenie „dotnet workload update”.
+
+ Cannot use the {0} option when workload version is specified in global.json. Remove the {0} option, or remove the 'workloadVersion' element from {1}.
+ Cannot use the {0} option when workload version is specified in global.json. Remove the {0} option, or remove the 'workloadVersion' element from {1}.
+ "workloadVersion" and "global.json" are literal values and should not be translated.
+
- Checking for updated workload manifests.
- Sprawdzanie zaktualizowanych manifestów obciążenia.
+ Checking for updated workload version.
+ Sprawdzanie zaktualizowanych manifestów obciążenia.
@@ -82,6 +92,11 @@
Instalowanie manifestu {0} w wersji {1} nie powiodło się: {2}.
+
+ Failed to install workload version {0}: {1}
+ Failed to install workload version {0}: {1}
+
+ DIRECTORYKATALOG
@@ -157,11 +172,6 @@
Docelowa platforma, dla której ma zostać zainstalowane obciążenie.
-
- No manifest with ID {0} exists.
- Nie istnieje żaden manifest o identyfikatorze {0}.
-
- Manifest MSI not found in NuGet package {0}Nie znaleziono pliku MSI manifestu w pakiecie NuGet {0}
diff --git a/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.pt-BR.xlf b/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.pt-BR.xlf
index 7174a379ecbf..87fd08333cb8 100644
--- a/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.pt-BR.xlf
+++ b/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.pt-BR.xlf
@@ -22,14 +22,24 @@
Não é possível usar as opções {0} e {1} juntas. Se estiver instalando a partir de um arquivo de reversão, remova {0}. Caso contrário, remova {1}
+
+ Cannot use the {0} and {1} options together. Remove one of the options.
+ Cannot use the {0} and {1} options together. Remove one of the options.
+
+ Cannot specify a particular workload version on the command line via --version or --from-history when there is already a version specified in global.json file {0}. To update the globally installed workload version, run the command outside of the path containing that global.json file or update the version specified in the global.json file and run "dotnet workload update."Não é possível especificar uma versão específica da carga de trabalho na linha de comando por meio de --version ou --from-history quando já existe uma versão especificada no arquivo global.json {0}. Para atualizar a versão da carga de trabalho instalada globalmente, execute o comando fora do caminho que contém o arquivo global.json ou atualize a versão especificada no arquivo global.json e execute "dotnet workload update".
+
+ Cannot use the {0} option when workload version is specified in global.json. Remove the {0} option, or remove the 'workloadVersion' element from {1}.
+ Cannot use the {0} option when workload version is specified in global.json. Remove the {0} option, or remove the 'workloadVersion' element from {1}.
+ "workloadVersion" and "global.json" are literal values and should not be translated.
+
- Checking for updated workload manifests.
- Verificando manifestos de carga de trabalho atualizados.
+ Checking for updated workload version.
+ Verificando manifestos de carga de trabalho atualizados.
@@ -82,6 +92,11 @@
Falha ao instalar o manifesto {0} versão {1}: {2}.
+
+ Failed to install workload version {0}: {1}
+ Failed to install workload version {0}: {1}
+
+ DIRECTORYDIRETÓRIO
@@ -157,11 +172,6 @@
A estrutura de destino para a qual a carga de trabalho será instalada.
-
- No manifest with ID {0} exists.
- Não existe nenhum manifesto com ID {0}.
-
- Manifest MSI not found in NuGet package {0}MSI do manifesto não encontrado no pacote NuGet {0}
diff --git a/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.ru.xlf b/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.ru.xlf
index a03ffba5378e..ae601d920cae 100644
--- a/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.ru.xlf
+++ b/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.ru.xlf
@@ -22,14 +22,24 @@
Невозможно использовать параметры {0} и {1} одновременно. При установке из файла отката удалите {0}, в противном случае удалите {1}.
+
+ Cannot use the {0} and {1} options together. Remove one of the options.
+ Cannot use the {0} and {1} options together. Remove one of the options.
+
+ Cannot specify a particular workload version on the command line via --version or --from-history when there is already a version specified in global.json file {0}. To update the globally installed workload version, run the command outside of the path containing that global.json file or update the version specified in the global.json file and run "dotnet workload update."Невозможно указать конкретную версию рабочей нагрузки в командной строке с помощью --version или --from-history, если в файле global.json уже указана версия {0}. Чтобы обновить глобально установленную версию рабочей нагрузки, выполните команду вне пути, содержащего этот файл global.json, либо измените версию в файле global.json и выполните команду "dotnet workload update".
+
+ Cannot use the {0} option when workload version is specified in global.json. Remove the {0} option, or remove the 'workloadVersion' element from {1}.
+ Cannot use the {0} option when workload version is specified in global.json. Remove the {0} option, or remove the 'workloadVersion' element from {1}.
+ "workloadVersion" and "global.json" are literal values and should not be translated.
+
- Checking for updated workload manifests.
- Проверка обновленных манифестов рабочей нагрузки.
+ Checking for updated workload version.
+ Проверка обновленных манифестов рабочей нагрузки.
@@ -82,6 +92,11 @@
Не удалось установить манифест {0} версии {1}: {2}.
+
+ Failed to install workload version {0}: {1}
+ Failed to install workload version {0}: {1}
+
+ DIRECTORYКАТАЛОГ
@@ -157,11 +172,6 @@
Целевая платформа для установки рабочей нагрузки.
-
- No manifest with ID {0} exists.
- Манифест с идентификатором {0} не существует.
-
- Manifest MSI not found in NuGet package {0}MSI манифеста не найден в пакете NuGet {0}
diff --git a/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.tr.xlf b/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.tr.xlf
index 47a1c30dbf18..e9518e983218 100644
--- a/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.tr.xlf
+++ b/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.tr.xlf
@@ -22,14 +22,24 @@
{0} ve {1} seçenekleri birlikte kullanılamıyor. Bir geri alma dosyasından yükleniyorsa {0} seçeneğini kaldırın. Aksi takdirde, {1} seçeneğini kaldırın
+
+ Cannot use the {0} and {1} options together. Remove one of the options.
+ Cannot use the {0} and {1} options together. Remove one of the options.
+
+ Cannot specify a particular workload version on the command line via --version or --from-history when there is already a version specified in global.json file {0}. To update the globally installed workload version, run the command outside of the path containing that global.json file or update the version specified in the global.json file and run "dotnet workload update."{0} global.json dosyasında zaten belirtilen bir sürüm varsa, “--version” veya “--from-history” aracılığıyla komut satırında belirli bir iş yükü sürümü belirtilemez. Genel olarak yüklenen iş yükü sürümünü güncelleştirmek için, komutu global.json dosyasını içeren yolun dışında çalıştırın veya global.json dosyasında belirtilen sürümü güncelleştirin ve “dotnet workload update” komutunu çalıştırın.
+
+ Cannot use the {0} option when workload version is specified in global.json. Remove the {0} option, or remove the 'workloadVersion' element from {1}.
+ Cannot use the {0} option when workload version is specified in global.json. Remove the {0} option, or remove the 'workloadVersion' element from {1}.
+ "workloadVersion" and "global.json" are literal values and should not be translated.
+
- Checking for updated workload manifests.
- Güncelleştirilmiş iş yükü bildirimleri denetleniyor.
+ Checking for updated workload version.
+ Güncelleştirilmiş iş yükü bildirimleri denetleniyor.
@@ -82,6 +92,11 @@
{0} bildirimi sürüm {1} yüklenemedi:{2}.
+
+ Failed to install workload version {0}: {1}
+ Failed to install workload version {0}: {1}
+
+ DIRECTORYDİZİN
@@ -157,11 +172,6 @@
İş yükünün yükleneceği hedef çerçeve.
-
- No manifest with ID {0} exists.
- {0} kimliğine sahip bildirim yok.
-
- Manifest MSI not found in NuGet package {0}{0} NuGet paketinde bildirim MSI'sı bulunamadı
diff --git a/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.zh-Hans.xlf b/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.zh-Hans.xlf
index be821166b151..c5d962aa3cb7 100644
--- a/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.zh-Hans.xlf
+++ b/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.zh-Hans.xlf
@@ -22,14 +22,24 @@
不能同时使用 {0} 和 {1} 选项。如果从回滚文件安装,请删除 {0}。否则,请删除 {1}
+
+ Cannot use the {0} and {1} options together. Remove one of the options.
+ Cannot use the {0} and {1} options together. Remove one of the options.
+
+ Cannot specify a particular workload version on the command line via --version or --from-history when there is already a version specified in global.json file {0}. To update the globally installed workload version, run the command outside of the path containing that global.json file or update the version specified in the global.json file and run "dotnet workload update."当 global.json 文件 {0} 中已指定版本时,无法在命令行上通过 --version 或 --from-history 指定特定工作负载版本。若要更新全局安装的工作负载版本,请在包含该 global.json 文件的路径外部运行命令,或者更新 global.json 文件中指定的版本,然后运行 "dotnet workload update"。
+
+ Cannot use the {0} option when workload version is specified in global.json. Remove the {0} option, or remove the 'workloadVersion' element from {1}.
+ Cannot use the {0} option when workload version is specified in global.json. Remove the {0} option, or remove the 'workloadVersion' element from {1}.
+ "workloadVersion" and "global.json" are literal values and should not be translated.
+
- Checking for updated workload manifests.
- 正在检查更新的工作负载清单。
+ Checking for updated workload version.
+ 正在检查更新的工作负载清单。
@@ -82,6 +92,11 @@
未能安装清单 {0} 版本 {1}: {2}。
+
+ Failed to install workload version {0}: {1}
+ Failed to install workload version {0}: {1}
+
+ DIRECTORY目录
@@ -157,11 +172,6 @@
要为其安装工作负载的目标框架。
-
- No manifest with ID {0} exists.
- 不存在 ID 为 {0} 的清单。
-
- Manifest MSI not found in NuGet package {0}在 NuGet 包 {0} 中找不到清单 MSI
diff --git a/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.zh-Hant.xlf b/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.zh-Hant.xlf
index dcade7263146..1310b788e92b 100644
--- a/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.zh-Hant.xlf
+++ b/src/Cli/dotnet/commands/dotnet-workload/install/xlf/LocalizableStrings.zh-Hant.xlf
@@ -22,14 +22,24 @@
無法同時使用 {0} 與 {1} 選項。如果從復原檔案安裝,請移除 {0}。否則,請移除 {1}
+
+ Cannot use the {0} and {1} options together. Remove one of the options.
+ Cannot use the {0} and {1} options together. Remove one of the options.
+
+ Cannot specify a particular workload version on the command line via --version or --from-history when there is already a version specified in global.json file {0}. To update the globally installed workload version, run the command outside of the path containing that global.json file or update the version specified in the global.json file and run "dotnet workload update."當 global.json 檔案 {0} 中已指定版本時,無法在命令列上透過 --version 或 --from-history 指定特定工作負載版本。若要更新全域安裝的工作負載版本,請在包含該 global.json 檔案的路徑外執行命令,或更新 global.json 檔案中指定的版本,然後執行 "dotnet workload update"。
+
+ Cannot use the {0} option when workload version is specified in global.json. Remove the {0} option, or remove the 'workloadVersion' element from {1}.
+ Cannot use the {0} option when workload version is specified in global.json. Remove the {0} option, or remove the 'workloadVersion' element from {1}.
+ "workloadVersion" and "global.json" are literal values and should not be translated.
+
- Checking for updated workload manifests.
- 正在檢查更新的工作負載資訊清單。
+ Checking for updated workload version.
+ 正在檢查更新的工作負載資訊清單。
@@ -82,6 +92,11 @@
無法安裝資訊清單 {0} 版本 {1}: {2}。
+
+ Failed to install workload version {0}: {1}
+ Failed to install workload version {0}: {1}
+
+ DIRECTORY目錄
@@ -157,11 +172,6 @@
要為工作負載安裝的目標 Framework。
-
- No manifest with ID {0} exists.
- 沒有識別碼為 {0} 的資訊清單。
-
- Manifest MSI not found in NuGet package {0}在 NuGet 套件 {0} 中找不到資訊清單 MSI
diff --git a/src/Cli/dotnet/commands/dotnet-workload/list/VisualStudioWorkloads.cs b/src/Cli/dotnet/commands/dotnet-workload/list/VisualStudioWorkloads.cs
index fe7415bdac98..2c3bc306405a 100644
--- a/src/Cli/dotnet/commands/dotnet-workload/list/VisualStudioWorkloads.cs
+++ b/src/Cli/dotnet/commands/dotnet-workload/list/VisualStudioWorkloads.cs
@@ -127,11 +127,12 @@ internal static void GetInstalledWorkloads(IWorkloadResolver workloadResolver,
/// This is to fix a bug where updating the manifests in the CLI will cause VS to also be told to use these newer workloads via the workload resolver.
/// ... but these workloads don't have their corresponding packs installed as VS doesn't update its workloads as the CLI does.
///
- internal static void WriteSDKInstallRecordsForVSWorkloads(IInstaller workloadInstaller, IWorkloadResolver workloadResolver,
+ /// Updated list of workloads including any that may have had new install records written
+ internal static IEnumerable WriteSDKInstallRecordsForVSWorkloads(IInstaller workloadInstaller, IWorkloadResolver workloadResolver,
IEnumerable workloadsWithExistingInstallRecords, IReporter reporter)
{
// Do this check to avoid adding an unused & unnecessary method to FileBasedInstallers
- if (OperatingSystem.IsWindows() && typeof(NetSdkMsiInstallerClient) == workloadInstaller.GetType())
+ if (OperatingSystem.IsWindows() && workloadInstaller is NetSdkMsiInstallerClient)
{
InstalledWorkloadsCollection vsWorkloads = new();
GetInstalledWorkloads(workloadResolver, vsWorkloads);
@@ -146,10 +147,15 @@ internal static void WriteSDKInstallRecordsForVSWorkloads(IInstaller workloadIns
string.Format(LocalizableStrings.WriteCLIRecordForVisualStudioWorkloadMessage,
string.Join(", ", workloadsToWriteRecordsFor.Select(w => w.ToString()).ToArray()))
);
- }
- ((NetSdkMsiInstallerClient)workloadInstaller).WriteWorkloadInstallRecords(workloadsToWriteRecordsFor);
+ ((NetSdkMsiInstallerClient)workloadInstaller).WriteWorkloadInstallRecords(workloadsToWriteRecordsFor);
+
+ return workloadsWithExistingInstallRecords.Concat(workloadsToWriteRecordsFor).ToList();
+ }
}
+
+ return workloadsWithExistingInstallRecords;
+
}
///
diff --git a/src/Cli/dotnet/commands/dotnet-workload/list/WorkloadListCommand.cs b/src/Cli/dotnet/commands/dotnet-workload/list/WorkloadListCommand.cs
index c927df84e4b4..252b33972bc8 100644
--- a/src/Cli/dotnet/commands/dotnet-workload/list/WorkloadListCommand.cs
+++ b/src/Cli/dotnet/commands/dotnet-workload/list/WorkloadListCommand.cs
@@ -150,7 +150,9 @@ internal IEnumerable GetUpdateAvailable(IEnumerableUpdating to a rollback file is not compatible with workload sets. Install and Update will now use loose manifests. To update to a specific workload version, use --version.
+
+ Cannot use the {0} and {1} options together.
+
No workload update found.
diff --git a/src/Cli/dotnet/commands/dotnet-workload/update/WorkloadUpdateCommand.cs b/src/Cli/dotnet/commands/dotnet-workload/update/WorkloadUpdateCommand.cs
index 7bd8614085c9..f340dcc83136 100644
--- a/src/Cli/dotnet/commands/dotnet-workload/update/WorkloadUpdateCommand.cs
+++ b/src/Cli/dotnet/commands/dotnet-workload/update/WorkloadUpdateCommand.cs
@@ -35,7 +35,7 @@ public WorkloadUpdateCommand(
tempDirPath: tempDirPath)
{
- _workloadSetVersion = parseResult.GetValue(InstallingWorkloadCommandParser.WorkloadSetVersionOption);
+
_fromPreviousSdk = parseResult.GetValue(WorkloadUpdateCommandParser.FromPreviousSdkOption);
_adManifestOnlyOption = parseResult.GetValue(WorkloadUpdateCommandParser.AdManifestOnlyOption);
_printRollbackDefinitionOnly = parseResult.GetValue(WorkloadUpdateCommandParser.PrintRollbackOption);
@@ -91,28 +91,27 @@ public override int Execute()
}
else
{
- var globaljsonPath = SdkDirectoryWorkloadManifestProvider.GetGlobalJsonPath(Environment.CurrentDirectory);
- _workloadSetVersionFromGlobalJson = SdkDirectoryWorkloadManifestProvider.GlobalJsonReader.GetWorkloadVersionFromGlobalJson(globaljsonPath);
-
+ Reporter.WriteLine();
try
{
- ErrorIfGlobalJsonAndCommandLineMismatch(globaljsonPath);
+ var workloadIds = WriteSDKInstallRecordsForVSWorkloads(GetUpdatableWorkloads());
+
DirectoryPath? offlineCache = string.IsNullOrWhiteSpace(_fromCacheOption) ? null : new DirectoryPath(_fromCacheOption);
- if (string.IsNullOrWhiteSpace(_workloadSetVersion) && string.IsNullOrWhiteSpace(_workloadSetVersionFromGlobalJson))
- {
- CalculateManifestUpdatesAndUpdateWorkloads(_includePreviews, offlineCache);
- }
- else
+
+ RunInNewTransaction(context =>
{
- RunInNewTransaction(context =>
- {
- if (!TryHandleWorkloadUpdateFromVersion(context, offlineCache, out var manifestUpdates))
- {
- return;
- }
- UpdateWorkloads(false, manifestUpdates, offlineCache, context);
- });
- }
+ UpdateWorkloadManifests(context, offlineCache);
+ _workloadInstaller.InstallWorkloads(workloadIds, _sdkFeatureBand, context, offlineCache);
+ });
+
+ WorkloadInstallCommand.TryRunGarbageCollection(_workloadInstaller, Reporter, Verbosity, workloadSetVersion => _workloadResolverFactory.CreateForWorkloadSet(_dotnetPath, _sdkVersion.ToString(), _userProfileDir, workloadSetVersion), offlineCache);
+
+ // TODO: potentially only do this in some cases (ie not if global.json specifies workload set)
+ _workloadManifestUpdater.DeleteUpdatableWorkloadsFile();
+
+ Reporter.WriteLine();
+ Reporter.WriteLine(string.Format(LocalizableStrings.UpdateSucceeded, string.Join(" ", workloadIds)));
+ Reporter.WriteLine();
}
catch (Exception e)
{
@@ -125,113 +124,6 @@ public override int Execute()
return _workloadInstaller.ExitCode;
}
- public void CalculateManifestUpdatesAndUpdateWorkloads(bool includePreviews = false, DirectoryPath? offlineCache = null)
- {
- Reporter.WriteLine();
-
- var useRollback = !string.IsNullOrWhiteSpace(_fromRollbackDefinition);
- var useWorkloadSets = ShouldUseWorkloadSetMode(_sdkFeatureBand, _dotnetPath);
-
- if (useRollback && useWorkloadSets)
- {
- // Rollback files are only for loose manifests. Update the mode to be loose manifests.
- Reporter.WriteLine(LocalizableStrings.UpdateFromRollbackSwitchesModeToLooseManifests);
- _workloadInstaller.UpdateInstallMode(_sdkFeatureBand, false);
- useWorkloadSets = false;
- }
-
- var workloadIds = GetUpdatableWorkloads();
- WriteSDKInstallRecordsForVSWorkloads(workloadIds);
- _workloadManifestUpdater.UpdateAdvertisingManifestsAsync(includePreviews, useWorkloadSets, offlineCache).Wait();
-
- IEnumerable manifestsToUpdate;
- RunInNewTransaction(context =>
- {
- if (useWorkloadSets)
- {
- if (!TryInstallWorkloadSet(context, out manifestsToUpdate))
- {
- return;
- }
- }
- else
- {
- manifestsToUpdate = useRollback ? _workloadManifestUpdater.CalculateManifestRollbacks(_fromRollbackDefinition) :
- _workloadManifestUpdater.CalculateManifestUpdates().Select(m => m.ManifestUpdate);
- }
-
- UpdateWorkloads(useRollback, manifestsToUpdate, offlineCache, context);
- });
-
- WorkloadInstallCommand.TryRunGarbageCollection(_workloadInstaller, Reporter, Verbosity, workloadSetVersion => _workloadResolverFactory.CreateForWorkloadSet(_dotnetPath, _sdkVersion.ToString(), _userProfileDir, workloadSetVersion), offlineCache);
-
- _workloadManifestUpdater.DeleteUpdatableWorkloadsFile();
-
- Reporter.WriteLine();
- Reporter.WriteLine(string.Format(LocalizableStrings.UpdateSucceeded, string.Join(" ", workloadIds)));
- Reporter.WriteLine();
- }
-
- private void UpdateWorkloads(bool useRollback, IEnumerable manifestsToUpdate, DirectoryPath? offlineCache, ITransactionContext context)
- {
- var workloadIds = GetUpdatableWorkloads();
-
- UpdateWorkloadsWithInstallRecord(_sdkFeatureBand, manifestsToUpdate, useRollback, context, offlineCache);
- }
-
- private void WriteSDKInstallRecordsForVSWorkloads(IEnumerable updateableWorkloads)
- {
-#if !DOT_NET_BUILD_FROM_SOURCE
- if (OperatingSystem.IsWindows())
- {
- VisualStudioWorkloads.WriteSDKInstallRecordsForVSWorkloads(_workloadInstaller, _workloadResolver, updateableWorkloads, Reporter);
- }
-#endif
- }
-
- private void UpdateWorkloadsWithInstallRecord(
- SdkFeatureBand sdkFeatureBand,
- IEnumerable manifestsToUpdate,
- bool useRollback,
- ITransactionContext context,
- DirectoryPath? offlineCache = null)
- {
- context.Run(
- action: () =>
- {
- foreach (var manifestUpdate in manifestsToUpdate)
- {
- _workloadInstaller.InstallWorkloadManifest(manifestUpdate, context, offlineCache, useRollback);
- }
-
- if (useRollback)
- {
- _workloadInstaller.SaveInstallStateManifestVersions(sdkFeatureBand, GetInstallStateContents(manifestsToUpdate));
- }
- else
- {
- _workloadInstaller.RemoveManifestsFromInstallState(sdkFeatureBand);
- }
-
- if (string.IsNullOrWhiteSpace(_workloadSetVersionFromGlobalJson))
- {
- _workloadInstaller.AdjustWorkloadSetInInstallState(sdkFeatureBand, string.IsNullOrWhiteSpace(_workloadSetVersion) ? null : _workloadSetVersion);
- }
-
- _workloadResolver.RefreshWorkloadManifests();
-
- var workloads = GetUpdatableWorkloads();
-
- _workloadInstaller.InstallWorkloads(workloads, sdkFeatureBand, context, offlineCache);
- },
- rollback: () =>
- {
- // Nothing to roll back at this level, InstallWorkloadManifest and InstallWorkloadPacks handle the transaction rollback
- // We will refresh the workload manifests to make sure that the resolver has the updated state after the rollback
- _workloadResolver.RefreshWorkloadManifests();
- });
- }
-
private async Task DownloadToOfflineCacheAsync(DirectoryPath offlineCache, bool includePreviews)
{
await GetDownloads(GetUpdatableWorkloads(), skipManifestUpdate: false, includePreviews, offlineCache.Value);
diff --git a/src/Cli/dotnet/commands/dotnet-workload/update/xlf/LocalizableStrings.cs.xlf b/src/Cli/dotnet/commands/dotnet-workload/update/xlf/LocalizableStrings.cs.xlf
index 4228a8117c0a..7a941608bc97 100644
--- a/src/Cli/dotnet/commands/dotnet-workload/update/xlf/LocalizableStrings.cs.xlf
+++ b/src/Cli/dotnet/commands/dotnet-workload/update/xlf/LocalizableStrings.cs.xlf
@@ -7,6 +7,11 @@
Aktualizujte jenom manifesty reklamy.
+
+ Cannot use the {0} and {1} options together.
+ Cannot use the {0} and {1} options together.
+
+ Update all installed workloads.Aktualizace všech nainstalovaných úloh.
diff --git a/src/Cli/dotnet/commands/dotnet-workload/update/xlf/LocalizableStrings.de.xlf b/src/Cli/dotnet/commands/dotnet-workload/update/xlf/LocalizableStrings.de.xlf
index e740d3b5fdda..5fdaa06d47c6 100644
--- a/src/Cli/dotnet/commands/dotnet-workload/update/xlf/LocalizableStrings.de.xlf
+++ b/src/Cli/dotnet/commands/dotnet-workload/update/xlf/LocalizableStrings.de.xlf
@@ -7,6 +7,11 @@
Aktualisieren Sie nur Werbemanifeste.
+
+ Cannot use the {0} and {1} options together.
+ Cannot use the {0} and {1} options together.
+
+ Update all installed workloads.Aktualisieren Sie alle installierten Workloads.
diff --git a/src/Cli/dotnet/commands/dotnet-workload/update/xlf/LocalizableStrings.es.xlf b/src/Cli/dotnet/commands/dotnet-workload/update/xlf/LocalizableStrings.es.xlf
index 5519d360b888..2e55fea4eda7 100644
--- a/src/Cli/dotnet/commands/dotnet-workload/update/xlf/LocalizableStrings.es.xlf
+++ b/src/Cli/dotnet/commands/dotnet-workload/update/xlf/LocalizableStrings.es.xlf
@@ -7,6 +7,11 @@
Actualizar solo los manifiestos de publicidad.
+
+ Cannot use the {0} and {1} options together.
+ Cannot use the {0} and {1} options together.
+
+ Update all installed workloads.Actualice todas las cargas de trabajo instaladas.
diff --git a/src/Cli/dotnet/commands/dotnet-workload/update/xlf/LocalizableStrings.fr.xlf b/src/Cli/dotnet/commands/dotnet-workload/update/xlf/LocalizableStrings.fr.xlf
index 0df26d1c4936..16cda2250592 100644
--- a/src/Cli/dotnet/commands/dotnet-workload/update/xlf/LocalizableStrings.fr.xlf
+++ b/src/Cli/dotnet/commands/dotnet-workload/update/xlf/LocalizableStrings.fr.xlf
@@ -7,6 +7,11 @@
Mettre à jour uniquement les manifestes de publicité
+
+ Cannot use the {0} and {1} options together.
+ Cannot use the {0} and {1} options together.
+
+ Update all installed workloads.Mettez à jour toutes les charges de travail installées.
diff --git a/src/Cli/dotnet/commands/dotnet-workload/update/xlf/LocalizableStrings.it.xlf b/src/Cli/dotnet/commands/dotnet-workload/update/xlf/LocalizableStrings.it.xlf
index f8a853bab73c..e1bc8b2b1a15 100644
--- a/src/Cli/dotnet/commands/dotnet-workload/update/xlf/LocalizableStrings.it.xlf
+++ b/src/Cli/dotnet/commands/dotnet-workload/update/xlf/LocalizableStrings.it.xlf
@@ -7,6 +7,11 @@
Aggiornare solo i manifesti pubblicitari.
+
+ Cannot use the {0} and {1} options together.
+ Cannot use the {0} and {1} options together.
+
+ Update all installed workloads.Aggiornare tutti i carichi di lavoro installati.
diff --git a/src/Cli/dotnet/commands/dotnet-workload/update/xlf/LocalizableStrings.ja.xlf b/src/Cli/dotnet/commands/dotnet-workload/update/xlf/LocalizableStrings.ja.xlf
index fdaf954d5f0d..52017d86e0f0 100644
--- a/src/Cli/dotnet/commands/dotnet-workload/update/xlf/LocalizableStrings.ja.xlf
+++ b/src/Cli/dotnet/commands/dotnet-workload/update/xlf/LocalizableStrings.ja.xlf
@@ -7,6 +7,11 @@
広告マニフェストのみを更新します。
+
+ Cannot use the {0} and {1} options together.
+ Cannot use the {0} and {1} options together.
+
+ Update all installed workloads.インストールされたすべてのワークロードを更新します。
diff --git a/src/Cli/dotnet/commands/dotnet-workload/update/xlf/LocalizableStrings.ko.xlf b/src/Cli/dotnet/commands/dotnet-workload/update/xlf/LocalizableStrings.ko.xlf
index 44bb501b1579..14dbe43d77b3 100644
--- a/src/Cli/dotnet/commands/dotnet-workload/update/xlf/LocalizableStrings.ko.xlf
+++ b/src/Cli/dotnet/commands/dotnet-workload/update/xlf/LocalizableStrings.ko.xlf
@@ -7,6 +7,11 @@
광고 매니페스트만 업데이트합니다.
+
+ Cannot use the {0} and {1} options together.
+ Cannot use the {0} and {1} options together.
+
+ Update all installed workloads.설치된 모든 워크로드를 업데이트합니다.
diff --git a/src/Cli/dotnet/commands/dotnet-workload/update/xlf/LocalizableStrings.pl.xlf b/src/Cli/dotnet/commands/dotnet-workload/update/xlf/LocalizableStrings.pl.xlf
index de69fac76dc2..c1afdb678235 100644
--- a/src/Cli/dotnet/commands/dotnet-workload/update/xlf/LocalizableStrings.pl.xlf
+++ b/src/Cli/dotnet/commands/dotnet-workload/update/xlf/LocalizableStrings.pl.xlf
@@ -7,6 +7,11 @@
Aktualizuj tylko manifesty reklam.
+
+ Cannot use the {0} and {1} options together.
+ Cannot use the {0} and {1} options together.
+
+ Update all installed workloads.Aktualizuj wszystkie zainstalowane obciążenia.
diff --git a/src/Cli/dotnet/commands/dotnet-workload/update/xlf/LocalizableStrings.pt-BR.xlf b/src/Cli/dotnet/commands/dotnet-workload/update/xlf/LocalizableStrings.pt-BR.xlf
index e3bdb7df5f71..65214c95a716 100644
--- a/src/Cli/dotnet/commands/dotnet-workload/update/xlf/LocalizableStrings.pt-BR.xlf
+++ b/src/Cli/dotnet/commands/dotnet-workload/update/xlf/LocalizableStrings.pt-BR.xlf
@@ -7,6 +7,11 @@
Atualizar somente manifestos de anúncio.
+
+ Cannot use the {0} and {1} options together.
+ Cannot use the {0} and {1} options together.
+
+ Update all installed workloads.Atualizar todas as cargas de trabalho instaladas.
diff --git a/src/Cli/dotnet/commands/dotnet-workload/update/xlf/LocalizableStrings.ru.xlf b/src/Cli/dotnet/commands/dotnet-workload/update/xlf/LocalizableStrings.ru.xlf
index 687aca812e9e..90cd22087b89 100644
--- a/src/Cli/dotnet/commands/dotnet-workload/update/xlf/LocalizableStrings.ru.xlf
+++ b/src/Cli/dotnet/commands/dotnet-workload/update/xlf/LocalizableStrings.ru.xlf
@@ -7,6 +7,11 @@
Обновляются только манифесты рекламы.
+
+ Cannot use the {0} and {1} options together.
+ Cannot use the {0} and {1} options together.
+
+ Update all installed workloads.Обновление всех установленных рабочих нагрузок.
diff --git a/src/Cli/dotnet/commands/dotnet-workload/update/xlf/LocalizableStrings.tr.xlf b/src/Cli/dotnet/commands/dotnet-workload/update/xlf/LocalizableStrings.tr.xlf
index 5ab2d025566b..5e06983f765d 100644
--- a/src/Cli/dotnet/commands/dotnet-workload/update/xlf/LocalizableStrings.tr.xlf
+++ b/src/Cli/dotnet/commands/dotnet-workload/update/xlf/LocalizableStrings.tr.xlf
@@ -7,6 +7,11 @@
Yalnızca reklam bildirimlerini güncelleştirin.
+
+ Cannot use the {0} and {1} options together.
+ Cannot use the {0} and {1} options together.
+
+ Update all installed workloads.Tüm yüklü iş yüklerini güncelleştirin.
diff --git a/src/Cli/dotnet/commands/dotnet-workload/update/xlf/LocalizableStrings.zh-Hans.xlf b/src/Cli/dotnet/commands/dotnet-workload/update/xlf/LocalizableStrings.zh-Hans.xlf
index 8e99dc9984ff..bea532aa56b1 100644
--- a/src/Cli/dotnet/commands/dotnet-workload/update/xlf/LocalizableStrings.zh-Hans.xlf
+++ b/src/Cli/dotnet/commands/dotnet-workload/update/xlf/LocalizableStrings.zh-Hans.xlf
@@ -7,6 +7,11 @@
仅更新广告清单。
+
+ Cannot use the {0} and {1} options together.
+ Cannot use the {0} and {1} options together.
+
+ Update all installed workloads.更新所有已安装的工作负载。
diff --git a/src/Cli/dotnet/commands/dotnet-workload/update/xlf/LocalizableStrings.zh-Hant.xlf b/src/Cli/dotnet/commands/dotnet-workload/update/xlf/LocalizableStrings.zh-Hant.xlf
index 9eef806d2028..6aeb8cff4d01 100644
--- a/src/Cli/dotnet/commands/dotnet-workload/update/xlf/LocalizableStrings.zh-Hant.xlf
+++ b/src/Cli/dotnet/commands/dotnet-workload/update/xlf/LocalizableStrings.zh-Hant.xlf
@@ -7,6 +7,11 @@
只更新廣告資訊清單。
+
+ Cannot use the {0} and {1} options together.
+ Cannot use the {0} and {1} options together.
+
+ Update all installed workloads.更新所有已安裝的工作負載。
diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/IWorkloadResolver.cs b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/IWorkloadResolver.cs
index 05a86f60d3b5..054aa1201798 100644
--- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/IWorkloadResolver.cs
+++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/IWorkloadResolver.cs
@@ -17,6 +17,7 @@ public interface IWorkloadResolver
IEnumerable GetAvailableWorkloads();
bool IsPlatformIncompatibleWorkload(WorkloadId workloadId);
string GetManifestVersion(string manifestId);
+ string GetManifestFeatureBand(string manifestId);
IEnumerable GetInstalledManifests();
string GetSdkFeatureBand();
string? GetWorkloadVersion();
diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/ManifestVersionUpdate.cs b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/ManifestVersionUpdate.cs
index 0d32c472c394..07119281d9a4 100644
--- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/ManifestVersionUpdate.cs
+++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/ManifestVersionUpdate.cs
@@ -3,45 +3,25 @@
namespace Microsoft.NET.Sdk.WorkloadManifestReader
{
+ // TODO: Do we need this class, or the existing version information anymore now that workload manifest are side by side?
public class ManifestVersionUpdate : IEquatable, IComparable
{
- public ManifestVersionUpdate(ManifestId manifestId, ManifestVersion? existingVersion, string? existingFeatureBand, ManifestVersion? newVersion, string? newFeatureBand)
+ public ManifestVersionUpdate(ManifestId manifestId, ManifestVersion? newVersion, string? newFeatureBand)
{
ManifestId = manifestId;
- ExistingVersion = existingVersion;
- ExistingFeatureBand = existingFeatureBand;
NewVersion = newVersion;
NewFeatureBand = newFeatureBand;
}
public ManifestId ManifestId { get; }
- public ManifestVersion? ExistingVersion { get; }
- public string? ExistingFeatureBand { get; }
public ManifestVersion? NewVersion { get; }
public string? NewFeatureBand { get; }
- // Returns an object representing an undo of this manifest update
- public ManifestVersionUpdate Reverse()
- {
- return new ManifestVersionUpdate(ManifestId, NewVersion, NewFeatureBand, ExistingVersion, ExistingFeatureBand);
- }
-
public int CompareTo(ManifestVersionUpdate? other)
{
if (other == null) return 1;
int ret = ManifestId.CompareTo(other.ManifestId);
if (ret != 0) return ret;
-
- if (ExistingVersion == null && other.ExistingVersion != null) return -1;
- if (ExistingVersion != null && other.ExistingVersion == null) return 1;
- if (ExistingVersion != null)
- {
- ret = ExistingVersion.CompareTo(other.ExistingVersion);
- if (ret != 0) return ret;
- }
-
- ret = string.Compare(ExistingFeatureBand, other.ExistingFeatureBand, StringComparison.Ordinal);
- if (ret != 0) return ret;
if (NewVersion == null && other.NewVersion != null) return -1;
if (NewVersion != null && other.NewVersion == null) return 1;
@@ -58,8 +38,6 @@ public bool Equals(ManifestVersionUpdate? other)
{
if (other == null) return false;
return EqualityComparer.Default.Equals(ManifestId, other.ManifestId) &&
- EqualityComparer.Default.Equals(ExistingVersion, other.ExistingVersion) &&
- string.Equals(ExistingFeatureBand, other.ExistingFeatureBand, StringComparison.Ordinal) &&
EqualityComparer.Default.Equals(NewVersion, other.NewVersion) &&
string.Equals(NewFeatureBand, other.NewFeatureBand, StringComparison.Ordinal);
}
@@ -72,12 +50,10 @@ public override bool Equals(object? obj)
public override int GetHashCode()
{
#if NETCOREAPP3_1_OR_GREATER
- return HashCode.Combine(ManifestId, ExistingVersion, ExistingFeatureBand, NewVersion, NewFeatureBand);
+ return HashCode.Combine(ManifestId, NewVersion, NewFeatureBand);
#else
int hashCode = 1601069575;
hashCode = hashCode * -1521134295 + ManifestId.GetHashCode();
- hashCode = hashCode * -1521134295 + EqualityComparer.Default.GetHashCode(ExistingVersion);
- hashCode = hashCode * -1521134295 + EqualityComparer.Default.GetHashCode(ExistingFeatureBand);
hashCode = hashCode * -1521134295 + EqualityComparer.Default.GetHashCode(NewVersion);
hashCode = hashCode * -1521134295 + EqualityComparer.Default.GetHashCode(NewFeatureBand);
return hashCode;
diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/SdkDirectoryWorkloadManifestProvider.cs b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/SdkDirectoryWorkloadManifestProvider.cs
index 167197fcf94d..f46af199399b 100644
--- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/SdkDirectoryWorkloadManifestProvider.cs
+++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/SdkDirectoryWorkloadManifestProvider.cs
@@ -122,12 +122,34 @@ public void RefreshWorkloadManifests()
_manifestsFromInstallState = null;
_installStateFilePath = null;
_useManifestsFromInstallState = true;
- var availableWorkloadSets = GetAvailableWorkloadSets();
+ var availableWorkloadSets = GetAvailableWorkloadSets(_sdkVersionBand);
+
+ bool TryGetWorkloadSet(string workloadSetVersion, out WorkloadSet? workloadSet)
+ {
+ if (availableWorkloadSets.TryGetValue(workloadSetVersion, out workloadSet))
+ {
+ return true;
+ }
+
+ // Check to see if workload set is from a different feature band
+ WorkloadSet.WorkloadSetVersionToWorkloadSetPackageVersion(workloadSetVersion, out SdkFeatureBand workloadSetFeatureBand);
+ if (!workloadSetFeatureBand.Equals(_sdkVersionBand))
+ {
+ var featureBandWorkloadSets = GetAvailableWorkloadSets(workloadSetFeatureBand);
+ if (featureBandWorkloadSets.TryGetValue(workloadSetVersion, out workloadSet))
+ {
+ return true;
+ }
+ }
+
+ workloadSet = null;
+ return false;
+ }
if (_workloadSetVersionFromConstructor != null)
{
_useManifestsFromInstallState = false;
- if (!availableWorkloadSets.TryGetValue(_workloadSetVersionFromConstructor, out _workloadSet))
+ if (!TryGetWorkloadSet(_workloadSetVersionFromConstructor, out _workloadSet))
{
throw new FileNotFoundException(string.Format(Strings.WorkloadVersionNotFound, _workloadSetVersionFromConstructor));
}
@@ -139,7 +161,7 @@ public void RefreshWorkloadManifests()
if (_globalJsonWorkloadSetVersion != null)
{
_useManifestsFromInstallState = false;
- if (!availableWorkloadSets.TryGetValue(_globalJsonWorkloadSetVersion, out _workloadSet))
+ if (!TryGetWorkloadSet(_globalJsonWorkloadSetVersion, out _workloadSet))
{
_exceptionToThrow = new FileNotFoundException(string.Format(Strings.WorkloadVersionFromGlobalJsonNotFound, _globalJsonWorkloadSetVersion, _globalJsonPathFromConstructor));
return;
@@ -155,7 +177,7 @@ public void RefreshWorkloadManifests()
var installState = InstallStateContents.FromPath(installStateFilePath);
if (!string.IsNullOrEmpty(installState.WorkloadVersion))
{
- if (!availableWorkloadSets.TryGetValue(installState.WorkloadVersion!, out _workloadSet))
+ if (!TryGetWorkloadSet(installState.WorkloadVersion!, out _workloadSet))
{
throw new FileNotFoundException(string.Format(Strings.WorkloadVersionFromInstallStateNotFound, installState.WorkloadVersion, installStateFilePath));
}
@@ -469,48 +491,53 @@ void ProbeDirectory(string manifestDirectory, string featureBand)
///
public Dictionary GetAvailableWorkloadSets()
{
+ return GetAvailableWorkloadSetsInternal(null);
+ }
+
+ public Dictionary GetAvailableWorkloadSets(SdkFeatureBand workloadSetFeatureBand)
+ {
+ return GetAvailableWorkloadSetsInternal(workloadSetFeatureBand);
+ }
+
+ Dictionary GetAvailableWorkloadSetsInternal(SdkFeatureBand? workloadSetFeatureBand)
+ {
+ // How to deal with cross-band workload sets?
Dictionary availableWorkloadSets = new Dictionary();
foreach (var manifestRoot in _manifestRoots.Reverse())
{
- // Workload sets must match the SDK feature band, we don't support any fallback to a previous band
- var workloadSetsRoot = Path.Combine(manifestRoot, _sdkVersionBand.ToString(), WorkloadSetsFolderName);
- if (Directory.Exists(workloadSetsRoot))
+ if (workloadSetFeatureBand != null)
{
- foreach (var workloadSetDirectory in Directory.GetDirectories(workloadSetsRoot))
+ // Get workload sets for specific feature band
+ var featureBandDirectory = Path.Combine(manifestRoot, workloadSetFeatureBand.Value.ToString());
+ AddWorkloadSetsForFeatureBand(availableWorkloadSets, featureBandDirectory);
+ }
+ else
+ {
+ // Get workload sets for all feature bands
+ foreach (var featureBandDirectory in Directory.GetDirectories(manifestRoot))
{
- WorkloadSet? workloadSet = null;
- foreach (var jsonFile in Directory.GetFiles(workloadSetDirectory, "*.workloadset.json"))
- {
- var newWorkloadSet = WorkloadSet.FromJson(File.ReadAllText(jsonFile), _sdkVersionBand);
- if (workloadSet == null)
- {
- workloadSet = newWorkloadSet;
- }
- else
- {
- // If there are multiple workloadset.json files, merge them
- foreach (var kvp in newWorkloadSet.ManifestVersions)
- {
- workloadSet.ManifestVersions.Add(kvp.Key, kvp.Value);
- }
- }
- }
- if (workloadSet != null)
- {
- if (File.Exists(Path.Combine(workloadSetDirectory, "baseline.workloadset.json")))
- {
- workloadSet.IsBaselineWorkloadSet = true;
- }
-
- workloadSet.Version = Path.GetFileName(workloadSetDirectory);
- availableWorkloadSets[workloadSet.Version] = workloadSet;
- }
+ AddWorkloadSetsForFeatureBand(availableWorkloadSets, featureBandDirectory);
}
}
}
return availableWorkloadSets;
+
+ static void AddWorkloadSetsForFeatureBand(Dictionary availableWorkloadSets, string featureBandDirectory)
+ {
+ var featureBand = new SdkFeatureBand(Path.GetFileName(featureBandDirectory));
+ var workloadSetsRoot = Path.Combine(featureBandDirectory, WorkloadSetsFolderName);
+ if (Directory.Exists(workloadSetsRoot))
+ {
+ foreach (var workloadSetDirectory in Directory.GetDirectories(workloadSetsRoot))
+ {
+ var workloadSetVersion = Path.GetFileName(workloadSetDirectory);
+ var workloadSet = WorkloadSet.FromWorkloadSetFolder(workloadSetDirectory, workloadSetVersion, featureBand);
+ availableWorkloadSets[workloadSet.Version!] = workloadSet;
+ }
+ }
+ }
}
public string GetSdkFeatureBand()
diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/Strings.resx b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/Strings.resx
index 2de51f6d77b2..cf418daa75cb 100644
--- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/Strings.resx
+++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/Strings.resx
@@ -210,4 +210,8 @@
Error parsing version '{1}' for workload manifest ID '{0}'
+
+ No manifest with ID {0} exists.
+
+
diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs
index 90a3137c9ded..6e02b99bc86a 100644
--- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs
+++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs
@@ -749,9 +749,21 @@ public string GetManifestVersion(string manifestId)
InitializeManifests();
if (_manifests.TryGetValue(manifestId, out var value))
{
- return value.manifest.Version;
+ return value.info.Version;
}
- throw new Exception($"Manifest with id {manifestId} does not exist.");
+
+ throw new Exception(string.Format(Strings.ManifestDoesNotExist, manifestId));
+ }
+
+ public string GetManifestFeatureBand(string manifestId)
+ {
+ InitializeManifests();
+ if (_manifests.TryGetValue(manifestId, out var value))
+ {
+ return value.info.ManifestFeatureBand;
+ }
+
+ throw new Exception(string.Format(Strings.ManifestDoesNotExist, manifestId));
}
public IEnumerable GetInstalledManifests()
diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadSet.cs b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadSet.cs
index 09e8ad4cfffa..eecb89c38f06 100644
--- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadSet.cs
+++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadSet.cs
@@ -81,6 +81,45 @@ public static WorkloadSet FromJson(string json, SdkFeatureBand defaultFeatureBan
#endif
}
+ public static WorkloadSet FromWorkloadSetFolder(string path, string workloadSetVersion, SdkFeatureBand defaultFeatureBand)
+ {
+ WorkloadSet? workloadSet = null;
+ foreach (var jsonFile in Directory.GetFiles(path, "*.workloadset.json"))
+ {
+ var newWorkloadSet = WorkloadSet.FromJson(File.ReadAllText(jsonFile), defaultFeatureBand);
+ if (workloadSet == null)
+ {
+ workloadSet = newWorkloadSet;
+ }
+ else
+ {
+ // If there are multiple workloadset.json files, merge them
+ foreach (var kvp in newWorkloadSet.ManifestVersions)
+ {
+ if (workloadSet.ManifestVersions.ContainsKey(kvp.Key))
+ {
+ throw new InvalidOperationException($"Workload set files in {path} defined the same manifest ({kvp.Key}) multiple times");
+ }
+ workloadSet.ManifestVersions.Add(kvp.Key, kvp.Value);
+ }
+ }
+ }
+
+ if (workloadSet == null)
+ {
+ throw new InvalidOperationException("No workload set information found in: " + path);
+ }
+
+ if (File.Exists(Path.Combine(path, "baseline.workloadset.json")))
+ {
+ workloadSet.IsBaselineWorkloadSet = true;
+ }
+
+ workloadSet.Version = workloadSetVersion;
+
+ return workloadSet;
+ }
+
public Dictionary ToDictionaryForJson()
{
var dictionary = ManifestVersions.ToDictionary(kvp => kvp.Key.ToString(), kvp => kvp.Value.Version + "/" + kvp.Value.FeatureBand, StringComparer.OrdinalIgnoreCase);
@@ -97,5 +136,45 @@ public string ToJson()
return json;
}
+ // Corresponding method for opposite direction is in WorkloadManifestUpdater, as its implementation depends on NuGetVersion,
+ // which we'd like to avoid adding as a dependency here.
+ public static string WorkloadSetVersionToWorkloadSetPackageVersion(string setVersion, out SdkFeatureBand sdkFeatureBand)
+ {
+ string[] sections = setVersion.Split(new char[] { '-', '+' }, 2);
+ string versionCore = sections[0];
+ string? preReleaseOrBuild = sections.Length > 1 ? sections[1] : null;
+
+ string[] coreComponents = versionCore.Split('.');
+ string major = coreComponents[0];
+ string minor = coreComponents[1];
+ string patch = coreComponents[2];
+
+ string packageVersion = $"{major}.{patch}.";
+ if (coreComponents.Length == 3)
+ {
+ // No workload set patch version
+ packageVersion += "0";
+
+ // Use preview specifier (if any) from workload set version as part of SDK feature band
+ sdkFeatureBand = new SdkFeatureBand(setVersion);
+ }
+ else
+ {
+ // Workload set version has workload patch version (ie 4 components)
+ packageVersion += coreComponents[3];
+
+ // Don't include any preview specifiers in SDK feature band
+ sdkFeatureBand = new SdkFeatureBand($"{major}.{minor}.{patch}");
+ }
+
+ if (preReleaseOrBuild != null)
+ {
+ // Figure out if we split on a '-' or '+'
+ char separator = setVersion[sections[0].Length];
+ packageVersion += separator + preReleaseOrBuild;
+ }
+
+ return packageVersion;
+ }
}
}
diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.cs.xlf b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.cs.xlf
index 19a075d8d93c..4407d1e29043 100644
--- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.cs.xlf
+++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.cs.xlf
@@ -77,6 +77,11 @@
Závislost manifestu úlohy {0} verze {1} je nižší než verze {2} požadovaná manifestem {3} [{4}].
+
+ No manifest with ID {0} exists.
+ No manifest with ID {0} exists.
+
+ Workload manifest {0}, which was specified in {1}, was not found. Running "dotnet workload repair" may resolve this.Manifest úlohy {0}, který byl určen v {1}, nebyl nalezen. Tento problém může vyřešit spuštění „dotnet workload repair“.
diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.de.xlf b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.de.xlf
index 90025005a6fb..4ef614824da0 100644
--- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.de.xlf
+++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.de.xlf
@@ -77,6 +77,11 @@
Die Workloadmanifestabhängigkeit „{0}“, Version „{1}“, ist niedriger als die Version „{2}“, die vom Manifest „{3}“ [{4}] benötigt wird.
+
+ No manifest with ID {0} exists.
+ No manifest with ID {0} exists.
+
+ Workload manifest {0}, which was specified in {1}, was not found. Running "dotnet workload repair" may resolve this.Das Arbeitsauslastungsmanifest {0}, das in {1} angegeben wurde, wurde nicht gefunden. Die Ausführung von "dotnet workload repair" kann dies beheben.
diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.es.xlf b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.es.xlf
index 458cb48dabf2..965f78c7a674 100644
--- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.es.xlf
+++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.es.xlf
@@ -77,6 +77,11 @@
La dependencia del manifiesto de carga de trabajo '{0}' versión '{1}' es inferior a la versión '{2}' requerida por el manifiesto '{3}' [{4}]
+
+ No manifest with ID {0} exists.
+ No manifest with ID {0} exists.
+
+ Workload manifest {0}, which was specified in {1}, was not found. Running "dotnet workload repair" may resolve this.No se ha encontrado el manifiesto de carga de trabajo {0}, que se especificó en {1}. La ejecución de "dotnet workload repair" puede resolverlo.
diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.fr.xlf b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.fr.xlf
index a5c39b99ca26..86ea8311cbd8 100644
--- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.fr.xlf
+++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.fr.xlf
@@ -77,6 +77,11 @@
La version {0}' de la dépendance du manifeste de charge de travail est inférieure à la version '{1}' requise par {2}le manifeste '{3}' [{4}].
+
+ No manifest with ID {0} exists.
+ No manifest with ID {0} exists.
+
+ Workload manifest {0}, which was specified in {1}, was not found. Running "dotnet workload repair" may resolve this.Le manifeste de charge de travail {0}, spécifié dans {1}, est introuvable. L’exécution "dotnet workload repair" pourrait résoudre ce problème.
diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.it.xlf b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.it.xlf
index daca70889d58..7bab4f663335 100644
--- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.it.xlf
+++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.it.xlf
@@ -77,6 +77,11 @@
La dipendenza del manifesto del carico di lavoro '{0}' versione '{1}' è inferiore alla versione '{2}' richiesta dal manifesto '{3}' [{4}]
+
+ No manifest with ID {0} exists.
+ No manifest with ID {0} exists.
+
+ Workload manifest {0}, which was specified in {1}, was not found. Running "dotnet workload repair" may resolve this.Il manifesto del carico di lavoro {0}, specificato in {1}, non è stato trovato. L'esecuzione della "dotnet workload repair" può risolvere questo errore.
diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.ja.xlf b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.ja.xlf
index f8f51cb5cd20..7a8e0cf5bd18 100644
--- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.ja.xlf
+++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.ja.xlf
@@ -77,6 +77,11 @@
ワークロード マニフェストの依存関係 '{0}' のバージョン '{1}' は、マニフェスト '{3}' [{4}] で必要とされるバージョン '{2}' 以前のものです
+
+ No manifest with ID {0} exists.
+ No manifest with ID {0} exists.
+
+ Workload manifest {0}, which was specified in {1}, was not found. Running "dotnet workload repair" may resolve this.{1} で指定されたワークロード マニフェスト {0} が見つかりませんでした。"dotnet workload repair" を実行すると、これを解決できる場合があります。
diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.ko.xlf b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.ko.xlf
index 2ad7384a142a..ece3a585d49f 100644
--- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.ko.xlf
+++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.ko.xlf
@@ -77,6 +77,11 @@
워크로드 매니페스트 종속성 '{0}' 버전 '{1}'이(가) '{3}' [{4}]에 필요한 버전 '{2}'보다 낮습니다
+
+ No manifest with ID {0} exists.
+ No manifest with ID {0} exists.
+
+ Workload manifest {0}, which was specified in {1}, was not found. Running "dotnet workload repair" may resolve this.{1}에 지정된 워크로드 매니페스트 {0}을(를) 찾을 수 없습니다. "dotnet workload repair"를 실행하면 이 문제를 해결할 수 있습니다.
diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.pl.xlf b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.pl.xlf
index 66b2aa84d20c..4d426d6393bb 100644
--- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.pl.xlf
+++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.pl.xlf
@@ -77,6 +77,11 @@
Zależność manifestu obciążenia „{0}” w wersji „{1}” jest niższa niż w wersji "{2}" wymaganej przez manifest „{3}”[{4}]
+
+ No manifest with ID {0} exists.
+ No manifest with ID {0} exists.
+
+ Workload manifest {0}, which was specified in {1}, was not found. Running "dotnet workload repair" may resolve this.Nie znaleziono manifestu obciążenia {0}, który został określony w: {1}. Uruchomienie polecenia "dotnet workload repair" może rozwiązać ten problem.
diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.pt-BR.xlf b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.pt-BR.xlf
index f7b78be143fa..006a94cd72fa 100644
--- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.pt-BR.xlf
+++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.pt-BR.xlf
@@ -77,6 +77,11 @@
A dependência do manifesto de carga de trabalho '{0}' versão '{1}' é inferior à versão '{2}' exigida pelo manifesto '{3}' [{4}]
+
+ No manifest with ID {0} exists.
+ No manifest with ID {0} exists.
+
+ Workload manifest {0}, which was specified in {1}, was not found. Running "dotnet workload repair" may resolve this.O manifesto {0} de carga de trabalho, que foi especificado em {1}, não foi encontrado. Executar "dotnet workload repair" pode resolver isso.
diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.ru.xlf b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.ru.xlf
index 432d9b719fda..c99667294093 100644
--- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.ru.xlf
+++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.ru.xlf
@@ -77,6 +77,11 @@
Зависимость манифеста рабочей нагрузки "{0}" версии "{1}" ниже версии "{2}", необходимой для манифеста "{3}" [{4}]
+
+ No manifest with ID {0} exists.
+ No manifest with ID {0} exists.
+
+ Workload manifest {0}, which was specified in {1}, was not found. Running "dotnet workload repair" may resolve this.Не найден манифест рабочей нагрузки {0}, указанный в {1}. Выполнение команды "dotnet workload repair" может устранить эту проблему.
diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.tr.xlf b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.tr.xlf
index 71645cb83845..c8522d74ad06 100644
--- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.tr.xlf
+++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.tr.xlf
@@ -77,6 +77,11 @@
'{0}' iş yükü bildirimi bağımlılığının '{1}' sürümü, '{3}' [{4}] bildirimi için gereken '{2}' sürümünden düşük
+
+ No manifest with ID {0} exists.
+ No manifest with ID {0} exists.
+
+ Workload manifest {0}, which was specified in {1}, was not found. Running "dotnet workload repair" may resolve this.{1} içinde belirtilen iş yükü bildirimi {0} bulunamadı. Çalışan "dotnet workload repair" bu sorunu çözebilir.
diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.zh-Hans.xlf b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.zh-Hans.xlf
index ee0c5fc194b6..0aefce1fe3ef 100644
--- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.zh-Hans.xlf
+++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.zh-Hans.xlf
@@ -77,6 +77,11 @@
工作负荷清单依赖项“{0}”版本“{1}”低于清单“{2}”所需的版本“{3}”[{4}]
+
+ No manifest with ID {0} exists.
+ No manifest with ID {0} exists.
+
+ Workload manifest {0}, which was specified in {1}, was not found. Running "dotnet workload repair" may resolve this.找不到 {1} 中指定的工作负载清单 {0}。运行 "dotnet workload repair" 可能会解决此问题。
diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.zh-Hant.xlf b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.zh-Hant.xlf
index abbd8fbbb106..e34619e9f3f4 100644
--- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.zh-Hant.xlf
+++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.zh-Hant.xlf
@@ -77,6 +77,11 @@
工作負載資訊清單相依性 '{0}' 版本 ' {1} ' 低於資訊清單 '{3}' [{4}] 所需的版本 '{2}'
+
+ No manifest with ID {0} exists.
+ No manifest with ID {0} exists.
+
+ Workload manifest {0}, which was specified in {1}, was not found. Running "dotnet workload repair" may resolve this.找不到 {1} 中指定的工作負載資訊清單 {0}。執行 "dotnet workload repair" 可能會解決這個問題。
diff --git a/src/Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests/SdkDirectoryWorkloadManifestProviderTests.cs b/src/Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests/SdkDirectoryWorkloadManifestProviderTests.cs
index 3316a7d0a3ea..081d8c260a61 100644
--- a/src/Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests/SdkDirectoryWorkloadManifestProviderTests.cs
+++ b/src/Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests/SdkDirectoryWorkloadManifestProviderTests.cs
@@ -468,7 +468,7 @@ public void ItThrowsExceptionIfWorkloadSetJsonFilesHaveDuplicateManifests()
}
""");
- Assert.Throws(() =>
+ Assert.Throws(() =>
new SdkDirectoryWorkloadManifestProvider(sdkRootPath: _fakeDotnetRootDirectory, sdkVersion: "8.0.200", userProfileDir: null, globalJsonPath: null));
}
diff --git a/src/Tests/dotnet-MsiInstallation.Tests/Framework/VMControl.cs b/src/Tests/dotnet-MsiInstallation.Tests/Framework/VMControl.cs
index b619124f24e8..a7dfc17b9438 100644
--- a/src/Tests/dotnet-MsiInstallation.Tests/Framework/VMControl.cs
+++ b/src/Tests/dotnet-MsiInstallation.Tests/Framework/VMControl.cs
@@ -94,7 +94,8 @@ public CommandResult RunCommandOnVM(string[] args, string workingDirectory = nul
private IEnumerable GetSnapshotInstances()
{
- var snapshots = _session.QueryInstances(virtNamespace, "WQL", $"SELECT * FROM Msvm_VirtualSystemSettingData WHERE VirtualSystemIdentifier='{VMInstance.CimInstanceProperties["Name"].Value}' And IsSaved='True'").ToList();
+ // Note: Not querying for IsSaved='True' here, as this value was false for snapshots in at least one case
+ var snapshots = _session.QueryInstances(virtNamespace, "WQL", $"SELECT * FROM Msvm_VirtualSystemSettingData WHERE VirtualSystemIdentifier='{VMInstance.CimInstanceProperties["Name"].Value}'").ToList();
return snapshots;
}
diff --git a/src/Tests/dotnet-MsiInstallation.Tests/Framework/VMStateTree.cs b/src/Tests/dotnet-MsiInstallation.Tests/Framework/VMStateTree.cs
index ca5d69017f64..7e683a67c5c1 100644
--- a/src/Tests/dotnet-MsiInstallation.Tests/Framework/VMStateTree.cs
+++ b/src/Tests/dotnet-MsiInstallation.Tests/Framework/VMStateTree.cs
@@ -103,7 +103,7 @@ internal class SerializableVMState
{
public string DefaultRootState { get; set; }
- public List VMStates { get; set; }
+ public List VMStates { get; set; } = new();
public VMState ToVMState()
{
diff --git a/src/Tests/dotnet-MsiInstallation.Tests/Framework/VMTestBase.cs b/src/Tests/dotnet-MsiInstallation.Tests/Framework/VMTestBase.cs
index 87b4b13a8577..91f49bce6520 100644
--- a/src/Tests/dotnet-MsiInstallation.Tests/Framework/VMTestBase.cs
+++ b/src/Tests/dotnet-MsiInstallation.Tests/Framework/VMTestBase.cs
@@ -157,9 +157,15 @@ protected string GetInstalledSdkVersion()
return result.StdOut;
}
- protected CommandResult InstallWorkload(string workloadName)
+ protected CommandResult InstallWorkload(string workloadName, bool skipManifestUpdate)
{
- var result = VM.CreateRunCommand("dotnet", "workload", "install", workloadName, "--skip-manifest-update")
+ string [] args = { "dotnet", "workload", "install", workloadName};
+ if (skipManifestUpdate)
+ {
+ args = [.. args, "--skip-manifest-update"];
+ }
+
+ var result = VM.CreateRunCommand(args)
.WithDescription($"Install {workloadName} workload")
.Execute();
diff --git a/src/Tests/dotnet-MsiInstallation.Tests/Framework/VirtualMachine.cs b/src/Tests/dotnet-MsiInstallation.Tests/Framework/VirtualMachine.cs
index 844a1802e7d7..d22de7ecce86 100644
--- a/src/Tests/dotnet-MsiInstallation.Tests/Framework/VirtualMachine.cs
+++ b/src/Tests/dotnet-MsiInstallation.Tests/Framework/VirtualMachine.cs
@@ -360,7 +360,9 @@ VMActionResult Run(SerializedVMAction action)
{
var targetSharePath = VMPathToSharePath(action.TargetPath);
- CopyDirectory(action.SourcePath, targetSharePath);
+ var result = new RunExeCommand(Log, "robocopy", action.SourcePath, targetSharePath, "/mir")
+ .Execute()
+ .ExitCode.Should().BeLessThan(8); // Robocopy error exit codes are 8 or higher
return VMActionResult.Success();
}
@@ -471,24 +473,6 @@ void ProcessDirectory(DirectoryInfo dir, string relativeTo)
return sb.ToString();
}
- static void CopyDirectory(string sourcePath, string destPath)
- {
- if (!Directory.Exists(destPath))
- {
- Directory.CreateDirectory(destPath);
- }
-
- foreach (var dir in Directory.GetDirectories(sourcePath))
- {
- CopyDirectory(dir, Path.Combine(destPath, Path.GetFileName(dir)));
- }
-
- foreach (var file in Directory.GetFiles(sourcePath))
- {
- new FileInfo(file).CopyTo(Path.Combine(destPath, Path.GetFileName(file)), true);
- }
- }
-
string VMPathToSharePath(string vmPath)
{
var dirInfo = new DirectoryInfo(vmPath);
diff --git a/src/Tests/dotnet-MsiInstallation.Tests/MsiInstallerTests.cs b/src/Tests/dotnet-MsiInstallation.Tests/MsiInstallerTests.cs
index 2b4129f6db41..c557ba6ed856 100644
--- a/src/Tests/dotnet-MsiInstallation.Tests/MsiInstallerTests.cs
+++ b/src/Tests/dotnet-MsiInstallation.Tests/MsiInstallerTests.cs
@@ -75,7 +75,7 @@ public void InstallWasm()
ApplyRC1Manifests();
- InstallWorkload("wasm-tools");
+ InstallWorkload("wasm-tools", skipManifestUpdate: true);
}
[Fact]
@@ -85,7 +85,7 @@ public void InstallAndroid()
ApplyRC1Manifests();
- InstallWorkload("android");
+ InstallWorkload("android", skipManifestUpdate: true);
}
[Fact]
@@ -95,9 +95,9 @@ public void InstallAndroidAndWasm()
ApplyRC1Manifests();
- InstallWorkload("android");
+ InstallWorkload("android", skipManifestUpdate: true);
- InstallWorkload("wasm-tools");
+ InstallWorkload("wasm-tools", skipManifestUpdate: true);
}
[Fact]
@@ -151,7 +151,7 @@ public void WorkloadInstallationAndGarbageCollection()
var originalManifests = GetRollback();
- InstallWorkload("wasm-tools");
+ InstallWorkload("wasm-tools", skipManifestUpdate: true);
ListWorkloads().Should().Contain("wasm-tools");
@@ -182,7 +182,7 @@ public void WorkloadInstallationAndGarbageCollection()
public void InstallStateShouldBeRemovedOnSdkUninstall()
{
InstallSdk();
- InstallWorkload("wasm-tools");
+ InstallWorkload("wasm-tools", skipManifestUpdate: true);
ApplyRC1Manifests();
var featureBand = new SdkFeatureBand(SdkInstallerVersion);
var installStatePath = $@"c:\ProgramData\dotnet\workloads\x64\{featureBand}\InstallState\default.json";
@@ -195,7 +195,7 @@ public void InstallStateShouldBeRemovedOnSdkUninstall()
public void UpdateWithRollback()
{
InstallSdk();
- InstallWorkload("wasm-tools");
+ InstallWorkload("wasm-tools", skipManifestUpdate: true);
ApplyRC1Manifests();
TestWasmWorkload();
@@ -227,7 +227,7 @@ public void InstallShouldNotUpdatePinnedRollback()
ApplyRC1Manifests();
var workloadVersion = GetWorkloadVersion();
- InstallWorkload("aspire");
+ InstallWorkload("aspire", skipManifestUpdate: false);
GetWorkloadVersion().Should().Be(workloadVersion);
}
@@ -259,6 +259,26 @@ public void ApplyRollbackShouldNotUpdateAdvertisingManifests()
throw new NotImplementedException();
}
+ [Fact]
+ public void TestAspire()
+ {
+ InstallSdk();
+
+ //AddNuGetSource("https://pkgs.dev.azure.com/dnceng/internal/_packaging/8.0.300-rtm.24224.15-shipping/nuget/v3/index.json");
+ //AddNuGetSource("https://pkgs.dev.azure.com/dnceng/public/_packaging/darc-pub-dotnet-aspire-d215c528/nuget/v3/index.json");
+
+ //VM.CreateRunCommand("powershell", "-Command", "& { $(irm https://aka.ms/install-artifacts-credprovider.ps1) }")
+ // .Execute().Should().Pass();
+
+ InstallWorkload("aspire", skipManifestUpdate: true);
+
+ VM.CreateRunCommand("dotnet", "new", "aspire-starter", "-o", "Aspire-StarterApp01")
+ .WithWorkingDirectory(@"c:\SdkTesting")
+ .Execute()
+ .Should()
+ .Pass();
+ }
+
void TestWasmWorkload()
{
diff --git a/src/Tests/dotnet-MsiInstallation.Tests/WorkloadSetTests.cs b/src/Tests/dotnet-MsiInstallation.Tests/WorkloadSetTests.cs
index e7157a0b7da5..e580c8ad4d0f 100644
--- a/src/Tests/dotnet-MsiInstallation.Tests/WorkloadSetTests.cs
+++ b/src/Tests/dotnet-MsiInstallation.Tests/WorkloadSetTests.cs
@@ -3,16 +3,20 @@
using System;
using System.Collections.Generic;
+using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.DotNet.MsiInstallerTests.Framework;
using Microsoft.NET.Sdk.WorkloadManifestReader;
+using Microsoft.TemplateEngine.Abstractions.Mount;
namespace Microsoft.DotNet.MsiInstallerTests
{
public class WorkloadSetTests : VMTestBase
{
+ readonly string SdkTestingDirectory = @"C:\SdkTesting";
+
public WorkloadSetTests(ITestOutputHelper log) : base(log)
{
}
@@ -81,9 +85,7 @@ public void UpdateWithWorkloadSets()
AddNuGetSource(@"c:\SdkTesting\WorkloadSets");
VM.CreateRunCommand("dotnet", "workload", "update")
- .Execute()
- .Should()
- .Pass();
+ .Execute().Should().Pass();
var newRollback = GetRollback();
@@ -137,9 +139,16 @@ public void UpdateToSpecificWorkloadSetVersion(string versionToInstall)
GetWorkloadVersion().Should().Be(versionToInstall);
// Installing a workload shouldn't update workload version
- InstallWorkload("aspire");
+ InstallWorkload("aspire", skipManifestUpdate: false);
GetWorkloadVersion().Should().Be(versionToInstall);
+
+ VM.CreateRunCommand("dotnet", "workload", "update")
+ .Execute()
+ .Should()
+ .Pass();
+
+ GetWorkloadVersion().Should().Be("8.0.300-preview.0.24217.2");
}
[Fact]
@@ -155,8 +164,8 @@ public void UpdateToUnavailableWorkloadSetVersion()
.Execute()
.Should()
.Fail()
- .And
- .HaveStdErrContaining(unavailableWorkloadSetVersion);
+ .And.HaveStdErrContaining(unavailableWorkloadSetVersion)
+ .And.NotHaveStdOutContaining("Installation rollback failed");
VM.CreateRunCommand("dotnet", "workload", "search")
.WithIsReadOnly(true)
@@ -180,8 +189,8 @@ public void UpdateWorkloadSetWithoutAvailableManifests()
VM.CreateRunCommand("dotnet", "workload", "update", "--source", @"c:\SdkTesting\workloadsets")
.Execute()
.Should()
- .Fail();
-
+ .Pass()
+ .And.HaveStdOutContaining("No workload update found");
VM.CreateRunCommand("dotnet", "workload", "search")
.WithIsReadOnly(true)
@@ -213,25 +222,23 @@ public void UpdateToWorkloadSetVersionWithManifestsNotAvailable()
GetWorkloadVersion().Should().Be(workloadVersionBeforeUpdate);
}
- [Fact]
- public void UpdateWorkloadSetViaGlobalJson()
+ void SetupWorkloadSetInGlobalJson(out WorkloadSet originalRollback)
{
InstallSdk();
var versionToUpdateTo = "8.0.300-preview.0.24217.2";
- var directory = "C:\\SdkTesting";
string originalVersion = GetWorkloadVersion();
- var rollback = GetRollback(directory);
+ originalRollback = GetRollback(SdkTestingDirectory);
VM.WriteFile("C:\\SdkTesting\\global.json", @$"{{""sdk"":{{""workloadVersion"":""{versionToUpdateTo}""}}}}").Execute().Should().Pass();
- GetWorkloadVersion(directory).Should().Be(versionToUpdateTo);
+ GetWorkloadVersion(SdkTestingDirectory).Should().Be(versionToUpdateTo);
// The version should have changed but not yet the manifests. Since we expect both, getting the rollback should fail.
var result = VM.CreateRunCommand("dotnet", "workload", "update", "--print-rollback")
- .WithWorkingDirectory(directory)
+ .WithWorkingDirectory(SdkTestingDirectory)
.WithIsReadOnly(true)
.Execute();
@@ -239,11 +246,139 @@ public void UpdateWorkloadSetViaGlobalJson()
result.StdErr.Should().Contain("FileNotFoundException");
result.StdErr.Should().Contain(versionToUpdateTo);
- AddNuGetSource(@"C:\SdkTesting\workloadsets", directory);
+ AddNuGetSource(@"C:\SdkTesting\workloadsets", SdkTestingDirectory);
+ }
+
+ [Fact]
+ public void UpdateWorkloadSetViaGlobalJson()
+ {
+ SetupWorkloadSetInGlobalJson(out var originalRollback);
+
+ VM.CreateRunCommand("dotnet", "workload", "update").WithWorkingDirectory(SdkTestingDirectory).Execute().Should().Pass();
+ GetRollback(SdkTestingDirectory).Should().NotBe(originalRollback);
+ }
+
+ [Fact]
+ public void InstallWorkloadSetViaGlobalJson()
+ {
+ SetupWorkloadSetInGlobalJson(out var originalRollback);
+
+ VM.CreateRunCommand("dotnet", "workload", "install", "aspire")
+ .WithWorkingDirectory(SdkTestingDirectory)
+ .Execute().Should().Pass();
+
+ GetRollback(SdkTestingDirectory).Should().NotBe(originalRollback);
+ }
+
+ [Fact]
+ public void InstallWithGlobalJsonAndSkipManifestUpdate()
+ {
+ SetupWorkloadSetInGlobalJson(out var originalRollback);
+
+ VM.CreateRunCommand("dotnet", "workload", "install", "aspire", "--skip-manifest-update")
+ .WithWorkingDirectory(SdkTestingDirectory)
+ .Execute().Should().Fail()
+ .And.HaveStdErrContaining("--skip-manifest-update")
+ .And.HaveStdErrContaining(Path.Combine(SdkTestingDirectory, "global.json"));
+ }
- VM.CreateRunCommand("dotnet", "workload", "update").WithWorkingDirectory(directory).Execute().Should().Pass();
+ [Fact]
+ public void InstallWithVersionAndSkipManifestUpdate()
+ {
+ InstallSdk();
- GetRollback(directory).Should().NotBe(rollback);
+ VM.CreateRunCommand("dotnet", "workload", "install", "aspire", "--skip-manifest-update", "--version", "8.0.300-preview.0.24178.1")
+ .Execute().Should().Fail()
+ .And.HaveStdErrContaining("--skip-manifest-update")
+ .And.HaveStdErrContaining("--sdk-version");
+ }
+
+ [Fact]
+ public void InstallWithVersionWhenPinned()
+ {
+ InstallSdk();
+
+ AddNuGetSource(@"c:\SdkTesting\WorkloadSets");
+
+ string originalVersion = GetWorkloadVersion();
+ originalVersion.Should().NotBe("8.0.300-preview.0.24178.1");
+
+ VM.CreateRunCommand("dotnet", "workload", "update", "--version", "8.0.300-preview.0.24178.1")
+ .Execute().Should().Pass();
+
+ GetWorkloadVersion().Should().Be("8.0.300-preview.0.24178.1");
+
+ VM.CreateRunCommand("dotnet", "workload", "install", "aspire", "--version", "8.0.300-preview.0.24217.2")
+ .Execute().Should().Pass();
+
+ GetWorkloadVersion().Should().Be("8.0.300-preview.0.24217.2");
+ }
+
+ [Fact]
+ public void InstallWithGlobalJsonWhenPinned()
+ {
+ SetupWorkloadSetInGlobalJson(out var originalRollback);
+
+ //AddNuGetSource(@"c:\SdkTesting\WorkloadSets");
+
+ string originalVersion = GetWorkloadVersion();
+ originalVersion.Should().NotBe("8.0.300-preview.0.24178.1");
+
+ VM.CreateRunCommand("dotnet", "workload", "update", "--version", "8.0.300-preview.0.24178.1")
+ .Execute().Should().Pass();
+
+ GetWorkloadVersion().Should().Be("8.0.300-preview.0.24178.1");
+
+ VM.CreateRunCommand("dotnet", "workload", "install", "aspire")
+ .WithWorkingDirectory(SdkTestingDirectory)
+ .Execute().Should().Pass();
+
+ GetWorkloadVersion(SdkTestingDirectory).Should().Be("8.0.300-preview.0.24217.2");
+
+ GetRollback(SdkTestingDirectory).Should().NotBe(originalRollback);
+
+ }
+
+ [Fact]
+ public void UpdateShouldNotPinWorkloadSet()
+ {
+ InstallSdk();
+ UpdateAndSwitchToWorkloadSetMode(out _, out _);
+
+ AddNuGetSource(@"c:\SdkTesting\WorkloadSets");
+
+ // Rename latest workload set so it won't be installed
+ VM.CreateRunCommand("cmd", "/c", "ren", @$"c:\SdkTesting\WorkloadSets\Microsoft.NET.Workloads.8.0.300-preview.*.24217.2.nupkg", $"Microsoft.NET.Workloads.8.0.300-preview.*.24217.2.bak")
+ .Execute().Should().Pass();
+
+ VM.CreateRunCommand("dotnet", "workload", "update")
+ .Execute().Should().Pass();
+
+ GetWorkloadVersion().Should().Be("8.0.300-preview.0.24178.1");
+
+ // Bring latest workload set version back, so installing workload should update to it
+ VM.CreateRunCommand("cmd", "/c", "ren", @$"c:\SdkTesting\WorkloadSets\Microsoft.NET.Workloads.8.0.300-preview.*.24217.2.bak", $"Microsoft.NET.Workloads.8.0.300-preview.*.24217.2.nupkg")
+ .Execute().Should().Pass();
+
+ InstallWorkload("aspire", skipManifestUpdate: false);
+
+ GetWorkloadVersion().Should().Be("8.0.300-preview.0.24217.2");
+ }
+
+ [Fact]
+ public void WorkloadSetInstallationRecordIsWrittenCorrectly()
+ {
+ // Should the workload set version or the package version be used in the registry?
+ throw new NotImplementedException();
+ }
+
+ [Fact]
+ public void TurnOffWorkloadSetUpdateMode()
+ {
+ // If you have a workload set installed and then turn off workload set update mode, what should happen?
+ // - Update should update individual manifests
+ // - Resolver should ignore workload sets that are installed
+ throw new NotImplementedException();
}
string GetWorkloadVersion(string workingDirectory = null)
@@ -257,7 +392,6 @@ string GetWorkloadVersion(string workingDirectory = null)
return result.StdOut;
}
-
string GetUpdateMode()
{
var result = VM.CreateRunCommand("dotnet", "workload", "config", "--update-mode")
diff --git a/src/Tests/dotnet-workload-install.Tests/GivenDotnetWorkloadInstall.cs b/src/Tests/dotnet-workload-install.Tests/GivenDotnetWorkloadInstall.cs
index ac2f2c199f50..2596b08a8e8f 100644
--- a/src/Tests/dotnet-workload-install.Tests/GivenDotnetWorkloadInstall.cs
+++ b/src/Tests/dotnet-workload-install.Tests/GivenDotnetWorkloadInstall.cs
@@ -67,7 +67,8 @@ public void GivenWorkloadInstallItCanInstallPacks(bool userLocal, string sdkVers
var parseResult = Parser.Instance.Parse(new string[] { "dotnet", "workload", "install", "xamarin-android", "--skip-manifest-update" });
(_, var installManager, var installer, _, _, _) = GetTestInstallers(parseResult, userLocal, sdkVersion, installedFeatureBand: sdkVersion);
- installManager.InstallWorkloads(mockWorkloadIds, true);
+ installManager.Execute()
+ .Should().Be(0);
installer.GarbageCollectionCalled.Should().BeTrue();
installer.CachePath.Should().BeNull();
@@ -87,8 +88,9 @@ public void GivenWorkloadInstallItCanRollBackPackInstallation(bool userLocal, st
var parseResult = Parser.Instance.Parse(new string[] { "dotnet", "workload", "install", "xamarin-android", "xamarin-android-build", "--skip-manifest-update" });
(_, var installManager, var installer, var workloadResolver, _, _) = GetTestInstallers(parseResult, userLocal, sdkVersion, failingWorkload: "xamarin-android-build", installedFeatureBand: sdkVersion);
- var exceptionThrown = Assert.Throws(() => installManager.InstallWorkloads(mockWorkloadIds, true));
- exceptionThrown.Message.Should().Be("Failing workload: xamarin-android-build");
+ var exceptionThrown = Assert.Throws(() => installManager.Execute());
+ exceptionThrown.Message.Should().Contain("Failing workload: xamarin-android-build");
+
var expectedPacks = mockWorkloadIds
.SelectMany(workloadId => workloadResolver.GetPacksInWorkload(workloadId))
.Distinct()
@@ -111,8 +113,8 @@ public void GivenWorkloadInstallOnFailingRollbackItDisplaysTopLevelError()
var installManager = new WorkloadInstallCommand(parseResult, reporter: _reporter, workloadResolverFactory, workloadInstaller: installer);
- var exceptionThrown = Assert.Throws(() => installManager.InstallWorkloads(mockWorkloadIds, true));
- exceptionThrown.Message.Should().Be("Failing workload: xamarin-android-build");
+ var exceptionThrown = Assert.Throws(() => installManager.Execute());
+ exceptionThrown.Message.Should().Contain("Failing workload: xamarin-android-build");
string.Join(" ", _reporter.Lines).Should().Contain("Rollback failure");
}
@@ -126,7 +128,8 @@ public void GivenWorkloadInstallItCanUpdateAdvertisingManifests(bool userLocal,
var parseResult = Parser.Instance.Parse(new string[] { "dotnet", "workload", "install", "xamarin-android" });
(_, var installManager, var installer, _, var manifestUpdater, _) = GetTestInstallers(parseResult, userLocal, sdkVersion, installedFeatureBand: sdkVersion);
- installManager.InstallWorkloads(new List(), false); // Don't actually do any installs, just update manifests
+ installManager.Execute()
+ .Should().Be(0);
installer.InstalledManifests.Should().BeEmpty(); // Didn't try to alter any installed manifests
manifestUpdater.CalculateManifestUpdatesCallCount.Should().Be(1);
@@ -146,7 +149,9 @@ public void GivenWorkloadInstallItWarnsOnGarbageCollectionFailure()
var workloadResolverFactory = new MockWorkloadResolverFactory(dotnetRoot, "6.0.100", workloadResolver);
var installManager = new WorkloadInstallCommand(parseResult, reporter: _reporter, workloadResolverFactory, workloadInstaller: installer);
- installManager.InstallWorkloads(mockWorkloadIds, true);
+ installManager.Execute()
+ .Should()
+ .Be(0);
string.Join(" ", _reporter.Lines).Should().Contain("Failing garbage collection");
}
@@ -207,12 +212,13 @@ public void GivenWorkloadInstallItCanUpdateInstalledManifests(bool userLocal, st
var manifestsToUpdate =
new ManifestUpdateWithWorkloads[]
{
- new(new ManifestVersionUpdate(new ManifestId("mock-manifest"), new ManifestVersion("1.0.0"), featureBand.ToString(), new ManifestVersion("2.0.0"), featureBand.ToString()), null),
+ new(new ManifestVersionUpdate(new ManifestId("mock-manifest"), new ManifestVersion("2.0.0"), featureBand.ToString()), null),
};
(_, var installManager, var installer, _, _, _) =
GetTestInstallers(parseResult, userLocal, sdkVersion, manifestUpdates: manifestsToUpdate, installedFeatureBand: sdkVersion);
- installManager.InstallWorkloads(new List(), false); // Don't actually do any installs, just update manifests
+ installManager.Execute()
+ .Should().Be(0);
installer.InstalledManifests[0].manifestUpdate.ManifestId.Should().Be(manifestsToUpdate[0].ManifestUpdate.ManifestId);
installer.InstalledManifests[0].manifestUpdate.NewVersion.Should().Be(manifestsToUpdate[0].ManifestUpdate.NewVersion);
@@ -231,7 +237,7 @@ public void GivenWorkloadInstallFromCacheItInstallsCachedManifest(bool userLocal
var manifestsToUpdate =
new ManifestUpdateWithWorkloads[]
{
- new(new ManifestVersionUpdate(new ManifestId("mock-manifest"), new ManifestVersion("1.0.0"), featureBand.ToString(), new ManifestVersion("2.0.0"), featureBand.ToString()), null)
+ new(new ManifestVersionUpdate(new ManifestId("mock-manifest"), new ManifestVersion("2.0.0"), featureBand.ToString()), null)
};
var cachePath = Path.Combine(_testAssetsManager.CreateTestDirectory(identifier: AppendForUserLocal("mockCache_", userLocal) + sdkVersion).Path,
"mockCachePath");
@@ -489,6 +495,32 @@ static void CreateFile(string path)
[Fact]
public void GivenWorkloadInstallItErrorsOnInvalidWorkloadRollbackFile()
+ {
+ _reporter.Clear();
+ var testDirectory = _testAssetsManager.CreateTestDirectory().Path;
+ var dotnetRoot = Path.Combine(testDirectory, "dotnet");
+ var userProfileDir = Path.Combine(testDirectory, "user-profile");
+ var tmpDir = Path.Combine(testDirectory, "tmp");
+ var manifestPath = Path.Combine(_testAssetsManager.GetAndValidateTestProjectDirectory("SampleManifest"), "MockWorkloadsSample.json");
+ var workloadResolver = WorkloadResolver.CreateForTests(new MockManifestProvider(new[] { manifestPath }), dotnetRoot);
+ var sdkFeatureVersion = "6.0.100";
+ var workload = "mock-1";
+ var mockRollbackFileContent = @"[{""fake.manifest.name"":""1.0.0""}]";
+ var rollbackFilePath = Path.Combine(testDirectory, "rollback.json");
+ File.WriteAllText(rollbackFilePath, mockRollbackFileContent);
+ var workloadResolverFactory = new MockWorkloadResolverFactory(dotnetRoot, sdkFeatureVersion, workloadResolver, userProfileDir);
+
+ var installParseResult = Parser.Instance.Parse(new string[] { "dotnet", "workload", "install", workload, "--from-rollback-file", rollbackFilePath });
+ var installCommand = new WorkloadInstallCommand(installParseResult, reporter: _reporter, workloadResolverFactory, nugetPackageDownloader: new MockNuGetPackageDownloader(tmpDir),
+ tempDirPath: testDirectory);
+
+ var ex = Assert.Throws(() => installCommand.Execute());
+ ex.Message.Should().StartWith("Workload installation failed:");
+ string.Join(" ", _reporter.Lines).Should().Contain("Workload installation failed.");
+ }
+
+ [Fact]
+ public void GivenWorkloadInstallItWarnsWhenManifestFromRollbackFileIsntInstalled()
{
_reporter.Clear();
var testDirectory = _testAssetsManager.CreateTestDirectory().Path;
@@ -507,9 +539,9 @@ public void GivenWorkloadInstallItErrorsOnInvalidWorkloadRollbackFile()
var installParseResult = Parser.Instance.Parse(new string[] { "dotnet", "workload", "install", workload, "--from-rollback-file", rollbackFilePath });
var installCommand = new WorkloadInstallCommand(installParseResult, reporter: _reporter, workloadResolverFactory, nugetPackageDownloader: new MockNuGetPackageDownloader(tmpDir),
tempDirPath: testDirectory);
-
- Assert.Throws(() => installCommand.Execute());
- string.Join(" ", _reporter.Lines).Should().Contain("Invalid rollback definition");
+
+ installCommand.Execute().Should().Be(0);
+ string.Join(" ", _reporter.Lines).Should().Contain("Invalid rollback definition. The manifest IDs in rollback definition");
}
[Fact]
@@ -592,12 +624,12 @@ public void ShowManifestUpdatesWhenVerbosityIsDetailedOrDiagnostic(string verbos
var manifestsToUpdate =
new ManifestUpdateWithWorkloads[]
{
- new(new ManifestVersionUpdate(new ManifestId("mock-manifest"), new ManifestVersion("1.0.0"), sdkFeatureBand, new ManifestVersion("2.0.0"), sdkFeatureBand), null),
+ new(new ManifestVersionUpdate(new ManifestId("mock-manifest"), new ManifestVersion("2.0.0"), sdkFeatureBand), null),
};
(_, var installManager, _, _, _, _) =
GetTestInstallers(parseResult, true, sdkFeatureBand, manifestUpdates: manifestsToUpdate);
- installManager.InstallWorkloads(new List(), false); // Don't actually do any installs, just update manifests
+ installManager.Execute().Should().Be(0);
string.Join(" ", _reporter.Lines).Should().Contain(Workloads.Workload.Install.LocalizableStrings.CheckForUpdatedWorkloadManifests);
string.Join(" ", _reporter.Lines).Should().Contain(String.Format(Workloads.Workload.Install.LocalizableStrings.CheckForUpdatedWorkloadManifests, "mock-manifest"));
diff --git a/src/Tests/dotnet-workload-install.Tests/GivenFileBasedWorkloadInstall.cs b/src/Tests/dotnet-workload-install.Tests/GivenFileBasedWorkloadInstall.cs
index 92bb9ba7233d..b0f867ebf0ca 100644
--- a/src/Tests/dotnet-workload-install.Tests/GivenFileBasedWorkloadInstall.cs
+++ b/src/Tests/dotnet-workload-install.Tests/GivenFileBasedWorkloadInstall.cs
@@ -324,7 +324,7 @@ public void GivenManagedInstallItCanInstallManifestVersion()
var manifestId = new ManifestId("test-manifest-1");
var manifestVersion = new ManifestVersion("5.0.0");
- var manifestUpdate = new ManifestVersionUpdate(manifestId, null, null, manifestVersion, featureBand.ToString());
+ var manifestUpdate = new ManifestVersionUpdate(manifestId, manifestVersion, featureBand.ToString());
CliTransaction.RunNew(context => installer.InstallWorkloadManifest(manifestUpdate, context));
diff --git a/src/Tests/dotnet-workload-install.Tests/GivenWorkloadManifestUpdater.cs b/src/Tests/dotnet-workload-install.Tests/GivenWorkloadManifestUpdater.cs
index 1a12d4ccb8b9..8226f4362d96 100644
--- a/src/Tests/dotnet-workload-install.Tests/GivenWorkloadManifestUpdater.cs
+++ b/src/Tests/dotnet-workload-install.Tests/GivenWorkloadManifestUpdater.cs
@@ -91,9 +91,9 @@ public void GivenWorkloadManifestUpdateItCanCalculateUpdates()
var testDir = _testAssetsManager.CreateTestDirectory().Path;
var featureBand = "6.0.100";
var dotnetRoot = Path.Combine(testDir, "dotnet");
- var expectedManifestUpdates = new ManifestVersionUpdate[] {
- new ManifestVersionUpdate(new ManifestId("test-manifest-1"), new ManifestVersion("5.0.0"), featureBand, new ManifestVersion("7.0.0"), featureBand),
- new ManifestVersionUpdate(new ManifestId("test-manifest-2"), new ManifestVersion("3.0.0"), featureBand, new ManifestVersion("4.0.0"), featureBand) };
+ var expectedManifestUpdates = new TestManifestUpdate[] {
+ new TestManifestUpdate(new ManifestId("test-manifest-1"), new ManifestVersion("5.0.0"), featureBand, new ManifestVersion("7.0.0"), featureBand),
+ new TestManifestUpdate(new ManifestId("test-manifest-2"), new ManifestVersion("3.0.0"), featureBand, new ManifestVersion("4.0.0"), featureBand) };
var expectedManifestNotUpdated = new ManifestId[] { new ManifestId("test-manifest-3"), new ManifestId("test-manifest-4") };
// Write mock manifests
@@ -101,7 +101,7 @@ public void GivenWorkloadManifestUpdateItCanCalculateUpdates()
var adManifestDir = Path.Combine(testDir, ".dotnet", "sdk-advertising", featureBand);
Directory.CreateDirectory(installedManifestDir);
Directory.CreateDirectory(adManifestDir);
- foreach (ManifestVersionUpdate manifestUpdate in expectedManifestUpdates)
+ foreach (var manifestUpdate in expectedManifestUpdates)
{
Directory.CreateDirectory(Path.Combine(installedManifestDir, manifestUpdate.ManifestId.ToString()));
File.WriteAllText(Path.Combine(installedManifestDir, manifestUpdate.ManifestId.ToString(), _manifestFileName), GetManifestContent(manifestUpdate.ExistingVersion));
@@ -127,7 +127,7 @@ public void GivenWorkloadManifestUpdateItCanCalculateUpdates()
var manifestUpdater = new WorkloadManifestUpdater(_reporter, workloadResolver, nugetDownloader, userProfileDir: Path.Combine(testDir, ".dotnet"), installationRepo, new MockPackWorkloadInstaller(dotnetRoot));
var manifestUpdates = manifestUpdater.CalculateManifestUpdates().Select(m => m.ManifestUpdate);
- manifestUpdates.Should().BeEquivalentTo(expectedManifestUpdates);
+ manifestUpdates.Should().BeEquivalentTo(expectedManifestUpdates.Select(u => u.ToManifestVersionUpdate()));
}
@@ -137,16 +137,16 @@ public void GivenAdvertisedManifestsItCalculatesCorrectUpdates()
var testDir = _testAssetsManager.CreateTestDirectory().Path;
var currentFeatureBand = "6.0.300";
var dotnetRoot = Path.Combine(testDir, "dotnet");
- var expectedManifestUpdates = new ManifestVersionUpdate[] {
- new ManifestVersionUpdate(new ManifestId("test-manifest-1"), new ManifestVersion("5.0.0"), "6.0.100", new ManifestVersion("7.0.0"), "6.0.100"),
- new ManifestVersionUpdate(new ManifestId("test-manifest-2"), new ManifestVersion("3.0.0"), "6.0.100", new ManifestVersion("4.0.0"), "6.0.300"),
- new ManifestVersionUpdate(new ManifestId("test-manifest-3"), new ManifestVersion("3.0.0"), "6.0.300", new ManifestVersion("4.0.0"), "6.0.300")};
+ var expectedManifestUpdates = new TestManifestUpdate[] {
+ new TestManifestUpdate(new ManifestId("test-manifest-1"), new ManifestVersion("5.0.0"), "6.0.100", new ManifestVersion("7.0.0"), "6.0.100"),
+ new TestManifestUpdate(new ManifestId("test-manifest-2"), new ManifestVersion("3.0.0"), "6.0.100", new ManifestVersion("4.0.0"), "6.0.300"),
+ new TestManifestUpdate(new ManifestId("test-manifest-3"), new ManifestVersion("3.0.0"), "6.0.300", new ManifestVersion("4.0.0"), "6.0.300")};
var expectedManifestNotUpdated = new ManifestId[] { new ManifestId("test-manifest-4") };
// Write mock manifests
var adManifestDir = Path.Combine(testDir, ".dotnet", "sdk-advertising", currentFeatureBand);
Directory.CreateDirectory(adManifestDir);
- foreach (ManifestVersionUpdate manifestUpdate in expectedManifestUpdates)
+ foreach (var manifestUpdate in expectedManifestUpdates)
{
var installedManifestDir = Path.Combine(testDir, "dotnet", "sdk-manifests", manifestUpdate.ExistingFeatureBand);
if (!Directory.Exists(installedManifestDir))
@@ -181,9 +181,9 @@ public void GivenAdvertisedManifestsItCalculatesCorrectUpdates()
}
var manifestInfo = expectedManifestUpdates.Select(
- manifest => (manifest.ManifestId.ToString(), Path.Combine(testDir, "dotnet", "sdk-manifests", manifest.ExistingFeatureBand, manifest.ManifestId.ToString(), "WorkloadManifest.json"), manifest.ExistingFeatureBand))
+ manifest => (manifest.ManifestId.ToString(), Path.Combine(testDir, "dotnet", "sdk-manifests", manifest.ExistingFeatureBand, manifest.ManifestId.ToString(), "WorkloadManifest.json"), manifest.ExistingVersion.ToString(), manifest.ExistingFeatureBand))
.Concat(expectedManifestNotUpdated.Select(
- manifestId => (manifestId.ToString(), Path.Combine(testDir, "dotnet", "sdk-manifests", currentFeatureBand, manifestId.ToString(), "WorkloadManifest.json"), currentFeatureBand)))
+ manifestId => (manifestId.ToString(), Path.Combine(testDir, "dotnet", "sdk-manifests", currentFeatureBand, manifestId.ToString(), "WorkloadManifest.json"), "2.0.0", currentFeatureBand)))
.ToArray();
var workloadManifestProvider = new MockManifestProvider(manifestInfo);
@@ -194,7 +194,7 @@ public void GivenAdvertisedManifestsItCalculatesCorrectUpdates()
var manifestUpdater = new WorkloadManifestUpdater(_reporter, workloadResolver, nugetDownloader, userProfileDir: Path.Combine(testDir, ".dotnet"), installationRepo, new MockPackWorkloadInstaller(dotnetRoot));
var manifestUpdates = manifestUpdater.CalculateManifestUpdates().Select(m => m.ManifestUpdate);
- manifestUpdates.Should().BeEquivalentTo(expectedManifestUpdates);
+ manifestUpdates.Should().BeEquivalentTo(expectedManifestUpdates.Select(u => u.ToManifestVersionUpdate()));
}
[Theory]
@@ -224,7 +224,7 @@ public void ItCanFallbackAndAdvertiseCorrectUpdate(bool useOfflineCache)
string manifestPath = Path.Combine(installedManifestDir6_0_200, testManifestName, _manifestFileName);
- var workloadManifestProvider = new MockManifestProvider((testManifestName, manifestPath, "6.0.200"))
+ var workloadManifestProvider = new MockManifestProvider((testManifestName, manifestPath, "1.0.0", "6.0.200"))
{
SdkFeatureBand = new SdkFeatureBand(sdkFeatureBand)
};
@@ -302,7 +302,7 @@ public void ItCanFallbackWithNoUpdates(bool useOfflineCache)
Directory.CreateDirectory(Path.Combine(emptyInstalledManifestsDir, testManifestName));
File.WriteAllText(Path.Combine(emptyInstalledManifestsDir, testManifestName, _manifestFileName), GetManifestContent(new ManifestVersion("1.0.0")));
- var workloadManifestProvider = new MockManifestProvider((testManifestName, Path.Combine(emptyInstalledManifestsDir, testManifestName, _manifestFileName), "6.0.200"))
+ var workloadManifestProvider = new MockManifestProvider((testManifestName, Path.Combine(emptyInstalledManifestsDir, testManifestName, _manifestFileName), "1.0.0", "6.0.200"))
{
SdkFeatureBand = new SdkFeatureBand(sdkFeatureBand)
};
@@ -414,9 +414,9 @@ public void GivenWorkloadManifestRollbackItCanCalculateUpdates()
var testDir = _testAssetsManager.CreateTestDirectory().Path;
var currentFeatureBand = "6.0.100";
var dotnetRoot = Path.Combine(testDir, "dotnet");
- var expectedManifestUpdates = new ManifestVersionUpdate[] {
- new ManifestVersionUpdate(new ManifestId("test-manifest-1"), new ManifestVersion("5.0.0"), currentFeatureBand, new ManifestVersion("4.0.0"), currentFeatureBand),
- new ManifestVersionUpdate(new ManifestId("test-manifest-2"), new ManifestVersion("3.0.0"), currentFeatureBand, new ManifestVersion("2.0.0"), currentFeatureBand) };
+ var expectedManifestUpdates = new TestManifestUpdate[] {
+ new TestManifestUpdate(new ManifestId("test-manifest-1"), new ManifestVersion("5.0.0"), currentFeatureBand, new ManifestVersion("4.0.0"), currentFeatureBand),
+ new TestManifestUpdate(new ManifestId("test-manifest-2"), new ManifestVersion("3.0.0"), currentFeatureBand, new ManifestVersion("2.0.0"), currentFeatureBand) };
// Write mock manifests
var installedManifestDir = Path.Combine(testDir, "dotnet", "sdk-manifests", currentFeatureBand);
@@ -443,7 +443,7 @@ public void GivenWorkloadManifestRollbackItCanCalculateUpdates()
var manifestUpdater = new WorkloadManifestUpdater(_reporter, workloadResolver, nugetDownloader, testDir, installationRepo, new MockPackWorkloadInstaller(dotnetRoot));
var manifestUpdates = manifestUpdater.CalculateManifestRollbacks(rollbackDefPath);
- manifestUpdates.Should().BeEquivalentTo(expectedManifestUpdates);
+ manifestUpdates.Should().BeEquivalentTo(expectedManifestUpdates.Select(u => u.ToManifestVersionUpdate()));
}
[Fact]
diff --git a/src/Tests/dotnet-workload-install.Tests/MockManifestProvider.cs b/src/Tests/dotnet-workload-install.Tests/MockManifestProvider.cs
index 935fb9addfe8..ecfa11b0dfa9 100644
--- a/src/Tests/dotnet-workload-install.Tests/MockManifestProvider.cs
+++ b/src/Tests/dotnet-workload-install.Tests/MockManifestProvider.cs
@@ -7,19 +7,19 @@ namespace ManifestReaderTests
{
internal class MockManifestProvider : IWorkloadManifestProvider
{
- readonly (string name, string path, string featureBand)[] _manifests;
+ readonly (string name, string path, string manifestVersion, string featureBand)[] _manifests;
public MockManifestProvider(params string[] manifestPaths)
{
_manifests = Array.ConvertAll(manifestPaths, mp =>
{
string manifestId = Path.GetFileNameWithoutExtension(Path.GetDirectoryName(mp));
- return (manifestId, mp, (string)null);
+ return (manifestId, mp, (string)null, (string)null);
});
SdkFeatureBand = new SdkFeatureBand("6.0.100");
}
- public MockManifestProvider(params (string name, string path, string featureBand)[] manifests)
+ public MockManifestProvider(params (string name, string path, string manifestVersion, string featureBand)[] manifests)
{
_manifests = manifests;
SdkFeatureBand = new SdkFeatureBand("6.0.100");
@@ -33,14 +33,14 @@ public void RefreshWorkloadManifests() { }
public IEnumerable GetManifests()
{
- foreach ((var id, var path, var featureBand) in _manifests)
+ foreach ((var id, var path, var manifestVersion, var featureBand) in _manifests)
{
yield return new(
id,
Path.GetDirectoryName(path),
path,
featureBand ?? SdkFeatureBand.ToString(),
- string.Empty,
+ manifestVersion,
() => File.OpenRead(path),
() => WorkloadManifestReader.TryOpenLocalizationCatalogForManifest(path)
);
diff --git a/src/Tests/dotnet-workload-install.Tests/MockPackWorkloadInstaller.cs b/src/Tests/dotnet-workload-install.Tests/MockPackWorkloadInstaller.cs
index fb4b3924dea5..ebd336c20e54 100644
--- a/src/Tests/dotnet-workload-install.Tests/MockPackWorkloadInstaller.cs
+++ b/src/Tests/dotnet-workload-install.Tests/MockPackWorkloadInstaller.cs
@@ -20,6 +20,7 @@ internal class MockPackWorkloadInstaller : IInstaller
new List<(ManifestVersionUpdate manifestUpdate, DirectoryPath?)>();
public string CachePath;
public bool GarbageCollectionCalled = false;
+ public bool InstallWorkloadSetCalled = false;
public MockInstallationRecordRepository InstallationRecordRepository;
public bool FailingRollback;
public bool FailingGarbageCollection;
@@ -59,7 +60,7 @@ IEnumerable GetPacksForWorkloads(IEnumerable workloadIds)
}
}
- public void UpdateInstallMode(SdkFeatureBand sdkFeatureBand, bool newMode)
+ public void UpdateInstallMode(SdkFeatureBand sdkFeatureBand, bool? newMode)
{
throw new NotImplementedException();
}
@@ -105,12 +106,12 @@ public void InstallWorkloads(IEnumerable workloadIds, SdkFeatureBand
});
}
- public string InstallWorkloadSet(ITransactionContext context, string advertisingPackagePath)
+ public WorkloadSet InstallWorkloadSet(ITransactionContext context, string workloadSetVersion, DirectoryPath? offlineCache = null)
{
- var version = Path.GetFileName(Path.GetDirectoryName(advertisingPackagePath ?? string.Empty));
- Directory.CreateDirectory(advertisingPackagePath);
- File.WriteAllText(Path.Combine(advertisingPackagePath, Constants.workloadSetVersionFileName), version);
- return Path.GetDirectoryName(advertisingPackagePath ?? string.Empty);
+ InstallWorkloadSetCalled = true;
+ var workloadSet = WorkloadSet.FromJson(workloadSetContents, new SdkFeatureBand("6.0.100"));
+ workloadSet.Version = workloadSetVersion;
+ return workloadSet;
}
public void RepairWorkloads(IEnumerable workloadIds, SdkFeatureBand sdkFeatureBand, DirectoryPath? offlineCache = null) => throw new NotImplementedException();
@@ -129,7 +130,7 @@ public IWorkloadInstallationRecordRepository GetWorkloadInstallationRecordReposi
return InstallationRecordRepository;
}
- public void InstallWorkloadManifest(ManifestVersionUpdate manifestUpdate, ITransactionContext transactionContext, DirectoryPath? offlineCache = null, bool isRollback = false)
+ public void InstallWorkloadManifest(ManifestVersionUpdate manifestUpdate, ITransactionContext transactionContext, DirectoryPath? offlineCache = null)
{
InstalledManifests.Add((manifestUpdate, offlineCache));
}
diff --git a/src/Tests/dotnet-workload-install.Tests/MockWorkloadManifestUpdater.cs b/src/Tests/dotnet-workload-install.Tests/MockWorkloadManifestUpdater.cs
index 3b7a0275a2e6..609cb9b6bb52 100644
--- a/src/Tests/dotnet-workload-install.Tests/MockWorkloadManifestUpdater.cs
+++ b/src/Tests/dotnet-workload-install.Tests/MockWorkloadManifestUpdater.cs
@@ -14,11 +14,13 @@ internal class MockWorkloadManifestUpdater : IWorkloadManifestUpdater
public int GetManifestPackageDownloadsCallCount = 0;
private readonly IEnumerable _manifestUpdates;
private bool _fromWorkloadSet;
+ private string _workloadSetVersion;
- public MockWorkloadManifestUpdater(IEnumerable manifestUpdates = null, bool fromWorkloadSet = false)
+ public MockWorkloadManifestUpdater(IEnumerable manifestUpdates = null, bool fromWorkloadSet = false, string workloadSetVersion = null)
{
_manifestUpdates = manifestUpdates ?? new List();
_fromWorkloadSet = fromWorkloadSet;
+ _workloadSetVersion = workloadSetVersion;
}
public Task UpdateAdvertisingManifestsAsync(bool includePreview, bool useWorkloadSets = false, DirectoryPath? cachePath = null)
@@ -56,7 +58,9 @@ public IEnumerable CalculateManifestRollbacks(string roll
public IEnumerable GetUpdatableWorkloadsToAdvertise(IEnumerable installedWorkloads) => throw new NotImplementedException();
public void DeleteUpdatableWorkloadsFile() { }
- public void DownloadWorkloadSet(string version, DirectoryPath? offlineCache) => throw new NotImplementedException();
- public IEnumerable ParseRollbackDefinitionFiles(IEnumerable files) => _manifestUpdates.Select(t => t.ManifestUpdate);
+ public IEnumerable CalculateManifestUpdatesForWorkloadSet(WorkloadSet workloadSet) => _manifestUpdates.Select(t => t.ManifestUpdate);
+
+ public string GetAdvertisedWorkloadSetVersion() => _workloadSetVersion;
+
}
}
diff --git a/src/Tests/dotnet-workload-install.Tests/TestManifestUpdate.cs b/src/Tests/dotnet-workload-install.Tests/TestManifestUpdate.cs
new file mode 100644
index 000000000000..fd71e9a76d35
--- /dev/null
+++ b/src/Tests/dotnet-workload-install.Tests/TestManifestUpdate.cs
@@ -0,0 +1,104 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Runtime.CompilerServices;
+using System.Text.Json;
+using FluentAssertions.Extensions;
+using ManifestReaderTests;
+using Microsoft.DotNet.Cli.NuGetPackageDownloader;
+using Microsoft.DotNet.ToolPackage;
+using Microsoft.DotNet.Workloads.Workload.Install;
+using Microsoft.Extensions.EnvironmentAbstractions;
+using Microsoft.NET.Sdk.WorkloadManifestReader;
+using NuGet.Versioning;
+
+namespace Microsoft.DotNet.Cli.Workload.Install.Tests
+{
+ public class TestManifestUpdate
+ {
+ public TestManifestUpdate(ManifestId manifestId, ManifestVersion existingVersion, string existingFeatureBand, ManifestVersion newVersion, string newFeatureBand)
+ {
+ ManifestId = manifestId;
+ ExistingVersion = existingVersion;
+ ExistingFeatureBand = existingFeatureBand;
+ NewVersion = newVersion;
+ NewFeatureBand = newFeatureBand;
+ }
+
+ public ManifestId ManifestId { get; }
+ public ManifestVersion ExistingVersion { get; }
+ public string ExistingFeatureBand { get; }
+ public ManifestVersion NewVersion { get; }
+ public string NewFeatureBand { get; }
+
+ // Returns an object representing an undo of this manifest update
+ //public TestManifestUpdate Reverse()
+ //{
+ // return new TestManifestUpdate(ManifestId, NewVersion, NewFeatureBand, ExistingVersion, ExistingFeatureBand);
+ //}
+
+ public int CompareTo(TestManifestUpdate other)
+ {
+ if (other == null) return 1;
+ int ret = ManifestId.CompareTo(other.ManifestId);
+ if (ret != 0) return ret;
+
+ if (ExistingVersion == null && other.ExistingVersion != null) return -1;
+ if (ExistingVersion != null && other.ExistingVersion == null) return 1;
+ if (ExistingVersion != null)
+ {
+ ret = ExistingVersion.CompareTo(other.ExistingVersion);
+ if (ret != 0) return ret;
+ }
+
+ ret = string.Compare(ExistingFeatureBand, other.ExistingFeatureBand, StringComparison.Ordinal);
+ if (ret != 0) return ret;
+
+ if (NewVersion == null && other.NewVersion != null) return -1;
+ if (NewVersion != null && other.NewVersion == null) return 1;
+ if (NewVersion != null)
+ {
+ ret = NewVersion.CompareTo(other.NewVersion);
+ if (ret != 0) return ret;
+ }
+
+ ret = string.Compare(NewFeatureBand, other.NewFeatureBand, StringComparison.Ordinal);
+ return ret;
+ }
+ public bool Equals(TestManifestUpdate other)
+ {
+ if (other == null) return false;
+ return EqualityComparer.Default.Equals(ManifestId, other.ManifestId) &&
+ EqualityComparer.Default.Equals(ExistingVersion, other.ExistingVersion) &&
+ string.Equals(ExistingFeatureBand, other.ExistingFeatureBand, StringComparison.Ordinal) &&
+ EqualityComparer.Default.Equals(NewVersion, other.NewVersion) &&
+ string.Equals(NewFeatureBand, other.NewFeatureBand, StringComparison.Ordinal);
+ }
+
+ public override bool Equals(object obj)
+ {
+ return obj is TestManifestUpdate id && Equals(id);
+ }
+
+ public override int GetHashCode()
+ {
+#if NETCOREAPP3_1_OR_GREATER
+ return HashCode.Combine(ManifestId, ExistingVersion, ExistingFeatureBand, NewVersion, NewFeatureBand);
+#else
+ int hashCode = 1601069575;
+ hashCode = hashCode * -1521134295 + ManifestId.GetHashCode();
+ hashCode = hashCode * -1521134295 + EqualityComparer.Default.GetHashCode(ExistingVersion);
+ hashCode = hashCode * -1521134295 + EqualityComparer.Default.GetHashCode(ExistingFeatureBand);
+ hashCode = hashCode * -1521134295 + EqualityComparer.Default.GetHashCode(NewVersion);
+ hashCode = hashCode * -1521134295 + EqualityComparer.Default.GetHashCode(NewFeatureBand);
+ return hashCode;
+#endif
+ }
+
+ public ManifestVersionUpdate ToManifestVersionUpdate()
+ {
+ return new(ManifestId, NewVersion, NewFeatureBand);
+ }
+
+ }
+}
diff --git a/src/Tests/dotnet-workload-list.Tests/GivenDotnetWorkloadList.cs b/src/Tests/dotnet-workload-list.Tests/GivenDotnetWorkloadList.cs
index b828a7a322d9..ee123d9cfa86 100644
--- a/src/Tests/dotnet-workload-list.Tests/GivenDotnetWorkloadList.cs
+++ b/src/Tests/dotnet-workload-list.Tests/GivenDotnetWorkloadList.cs
@@ -55,7 +55,7 @@ public void GivenWorkloadsAreInstalledListIsNotEmpty()
_reporter.Clear();
var expectedWorkloads = new List() { new WorkloadId("mock-workload-1"), new WorkloadId("mock-workload-2"), new WorkloadId("mock-workload-3") };
var workloadInstaller = new MockWorkloadRecordRepo(expectedWorkloads);
- var workloadResolver = WorkloadResolver.CreateForTests(new MockManifestProvider(("SampleManifest", _manifestPath, "6.0.100")), Directory.GetCurrentDirectory());
+ var workloadResolver = WorkloadResolver.CreateForTests(new MockManifestProvider(("SampleManifest", _manifestPath, "5.0.0", "6.0.100")), Directory.GetCurrentDirectory());
var command = new WorkloadListCommand(_parseResult, _reporter, workloadInstaller, "6.0.100", workloadResolver: workloadResolver);
command.Execute();
diff --git a/src/Tests/dotnet-workload-list.Tests/GivenWorkloadInstallerAndWorkloadsInstalled.cs b/src/Tests/dotnet-workload-list.Tests/GivenWorkloadInstallerAndWorkloadsInstalled.cs
index 29d942429114..10cb1a62781a 100644
--- a/src/Tests/dotnet-workload-list.Tests/GivenWorkloadInstallerAndWorkloadsInstalled.cs
+++ b/src/Tests/dotnet-workload-list.Tests/GivenWorkloadInstallerAndWorkloadsInstalled.cs
@@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System.CommandLine;
+using System.Runtime.CompilerServices;
+using ManifestReaderTests;
using Microsoft.Deployment.DotNet.Releases;
using Microsoft.DotNet.Cli.NuGetPackageDownloader;
using Microsoft.DotNet.Cli.Workload.Install.Tests;
@@ -23,7 +25,7 @@ public class GivenInstalledWorkloadAndManifestUpdater : SdkTest
private WorkloadListCommand _workloadListCommand;
private string _testDirectory;
- private List _mockManifestUpdates;
+ private List<(TestManifestUpdate update, WorkloadCollection workloads)> _mockManifestUpdates;
private MockNuGetPackageDownloader _nugetDownloader;
private string _dotnetRoot;
@@ -32,7 +34,12 @@ public GivenInstalledWorkloadAndManifestUpdater(ITestOutputHelper log) : base(lo
{
}
- private void Setup(string identifier)
+ private IEnumerable GetManifestUpdatesForMock()
+ {
+ return _mockManifestUpdates.Select(u => new ManifestUpdateWithWorkloads(u.update.ToManifestVersionUpdate(), u.workloads));
+ }
+
+ private void Setup([CallerMemberName] string identifier = "")
{
_testDirectory = _testAssetsManager.CreateTestDirectory(identifier: identifier).Path;
_dotnetRoot = Path.Combine(_testDirectory, "dotnet");
@@ -42,7 +49,7 @@ private void Setup(string identifier)
_mockManifestUpdates = new()
{
new(
- new ManifestVersionUpdate(
+ new TestManifestUpdate(
new ManifestId("manifest1"),
new ManifestVersion(CurrentSdkVersion),
currentSdkFeatureBand.ToString(),
@@ -58,7 +65,7 @@ private void Setup(string identifier)
WorkloadDefinitionKind.Dev, null, null, null)
}),
new(
- new ManifestVersionUpdate(
+ new TestManifestUpdate(
new ManifestId("manifest-other"),
new ManifestVersion(CurrentSdkVersion),
currentSdkFeatureBand.ToString(),
@@ -72,7 +79,7 @@ private void Setup(string identifier)
WorkloadDefinitionKind.Dev, null, null, null)
}),
new(
- new ManifestVersionUpdate(
+ new TestManifestUpdate(
new ManifestId("manifest-older-version"),
new ManifestVersion(CurrentSdkVersion),
currentSdkFeatureBand.ToString(),
@@ -92,21 +99,31 @@ private void Setup(string identifier)
"dotnet", "workload", "list", "--machine-readable", InstallingWorkloadCommandParser.VersionOption.Name, "7.0.100"
});
+
+ var manifestProvider = new MockManifestProvider(_mockManifestUpdates.Select(u =>
+ {
+ string manifestFile = Path.Combine(_testDirectory, u.update.ManifestId.ToString() + ".json");
+ File.WriteAllText(manifestFile, GivenWorkloadManifestUpdater.GetManifestContent(u.update.ExistingVersion));
+ return (u.update.ManifestId.ToString(), manifestFile, u.update.ExistingVersion.ToString(), u.update.ExistingFeatureBand.ToString());
+ }).ToArray());
+ var workloadResolver = WorkloadResolver.CreateForTests(manifestProvider, _dotnetRoot);
+
_workloadListCommand = new WorkloadListCommand(
listParseResult,
_reporter,
nugetPackageDownloader: _nugetDownloader,
- workloadManifestUpdater: new MockWorkloadManifestUpdater(_mockManifestUpdates),
+ workloadManifestUpdater: new MockWorkloadManifestUpdater(GetManifestUpdatesForMock()),
userProfileDir: _testDirectory,
currentSdkVersion: CurrentSdkVersion,
dotnetDir: _dotnetRoot,
- workloadRecordRepo: new MockMatchingFeatureBandInstallationRecordRepository());
+ workloadRecordRepo: new MockMatchingFeatureBandInstallationRecordRepository(),
+ workloadResolver: workloadResolver);
}
[Fact]
public void ItShouldGetAvailableUpdate()
{
- Setup(nameof(ItShouldGetAvailableUpdate));
+ Setup();
WorkloadListCommand.UpdateAvailableEntry[] result =
_workloadListCommand.GetUpdateAvailable(new List { new("xamarin-android") }).ToArray();
@@ -120,7 +137,7 @@ public void ItShouldGetAvailableUpdate()
[Fact]
public void ItShouldGetListOfWorkloadWithCurrentSdkVersionBand()
{
- Setup(nameof(ItShouldGetListOfWorkloadWithCurrentSdkVersionBand));
+ Setup();
_workloadListCommand.Execute();
_reporter.Lines.Should().Contain(c => c.Contains("\"installed\":[\"xamarin-android\"]"));
}
@@ -135,7 +152,7 @@ public void GivenLowerTargetVersionItShouldThrow()
}),
_reporter,
nugetPackageDownloader: _nugetDownloader,
- workloadManifestUpdater: new MockWorkloadManifestUpdater(_mockManifestUpdates),
+ workloadManifestUpdater: new MockWorkloadManifestUpdater(null),
userProfileDir: _testDirectory,
currentSdkVersion: CurrentSdkVersion,
dotnetDir: _dotnetRoot,
@@ -155,7 +172,7 @@ public void GivenSameLowerTargetVersionBandItShouldNotThrow()
}),
_reporter,
nugetPackageDownloader: _nugetDownloader,
- workloadManifestUpdater: new MockWorkloadManifestUpdater(_mockManifestUpdates),
+ workloadManifestUpdater: new MockWorkloadManifestUpdater(null),
userProfileDir: _testDirectory,
currentSdkVersion: "6.0.101",
dotnetDir: _dotnetRoot,
diff --git a/src/Tests/dotnet-workload-search.Tests/MockWorkloadResolver.cs b/src/Tests/dotnet-workload-search.Tests/MockWorkloadResolver.cs
index 5a9bdd9cb706..4c6e6618fb34 100644
--- a/src/Tests/dotnet-workload-search.Tests/MockWorkloadResolver.cs
+++ b/src/Tests/dotnet-workload-search.Tests/MockWorkloadResolver.cs
@@ -25,6 +25,7 @@ public void RefreshWorkloadManifests() { }
public WorkloadResolver.PackInfo TryGetPackInfo(WorkloadPackId packId) => throw new NotImplementedException();
public bool IsPlatformIncompatibleWorkload(WorkloadId workloadId) => throw new NotImplementedException();
public string GetManifestVersion(string manifestId) => throw new NotImplementedException();
+ public string GetManifestFeatureBand(string manifestId) => throw new NotImplementedException();
public IEnumerable GetInstalledManifests() => throw new NotImplementedException();
public IWorkloadResolver CreateOverlayResolver(IWorkloadManifestProvider overlayManifestProvider) => throw new NotImplementedException();
public string GetSdkFeatureBand() => "12.0.400";
diff --git a/src/Tests/dotnet-workload-update.Tests/GivenDotnetWorkloadUpdate.cs b/src/Tests/dotnet-workload-update.Tests/GivenDotnetWorkloadUpdate.cs
index 4535a63ef971..de8526916e3d 100644
--- a/src/Tests/dotnet-workload-update.Tests/GivenDotnetWorkloadUpdate.cs
+++ b/src/Tests/dotnet-workload-update.Tests/GivenDotnetWorkloadUpdate.cs
@@ -196,7 +196,12 @@ public void GivenWorkloadUpdateItUpdatesOutOfDatePacks()
[InlineData(false)]
public void UpdateViaWorkloadSet(bool upgrade)
{
- var versionNumber = "8.0.0";
+ var testDir = _testAssetsManager.CreateTestDirectory(identifier: upgrade.ToString());
+ string dotnetDir = Path.Combine(testDir.Path, "dotnet");
+ string userProfileDir = Path.Combine(testDir.Path, "userProfileDir");
+
+ var sdkVersion = "8.0.300";
+ var workloadSetVersion = "8.0.302";
var workloadSetContents = @"
{
""android"": ""2.3.4/8.0.200""
@@ -205,7 +210,7 @@ public void UpdateViaWorkloadSet(bool upgrade)
var nugetPackageDownloader = new MockNuGetPackageDownloader();
var workloadResolver = new MockWorkloadResolver(new WorkloadInfo[] { new WorkloadInfo(new WorkloadId("android"), string.Empty) });
var workloadInstaller = new MockPackWorkloadInstaller(
- Path.Combine(Path.GetTempPath(), "dotnetTestPat", "userProfileDir"),
+ dotnetDir,
installedWorkloads: new List() { new WorkloadId("android")},
workloadSetContents: workloadSetContents)
{
@@ -214,36 +219,19 @@ public void UpdateViaWorkloadSet(bool upgrade)
var oldVersion = upgrade ? "2.3.2" : "2.3.6";
var workloadManifestUpdater = new MockWorkloadManifestUpdater(
manifestUpdates: new ManifestUpdateWithWorkloads[] {
- new ManifestUpdateWithWorkloads(new ManifestVersionUpdate(new ManifestId("android"), new ManifestVersion(oldVersion), "8.0.200", new ManifestVersion("2.3.4"), "8.0.200"), Enumerable.Empty>().ToDictionary())
+ new ManifestUpdateWithWorkloads(new ManifestVersionUpdate(new ManifestId("android"), new ManifestVersion("2.3.4"), "8.0.200"), Enumerable.Empty>().ToDictionary())
},
- fromWorkloadSet: true);
- var resolverFactory = new MockWorkloadResolverFactory(Path.Combine(Path.GetTempPath(), "dotnetTestPath"), versionNumber, workloadResolver, "userProfileDir");
+ fromWorkloadSet: true, workloadSetVersion: workloadSetVersion);
+ var resolverFactory = new MockWorkloadResolverFactory(dotnetDir, sdkVersion, workloadResolver, userProfileDir);
var updateCommand = new WorkloadUpdateCommand(Parser.Instance.Parse("dotnet workload update"), Reporter.Output, resolverFactory, workloadInstaller, nugetPackageDownloader, workloadManifestUpdater);
- var installStatePath = Path.Combine(Path.GetTempPath(), "dotnetTestPath", "metadata", "workloads", RuntimeInformation.ProcessArchitecture.ToString(), versionNumber, "InstallState", "default.json");
+ var installStatePath = Path.Combine(dotnetDir, "metadata", "workloads", RuntimeInformation.ProcessArchitecture.ToString(), sdkVersion, "InstallState", "default.json");
var contents = new InstallStateContents();
contents.UseWorkloadSets = true;
- var versionFile = Path.Combine("userProfileDir", "sdk-advertising", "8.0.0", "microsoft.net.workloads", Constants.workloadSetVersionFileName);
- try
- {
- Directory.CreateDirectory(Path.GetDirectoryName(installStatePath));
- File.WriteAllText(installStatePath, contents.ToString());
- updateCommand.Execute();
- File.Exists(versionFile).Should().BeTrue();
- File.ReadAllText(versionFile).Should().Be("8.0.0");
- }
- finally
- {
- if (File.Exists(versionFile))
- {
- File.Delete(versionFile);
- }
-
- if (File.Exists(installStatePath))
- {
- File.Delete(installStatePath);
- }
- }
+
+ Directory.CreateDirectory(Path.GetDirectoryName(installStatePath));
+ File.WriteAllText(installStatePath, contents.ToString());
+ updateCommand.Execute();
workloadInstaller.InstalledManifests.Count.Should().Be(1);
workloadInstaller.InstalledManifests[0].manifestUpdate.NewVersion.ToString().Should().Be("2.3.4");
@@ -387,17 +375,16 @@ public void ApplyRollbackAcrossFeatureBand(string existingSdkFeatureBand, string
var manifestsToUpdate =
new ManifestUpdateWithWorkloads[]
{
- new(new ManifestVersionUpdate(new ManifestId("mock-manifest"), new ManifestVersion("1.0.0"), existingSdkFeatureBand, new ManifestVersion("2.0.0"), newSdkFeatureBand), null),
+ new(new ManifestVersionUpdate(new ManifestId("mock-manifest"), new ManifestVersion("2.0.0"), newSdkFeatureBand), null),
};
(var dotnetPath, var updateCommand, var packInstaller, _, _, _) = GetTestInstallers(parseResult, manifestUpdates: manifestsToUpdate, sdkVersion: "6.0.300", identifier: existingSdkFeatureBand + newSdkFeatureBand, installedFeatureBand: existingSdkFeatureBand);
- updateCommand.CalculateManifestUpdatesAndUpdateWorkloads();
+ updateCommand.Execute()
+ .Should().Be(0);
packInstaller.InstalledManifests[0].manifestUpdate.ManifestId.Should().Be(manifestsToUpdate[0].ManifestUpdate.ManifestId);
packInstaller.InstalledManifests[0].manifestUpdate.NewVersion.Should().Be(manifestsToUpdate[0].ManifestUpdate.NewVersion);
packInstaller.InstalledManifests[0].manifestUpdate.NewFeatureBand.Should().Be(manifestsToUpdate[0].ManifestUpdate.NewFeatureBand);
- packInstaller.InstalledManifests[0].manifestUpdate.ExistingVersion.Should().Be(manifestsToUpdate[0].ManifestUpdate.ExistingVersion);
- packInstaller.InstalledManifests[0].manifestUpdate.ExistingFeatureBand.Should().Be(manifestsToUpdate[0].ManifestUpdate.ExistingFeatureBand);
packInstaller.InstalledManifests[0].offlineCache.Should().Be(null);
var defaultJsonPath = Path.Combine(dotnetPath, "metadata", "workloads", RuntimeInformation.ProcessArchitecture.ToString(), "6.0.300", "InstallState", "default.json");
@@ -415,22 +402,20 @@ public void ApplyRollbackWithMultipleManifestsAcrossFeatureBand()
var manifestsToUpdate =
new ManifestUpdateWithWorkloads[]
{
- new(new ManifestVersionUpdate(new ManifestId("mock-manifest-1"), new ManifestVersion("1.0.0"), "6.0.300", new ManifestVersion("2.0.0"), "6.0.100"), null),
- new(new ManifestVersionUpdate(new ManifestId("mock-manifest-2"), new ManifestVersion("1.0.0"), "6.0.100", new ManifestVersion("2.0.0"), "6.0.300"), null),
- new(new ManifestVersionUpdate(new ManifestId("mock-manifest-3"), new ManifestVersion("1.0.0"), "5.0.100", new ManifestVersion("2.0.0"), "6.0.100"), null),
+ new(new ManifestVersionUpdate(new ManifestId("mock-manifest-1"), new ManifestVersion("2.0.0"), "6.0.100"), null),
+ new(new ManifestVersionUpdate(new ManifestId("mock-manifest-2"), new ManifestVersion("2.0.0"), "6.0.300"), null),
+ new(new ManifestVersionUpdate(new ManifestId("mock-manifest-3"), new ManifestVersion("2.0.0"), "6.0.100"), null),
};
(_, var updateCommand, var packInstaller, _, _, _) = GetTestInstallers(parseResult, manifestUpdates: manifestsToUpdate, sdkVersion: "6.0.300", installedFeatureBand: "6.0.300");
- updateCommand.CalculateManifestUpdatesAndUpdateWorkloads();
+ updateCommand.Execute()
+ .Should().Be(0);
packInstaller.InstalledManifests[0].manifestUpdate.ManifestId.Should().Be(manifestsToUpdate[0].ManifestUpdate.ManifestId);
packInstaller.InstalledManifests[0].manifestUpdate.NewVersion.Should().Be(manifestsToUpdate[0].ManifestUpdate.NewVersion);
packInstaller.InstalledManifests[0].manifestUpdate.NewFeatureBand.Should().Be("6.0.100");
packInstaller.InstalledManifests[1].manifestUpdate.NewFeatureBand.Should().Be("6.0.300");
packInstaller.InstalledManifests[2].manifestUpdate.NewFeatureBand.Should().Be("6.0.100");
- packInstaller.InstalledManifests[0].manifestUpdate.ExistingFeatureBand.Should().Be("6.0.300");
- packInstaller.InstalledManifests[1].manifestUpdate.ExistingFeatureBand.Should().Be("6.0.100");
- packInstaller.InstalledManifests[2].manifestUpdate.ExistingFeatureBand.Should().Be("5.0.100");
packInstaller.InstalledManifests[0].offlineCache.Should().Be(null);
}