diff --git a/src/Cli/dotnet/commands/dotnet-workload/install/IWorkloadManifestUpdater.cs b/src/Cli/dotnet/commands/dotnet-workload/install/IWorkloadManifestUpdater.cs index 91302969b95a..24fdfe0af58f 100644 --- a/src/Cli/dotnet/commands/dotnet-workload/install/IWorkloadManifestUpdater.cs +++ b/src/Cli/dotnet/commands/dotnet-workload/install/IWorkloadManifestUpdater.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Threading.Tasks; +using Microsoft.DotNet.Workloads.Workload.Install.InstallRecord; using Microsoft.Extensions.EnvironmentAbstractions; using Microsoft.NET.Sdk.WorkloadManifestReader; @@ -16,11 +17,14 @@ internal interface IWorkloadManifestUpdater IEnumerable<( ManifestId manifestId, - ManifestVersion existingVersion, + ManifestVersion existingVersion, + SdkFeatureBand existingFeatureBand, ManifestVersion newVersion, - Dictionary Workloads)> CalculateManifestUpdates(); + SdkFeatureBand newFeatureBand, + Dictionary Workloads + )> CalculateManifestUpdates(); - IEnumerable<(ManifestId manifestId, ManifestVersion existingVersion, ManifestVersion newVersion)> + IEnumerable<(ManifestId manifestId, ManifestVersion existingVersion, SdkFeatureBand existingFeatureBand, ManifestVersion newVersion, SdkFeatureBand newFeatureBand)> CalculateManifestRollbacks(string rollbackDefinitionFilePath); Task> DownloadManifestPackagesAsync(bool includePreviews, DirectoryPath downloadPath); diff --git a/src/Cli/dotnet/commands/dotnet-workload/install/WorkloadInstallCommand.cs b/src/Cli/dotnet/commands/dotnet-workload/install/WorkloadInstallCommand.cs index 34585af73a72..ec98f46f7d0f 100644 --- a/src/Cli/dotnet/commands/dotnet-workload/install/WorkloadInstallCommand.cs +++ b/src/Cli/dotnet/commands/dotnet-workload/install/WorkloadInstallCommand.cs @@ -182,7 +182,7 @@ public void InstallWorkloads(IEnumerable workloadIds, bool skipManif { _reporter.WriteLine(); - IEnumerable<(ManifestId, ManifestVersion, ManifestVersion)> manifestsToUpdate = new List<(ManifestId, ManifestVersion, ManifestVersion)>(); + var manifestsToUpdate = Enumerable.Empty<(ManifestId manifestId, ManifestVersion existingVersion, SdkFeatureBand existingFeatureBand, ManifestVersion newVersion, SdkFeatureBand newFeatureBand)>(); if (!skipManifestUpdate) { if (_verbosity != VerbosityOptions.quiet && _verbosity != VerbosityOptions.q) @@ -200,7 +200,7 @@ public void InstallWorkloads(IEnumerable workloadIds, bool skipManif _workloadManifestUpdater.UpdateAdvertisingManifestsAsync(includePreviews, offlineCache).Wait(); manifestsToUpdate = string.IsNullOrWhiteSpace(_fromRollbackDefinition) ? - _workloadManifestUpdater.CalculateManifestUpdates().Select(m => (m.manifestId, m.existingVersion, m.newVersion)) : + _workloadManifestUpdater.CalculateManifestUpdates().Select(m => (m.manifestId, m.existingVersion, m.existingFeatureBand, m.newVersion, m.newFeatureBand)) : _workloadManifestUpdater.CalculateManifestRollbacks(_fromRollbackDefinition); } @@ -233,7 +233,7 @@ internal static void TryRunGarbageCollection(IInstaller workloadInstaller, IRepo private void InstallWorkloadsWithInstallRecord( IEnumerable workloadIds, SdkFeatureBand sdkFeatureBand, - IEnumerable<(ManifestId manifestId, ManifestVersion existingVersion, ManifestVersion newVersion)> manifestsToUpdate, + IEnumerable<(ManifestId manifestId, ManifestVersion existingVersion, SdkFeatureBand existingFeatureBand, ManifestVersion newVersion, SdkFeatureBand newFeatureBand)> manifestsToUpdate, DirectoryPath? offlineCache) { if (_workloadInstaller.GetInstallationUnit().Equals(InstallationUnit.Packs)) @@ -249,7 +249,7 @@ private void InstallWorkloadsWithInstallRecord( foreach (var manifest in manifestsToUpdate) { - _workloadInstaller.InstallWorkloadManifest(manifest.manifestId, manifest.newVersion, sdkFeatureBand, offlineCache, rollback); + _workloadInstaller.InstallWorkloadManifest(manifest.manifestId, manifest.newVersion, manifest.newFeatureBand, offlineCache, rollback); } _workloadResolver.RefreshWorkloadManifests(); @@ -273,7 +273,7 @@ private void InstallWorkloadsWithInstallRecord( foreach (var manifest in manifestsToUpdate) { - _workloadInstaller.InstallWorkloadManifest(manifest.manifestId, manifest.existingVersion, sdkFeatureBand, offlineCache: null, isRollback: true); + _workloadInstaller.InstallWorkloadManifest(manifest.manifestId, manifest.existingVersion, manifest.existingFeatureBand, offlineCache: null, isRollback: true); } foreach (var packId in workloadPackToInstall) diff --git a/src/Cli/dotnet/commands/dotnet-workload/install/WorkloadManifestUpdater.cs b/src/Cli/dotnet/commands/dotnet-workload/install/WorkloadManifestUpdater.cs index c03c1132e343..ccb6f0d2ec0f 100644 --- a/src/Cli/dotnet/commands/dotnet-workload/install/WorkloadManifestUpdater.cs +++ b/src/Cli/dotnet/commands/dotnet-workload/install/WorkloadManifestUpdater.cs @@ -165,11 +165,19 @@ public static void AdvertiseWorkloadUpdates() public IEnumerable<( ManifestId manifestId, ManifestVersion existingVersion, + SdkFeatureBand existingFeatureBand, ManifestVersion newVersion, - Dictionary Workloads)> CalculateManifestUpdates() + SdkFeatureBand newFeatureBand, + Dictionary Workloads + )> + CalculateManifestUpdates() { var manifestUpdates = - new List<(ManifestId, ManifestVersion, ManifestVersion, + new List<(ManifestId manifestId, + ManifestVersion existingVersion, + SdkFeatureBand existingFeatureBand, + ManifestVersion newVersion, + SdkFeatureBand newFeatureBand, Dictionary Workloads)>(); var currentManifestIds = GetInstalledManifestIds(); foreach (var manifestId in currentManifestIds) @@ -182,10 +190,10 @@ public static void AdvertiseWorkloadUpdates() } if (advertisingManifestVersionAndWorkloads != null && - advertisingManifestVersionAndWorkloads.Value.ManifestVersion.CompareTo(currentManifestVersion) > 0) + advertisingManifestVersionAndWorkloads.Value.ManifestVersion.CompareTo(currentManifestVersion.Item1) > 0) { - manifestUpdates.Add((manifestId, currentManifestVersion, - advertisingManifestVersionAndWorkloads.Value.ManifestVersion, + manifestUpdates.Add((manifestId, currentManifestVersion.Item1, currentManifestVersion.Item2, + advertisingManifestVersionAndWorkloads.Value.ManifestVersion, advertisingManifestVersionAndWorkloads.Value.ManifestFeatureBand, advertisingManifestVersionAndWorkloads.Value.Workloads)); } } @@ -207,7 +215,7 @@ public IEnumerable GetUpdatableWorkloadsToAdvertise(IEnumerable CalculateManifestRollbacks(string rollbackDefinitionFilePath) + public IEnumerable<(ManifestId manifestId, ManifestVersion existingVersion, SdkFeatureBand existingFeatureBand, ManifestVersion newVersion, SdkFeatureBand newFeatureBand)> CalculateManifestRollbacks(string rollbackDefinitionFilePath) { var currentManifestIds = GetInstalledManifestIds(); var manifestRollbacks = ParseRollbackDefinitionFile(rollbackDefinitionFilePath); @@ -220,7 +228,11 @@ public IEnumerable GetUpdatableWorkloadsToAdvertise(IEnumerable (manifest.Item1, GetInstalledManifestVersion(manifest.Item1), manifest.Item2)); + .Select(manifest => + { + var installedManifestInfo = GetInstalledManifestVersion(manifest.id); + return (manifest.id, installedManifestInfo.manifestVersion, installedManifestInfo.sdkFeatureBand, manifest.version, manifest.featureBand); + }); return manifestUpdates; } @@ -365,7 +377,7 @@ private async Task UpdateAdvertisingManifestAsync(ManifestId manifestId, bool in } } - private (ManifestVersion ManifestVersion, Dictionary Workloads)? + private (ManifestVersion ManifestVersion, SdkFeatureBand ManifestFeatureBand, Dictionary Workloads)? GetAdvertisingManifestVersionAndWorkloads(ManifestId manifestId) { var manifestPath = Path.Combine(GetAdvertisingManifestPath(_sdkFeatureBand, manifestId), @@ -378,11 +390,14 @@ private async Task UpdateAdvertisingManifestAsync(ManifestId manifestId, bool in using (FileStream fsSource = new FileStream(manifestPath, FileMode.Open, FileAccess.Read)) { var manifest = WorkloadManifestReader.ReadWorkloadManifest(manifestId.ToString(), fsSource, manifestPath); - return (new ManifestVersion(manifest.Version), manifest.Workloads.Values.OfType().ToDictionary(w => w.Id)); + + // TODO: figure out how to differentiate between the feature band an advertising manifest is branded as and the feature band of the SDK + // it's advertised to + return (new ManifestVersion(manifest.Version), _sdkFeatureBand, manifest.Workloads.Values.OfType().ToDictionary(w => w.Id)); } } - private ManifestVersion GetInstalledManifestVersion(ManifestId manifestId) + private (ManifestVersion manifestVersion, SdkFeatureBand sdkFeatureBand) GetInstalledManifestVersion(ManifestId manifestId) { var manifest = _workloadResolver.GetInstalledManifests() @@ -391,7 +406,7 @@ private ManifestVersion GetInstalledManifestVersion(ManifestId manifestId) { throw new Exception(string.Format(LocalizableStrings.ManifestDoesNotExist, manifestId.ToString())); } - return new ManifestVersion(manifest.Version); + return (new ManifestVersion(manifest.Version), new SdkFeatureBand(manifest.ManifestFeatureBand)); } private bool AdManifestSentinelIsDueForUpdate() @@ -437,7 +452,7 @@ private async Task NewerManifestPackageExists(ManifestId manifest) } } - private IEnumerable<(ManifestId, ManifestVersion)> ParseRollbackDefinitionFile(string rollbackDefinitionFilePath) + private IEnumerable<(ManifestId id, ManifestVersion version, SdkFeatureBand featureBand)> ParseRollbackDefinitionFile(string rollbackDefinitionFilePath) { string fileContent; @@ -457,7 +472,22 @@ private async Task NewerManifestPackageExists(ManifestId manifest) } } return JsonSerializer.Deserialize>(fileContent) - .Select(manifest => (new ManifestId(manifest.Key), new ManifestVersion(manifest.Value))); + .Select(manifest => + { + ManifestVersion manifestVersion; + SdkFeatureBand manifestFeatureBand; + var parts = manifest.Value.Split('/'); + manifestVersion = new ManifestVersion(parts[0]); + if (parts.Length == 1) + { + manifestFeatureBand = _sdkFeatureBand; + } + else + { + manifestFeatureBand = new SdkFeatureBand(parts[1]); + } + return (new ManifestId(manifest.Key), manifestVersion, manifestFeatureBand); + }); } private bool BackgroundUpdatesAreDisabled() => diff --git a/src/Cli/dotnet/commands/dotnet-workload/list/WorkloadListCommand.cs b/src/Cli/dotnet/commands/dotnet-workload/list/WorkloadListCommand.cs index 7c0c2341b8cd..85a6eec49e95 100644 --- a/src/Cli/dotnet/commands/dotnet-workload/list/WorkloadListCommand.cs +++ b/src/Cli/dotnet/commands/dotnet-workload/list/WorkloadListCommand.cs @@ -150,12 +150,11 @@ internal UpdateAvailableEntry[] GetUpdateAvailable(IEnumerable insta { HashSet installedWorkloads = installedList.ToHashSet(); _workloadManifestUpdater.UpdateAdvertisingManifestsAsync(_includePreviews).Wait(); - IEnumerable<(ManifestId manifestId, ManifestVersion existingVersion, ManifestVersion newVersion, - Dictionary Workloads)> manifestsToUpdate = + var manifestsToUpdate = _workloadManifestUpdater.CalculateManifestUpdates(); List updateList = new(); - foreach ((ManifestId _, ManifestVersion existingVersion, ManifestVersion newVersion, + foreach ((ManifestId _, ManifestVersion existingVersion, SdkFeatureBand existingFeatureBand, ManifestVersion newVersion, SdkFeatureBand newFeatureBand, Dictionary workloads) in manifestsToUpdate) { foreach ((WorkloadId WorkloadId, WorkloadDefinition workloadDefinition) in @@ -163,6 +162,7 @@ internal UpdateAvailableEntry[] GetUpdateAvailable(IEnumerable insta { if (installedWorkloads.Contains(new WorkloadId(WorkloadId.ToString()))) { + // TODO: Potentially show existing and new feature bands updateList.Add(new UpdateAvailableEntry(existingVersion.ToString(), newVersion.ToString(), workloadDefinition.Description, WorkloadId.ToString())); diff --git a/src/Cli/dotnet/commands/dotnet-workload/update/WorkloadUpdateCommand.cs b/src/Cli/dotnet/commands/dotnet-workload/update/WorkloadUpdateCommand.cs index de7b54bf18f8..320613309dba 100644 --- a/src/Cli/dotnet/commands/dotnet-workload/update/WorkloadUpdateCommand.cs +++ b/src/Cli/dotnet/commands/dotnet-workload/update/WorkloadUpdateCommand.cs @@ -127,7 +127,7 @@ public override int Execute() } else if (_printRollbackDefinitionOnly) { - var manifests = _workloadResolver.GetInstalledManifests().ToDictionary(m => m.Id, m => m.Version, StringComparer.OrdinalIgnoreCase); + var manifests = _workloadResolver.GetInstalledManifests().ToDictionary(m => m.Id, m => m.Version + "/" + m.ManifestFeatureBand, StringComparer.OrdinalIgnoreCase); _reporter.WriteLine("==workloadRollbackDefinitionJsonOutputStart=="); _reporter.WriteLine(JsonSerializer.Serialize(manifests)); @@ -159,7 +159,7 @@ public void UpdateWorkloads(bool includePreviews = false, DirectoryPath? offline _workloadManifestUpdater.UpdateAdvertisingManifestsAsync(includePreviews, offlineCache).Wait(); var manifestsToUpdate = string.IsNullOrWhiteSpace(_fromRollbackDefinition) ? - _workloadManifestUpdater.CalculateManifestUpdates().Select(m => (m.manifestId, m.existingVersion, m.newVersion)) : + _workloadManifestUpdater.CalculateManifestUpdates().Select(m => (m.manifestId, m.existingVersion, m.existingFeatureBand, m.newVersion, m.newFeatureBand)) : _workloadManifestUpdater.CalculateManifestRollbacks(_fromRollbackDefinition); UpdateWorkloadsWithInstallRecord(workloadIds, featureBand, manifestsToUpdate, offlineCache); @@ -176,7 +176,7 @@ public void UpdateWorkloads(bool includePreviews = false, DirectoryPath? offline private void UpdateWorkloadsWithInstallRecord( IEnumerable workloadIds, SdkFeatureBand sdkFeatureBand, - IEnumerable<(ManifestId manifestId, ManifestVersion existingVersion, ManifestVersion newVersion)> manifestsToUpdate, + IEnumerable<(ManifestId manifestId, ManifestVersion existingVersion, SdkFeatureBand existingFeatureBand, ManifestVersion newVersion, SdkFeatureBand newFeatureBand)> manifestsToUpdate, DirectoryPath? offlineCache = null) { if (_workloadInstaller.GetInstallationUnit().Equals(InstallationUnit.Packs)) @@ -191,7 +191,7 @@ private void UpdateWorkloadsWithInstallRecord( foreach (var manifest in manifestsToUpdate) { - _workloadInstaller.InstallWorkloadManifest(manifest.manifestId, manifest.newVersion, sdkFeatureBand, offlineCache, rollback); + _workloadInstaller.InstallWorkloadManifest(manifest.manifestId, manifest.newVersion, manifest.newFeatureBand, offlineCache, rollback); } _workloadResolver.RefreshWorkloadManifests(); diff --git a/src/Tests/dotnet-workload-install.Tests/GivenDotnetWorkloadInstall.cs b/src/Tests/dotnet-workload-install.Tests/GivenDotnetWorkloadInstall.cs index 876aefa586da..86a765989943 100644 --- a/src/Tests/dotnet-workload-install.Tests/GivenDotnetWorkloadInstall.cs +++ b/src/Tests/dotnet-workload-install.Tests/GivenDotnetWorkloadInstall.cs @@ -167,10 +167,14 @@ public void GivenWorkloadInstallItCanUpdateInstalledManifests(bool userLocal, st var parseResult = Parser.Instance.Parse(new string[] {"dotnet", "workload", "install", "xamarin-android"}); var manifestsToUpdate = - new (ManifestId, ManifestVersion, ManifestVersion, Dictionary - Workloads)[] + new (ManifestId manifestId, + ManifestVersion existingVersion, + SdkFeatureBand existingFeatureBand, + ManifestVersion newVersion, + SdkFeatureBand newFeatureBand, + Dictionary Workloads)[] { - (new ManifestId("mock-manifest"), new ManifestVersion("1.0.0"), new ManifestVersion("2.0.0"), + (new ManifestId("mock-manifest"), new ManifestVersion("1.0.0"), new SdkFeatureBand(sdkVersion), new ManifestVersion("2.0.0"), new SdkFeatureBand(sdkVersion), null), }; (_, var installManager, var installer, _, _, _) = @@ -178,8 +182,8 @@ public void GivenWorkloadInstallItCanUpdateInstalledManifests(bool userLocal, st installManager.InstallWorkloads(new List(), false); // Don't actually do any installs, just update manifests - installer.InstalledManifests[0].manifestId.Should().Be(manifestsToUpdate[0].Item1); - installer.InstalledManifests[0].manifestVersion.Should().Be(manifestsToUpdate[0].Item3); + installer.InstalledManifests[0].manifestId.Should().Be(manifestsToUpdate[0].manifestId); + installer.InstalledManifests[0].manifestVersion.Should().Be(manifestsToUpdate[0].newVersion); installer.InstalledManifests[0].sdkFeatureBand.Should().Be(new SdkFeatureBand("6.0.100")); installer.InstalledManifests[0].offlineCache.Should().Be(null); } @@ -192,10 +196,14 @@ public void GivenWorkloadInstallItCanUpdateInstalledManifests(bool userLocal, st public void GivenWorkloadInstallFromCacheItInstallsCachedManifest(bool userLocal, string sdkVersion) { var manifestsToUpdate = - new (ManifestId, ManifestVersion, ManifestVersion, Dictionary - Workloads)[] + new (ManifestId manifestId, + ManifestVersion existingVersion, + SdkFeatureBand existingFeatureBand, + ManifestVersion newVersion, + SdkFeatureBand newFeatureBand, + Dictionary Workloads)[] { - (new ManifestId("mock-manifest"), new ManifestVersion("1.0.0"), new ManifestVersion("2.0.0"), + (new ManifestId("mock-manifest"), new ManifestVersion("1.0.0"), new SdkFeatureBand(sdkVersion), new ManifestVersion("2.0.0"), new SdkFeatureBand(sdkVersion), null) }; var cachePath = Path.Combine(_testAssetsManager.CreateTestDirectory(identifier: AppendForUserLocal("mockCache_", userLocal) + sdkVersion).Path, @@ -209,8 +217,8 @@ public void GivenWorkloadInstallFromCacheItInstallsCachedManifest(bool userLocal installManager.Execute(); - installer.InstalledManifests[0].manifestId.Should().Be(manifestsToUpdate[0].Item1); - installer.InstalledManifests[0].manifestVersion.Should().Be(manifestsToUpdate[0].Item3); + installer.InstalledManifests[0].manifestId.Should().Be(manifestsToUpdate[0].manifestId); + installer.InstalledManifests[0].manifestVersion.Should().Be(manifestsToUpdate[0].newVersion); installer.InstalledManifests[0].sdkFeatureBand.Should().Be(new SdkFeatureBand("6.0.100")); installer.InstalledManifests[0].offlineCache.Should().Be(new DirectoryPath(cachePath)); } @@ -346,7 +354,12 @@ public void GivenWorkloadInstallItDoesNotRemoveOldInstallsOnRollback(bool userLo string sdkVersion, [CallerMemberName] string testName = "", string failingWorkload = null, - IEnumerable<(ManifestId, ManifestVersion, ManifestVersion, Dictionary Workloads)> manifestUpdates = null, + IEnumerable<(ManifestId manifestId, + ManifestVersion existingVersion, + SdkFeatureBand existingFeatureBand, + ManifestVersion newVersion, + SdkFeatureBand newFeatureBand, + Dictionary Workloads)> manifestUpdates = null, string tempDirManifestPath = null) { _reporter.Clear(); @@ -474,10 +487,14 @@ public void ShowManifestUpdatesWhenVerbosityIsDetailedOrDiagnostic(string verbos var parseResult = Parser.Instance.Parse(new string[] { "dotnet", "workload", "install", verbosityFlag, "xamarin-android" }); var manifestsToUpdate = - new (ManifestId, ManifestVersion, ManifestVersion, Dictionary - Workloads)[] + new (ManifestId manifestId, + ManifestVersion existingVersion, + SdkFeatureBand existingFeatureBand, + ManifestVersion newVersion, + SdkFeatureBand newFeatureBand, + Dictionary Workloads)[] { - (new ManifestId("mock-manifest"), new ManifestVersion("1.0.0"), new ManifestVersion("2.0.0"), + (new ManifestId("mock-manifest"), new ManifestVersion("1.0.0"), new SdkFeatureBand("6.0.300"), new ManifestVersion("2.0.0"), new SdkFeatureBand("6.0.300"), null), }; (_, var installManager, var installer, _, _, _) = @@ -488,7 +505,7 @@ public void ShowManifestUpdatesWhenVerbosityIsDetailedOrDiagnostic(string verbos 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")); } - + private string AppendForUserLocal(string identifier, bool userLocal) { if (!userLocal) diff --git a/src/Tests/dotnet-workload-install.Tests/GivenWorkloadManifestUpdater.cs b/src/Tests/dotnet-workload-install.Tests/GivenWorkloadManifestUpdater.cs index dfebddec2d5f..4628c0a05f5d 100644 --- a/src/Tests/dotnet-workload-install.Tests/GivenWorkloadManifestUpdater.cs +++ b/src/Tests/dotnet-workload-install.Tests/GivenWorkloadManifestUpdater.cs @@ -147,16 +147,16 @@ public void GivenWorkloadManifestRollbackItCanCalculateUpdates() var testDir = _testAssetsManager.CreateTestDirectory().Path; var featureBand = "6.0.100"; var dotnetRoot = Path.Combine(testDir, "dotnet"); - var expectedManifestUpdates = new (ManifestId, ManifestVersion, ManifestVersion)[] { - (new ManifestId("test-manifest-1"), new ManifestVersion("5.0.0"), new ManifestVersion("4.0.0")), - (new ManifestId("test-manifest-2"), new ManifestVersion("3.0.0"), new ManifestVersion("2.0.0")) }; + var expectedManifestUpdates = new (ManifestId, ManifestVersion, SdkFeatureBand, ManifestVersion, SdkFeatureBand)[] { + (new ManifestId("test-manifest-1"), new ManifestVersion("5.0.0"), new SdkFeatureBand("6.0.100"), new ManifestVersion("4.0.0"), new SdkFeatureBand("6.0.100")), + (new ManifestId("test-manifest-2"), new ManifestVersion("3.0.0"), new SdkFeatureBand("6.0.100"), new ManifestVersion("2.0.0"), new SdkFeatureBand("6.0.100")) }; // Write mock manifests var installedManifestDir = Path.Combine(testDir, "dotnet", "sdk-manifests", featureBand); var adManifestDir = Path.Combine(testDir, ".dotnet", "sdk-advertising", featureBand); Directory.CreateDirectory(installedManifestDir); Directory.CreateDirectory(adManifestDir); - foreach ((var manifestId, var existingVersion, _) in expectedManifestUpdates) + foreach ((var manifestId, var existingVersion, var existingFeatureBand, _, _) in expectedManifestUpdates) { Directory.CreateDirectory(Path.Combine(installedManifestDir, manifestId.ToString())); File.WriteAllText(Path.Combine(installedManifestDir, manifestId.ToString(), _manifestFileName), GetManifestContent(existingVersion)); diff --git a/src/Tests/dotnet-workload-install.Tests/MockWorkloadManifestUpdater.cs b/src/Tests/dotnet-workload-install.Tests/MockWorkloadManifestUpdater.cs index fb77c78532cc..3e7581c7e67e 100644 --- a/src/Tests/dotnet-workload-install.Tests/MockWorkloadManifestUpdater.cs +++ b/src/Tests/dotnet-workload-install.Tests/MockWorkloadManifestUpdater.cs @@ -3,8 +3,10 @@ using System.Collections.Generic; using System.IO; +using System.Linq; using System.Threading.Tasks; using Microsoft.DotNet.Workloads.Workload.Install; +using Microsoft.DotNet.Workloads.Workload.Install.InstallRecord; using Microsoft.Extensions.EnvironmentAbstractions; using Microsoft.NET.Sdk.WorkloadManifestReader; @@ -16,12 +18,27 @@ internal class MockWorkloadManifestUpdater : IWorkloadManifestUpdater public int CalculateManifestUpdatesCallCount = 0; public int DownloadManifestPackagesCallCount = 0; public int ExtractManifestPackagesToTempDirCallCount = 0; - private IEnumerable<(ManifestId, ManifestVersion, ManifestVersion, Dictionary Workloads)> _manifestUpdates; + private IEnumerable<(ManifestId manifestId, + ManifestVersion existingVersion, + SdkFeatureBand existingFeatureBand, + ManifestVersion newVersion, + SdkFeatureBand newFeatureBand, + Dictionary Workloads)> _manifestUpdates; private string _tempDirManifestPath; - public MockWorkloadManifestUpdater(IEnumerable<(ManifestId, ManifestVersion, ManifestVersion, Dictionary Workloads)> manifestUpdates = null, string tempDirManifestPath = null) + public MockWorkloadManifestUpdater(IEnumerable<(ManifestId manifestId, + ManifestVersion existingVersion, + SdkFeatureBand existingFeatureBand, + ManifestVersion newVersion, + SdkFeatureBand newFeatureBand, + Dictionary Workloads)> manifestUpdates = null, string tempDirManifestPath = null) { - _manifestUpdates = manifestUpdates ?? new List<(ManifestId, ManifestVersion, ManifestVersion, Dictionary Workloads)>(); + _manifestUpdates = manifestUpdates ?? new List<(ManifestId manifestId, + ManifestVersion existingVersion, + SdkFeatureBand existingFeatureBand, + ManifestVersion newVersion, + SdkFeatureBand newFeatureBand, + Dictionary Workloads)>(); _tempDirManifestPath = tempDirManifestPath; } @@ -34,7 +51,9 @@ public Task UpdateAdvertisingManifestsAsync(bool includePreview, DirectoryPath? public IEnumerable<( ManifestId manifestId, ManifestVersion existingVersion, + SdkFeatureBand existingFeatureBand, ManifestVersion newVersion, + SdkFeatureBand newFeatureBand, Dictionary Workloads)> CalculateManifestUpdates() { CalculateManifestUpdatesCallCount++; @@ -63,8 +82,12 @@ public IEnumerable GetManifestPackageUrls(bool includePreviews) return new string[] { "mock-manifest-url" }; } + public IEnumerable<(ManifestId manifestId, ManifestVersion existingVersion, SdkFeatureBand existingFeatureBand, ManifestVersion newVersion, SdkFeatureBand newFeatureBand)> CalculateManifestRollbacks(string rollbackDefinitionFilePath) + { + return _manifestUpdates.Select(t => (t.manifestId, t.existingVersion, t.existingFeatureBand, t.newVersion, t.newFeatureBand)); + } + public Task BackgroundUpdateAdvertisingManifestsWhenRequiredAsync() => throw new System.NotImplementedException(); - public IEnumerable<(ManifestId manifestId, ManifestVersion existingVersion, ManifestVersion newVersion)> CalculateManifestRollbacks(string rollbackDefinitionFilePath) => throw new System.NotImplementedException(); public IEnumerable GetUpdatableWorkloadsToAdvertise(IEnumerable installedWorkloads) => throw new System.NotImplementedException(); public void DeleteUpdatableWorkloadsFile() { } } diff --git a/src/Tests/dotnet-workload-list.Tests/GivenWorkloadInstallerAndWorkloadsInstalled.cs b/src/Tests/dotnet-workload-list.Tests/GivenWorkloadInstallerAndWorkloadsInstalled.cs index 3dd57df289cc..2cdfc4ec093b 100644 --- a/src/Tests/dotnet-workload-list.Tests/GivenWorkloadInstallerAndWorkloadsInstalled.cs +++ b/src/Tests/dotnet-workload-list.Tests/GivenWorkloadInstallerAndWorkloadsInstalled.cs @@ -31,8 +31,12 @@ public class GivenInstalledWorkloadAndManifestUpdater : SdkTest private WorkloadListCommand _workloadListCommand; private string _testDirectory; - private List<(ManifestId, ManifestVersion, ManifestVersion, Dictionary - Workloads)> _mockManifestUpdates; + private List<(ManifestId manifestId, + ManifestVersion existingVersion, + SdkFeatureBand existingFeatureBand, + ManifestVersion newVersion, + SdkFeatureBand newFeatureBand, + Dictionary Workloads)> _mockManifestUpdates; private MockNuGetPackageDownloader _nugetDownloader; private string _dotnetRoot; @@ -46,13 +50,15 @@ private void Setup(string identifier) _testDirectory = _testAssetsManager.CreateTestDirectory(identifier: identifier).Path; _dotnetRoot = Path.Combine(_testDirectory, "dotnet"); _nugetDownloader = new(_dotnetRoot); - + _mockManifestUpdates = new() { ( new ManifestId("manifest1"), new ManifestVersion(CurrentSdkVersion), + new SdkFeatureBand("6.0.300"), new ManifestVersion(UpdateAvailableVersion), + new SdkFeatureBand("6.0.300"), new Dictionary { [new WorkloadId(InstallingWorkload)] = new( @@ -65,7 +71,9 @@ private void Setup(string identifier) ( new ManifestId("manifest-other"), new ManifestVersion(CurrentSdkVersion), + new SdkFeatureBand("6.0.300"), new ManifestVersion("7.0.101"), + new SdkFeatureBand("6.0.300"), new Dictionary { [new WorkloadId("other-manifest-workload")] = new( @@ -76,7 +84,9 @@ private void Setup(string identifier) ( new ManifestId("manifest-older-version"), new ManifestVersion(CurrentSdkVersion), + new SdkFeatureBand("6.0.300"), new ManifestVersion("6.0.100"), + new SdkFeatureBand("6.0.300"), new Dictionary { [new WorkloadId("other-manifest-workload")] = new( diff --git a/src/Tests/dotnet-workload-update.Tests/GivenDotnetWorkloadUpdate.cs b/src/Tests/dotnet-workload-update.Tests/GivenDotnetWorkloadUpdate.cs index fef7dfd5c0ce..5001b60442bf 100644 --- a/src/Tests/dotnet-workload-update.Tests/GivenDotnetWorkloadUpdate.cs +++ b/src/Tests/dotnet-workload-update.Tests/GivenDotnetWorkloadUpdate.cs @@ -338,17 +338,91 @@ public void GivenPrintRollbackDefinitionItIncludesAllInstalledManifests() string.Join("", _reporter.Lines).Should().Contain("SampleManifest"); } + [Theory] + [InlineData("6.0.200", "6.0.200")] + [InlineData("6.0.200", "6.0.100")] + [InlineData("6.0.100", "6.0.200")] + [InlineData("5.0.100", "6.0.100")] + [InlineData("6.0.100", "5.0.100")] + [InlineData("5.0.100", "6.0.300")] + [InlineData("6.0.300", "5.0.100")] + public void ApplyRollbackAcrossFeatureBand(string existingSdkFeatureBand, string newSdkFeatureBand) + { + var parseResult = Parser.Instance.Parse(new string[] { "dotnet", "workload", "update", "--from-rollback-file", "rollback.json" }); + + var manifestsToUpdate = + new (ManifestId manifestId, + ManifestVersion existingVersion, + SdkFeatureBand existingFeatureBand, + ManifestVersion newVersion, + SdkFeatureBand newFeatureBand, + Dictionary Workloads)[] + { + (new ManifestId("mock-manifest"), new ManifestVersion("1.0.0"), new SdkFeatureBand(existingSdkFeatureBand), new ManifestVersion("2.0.0"), new SdkFeatureBand(newSdkFeatureBand), + null), + }; + + (_, var updateCommand, var packInstaller, var workloadResolver, var workloadManifestUpdater, var nuGetPackageDownloader) = GetTestInstallers(parseResult, manifestUpdates: manifestsToUpdate, sdkVersion: "6.0.300", identifier: existingSdkFeatureBand + newSdkFeatureBand); + + updateCommand.UpdateWorkloads(); + + packInstaller.InstalledManifests[0].manifestId.Should().Be(manifestsToUpdate[0].manifestId); + packInstaller.InstalledManifests[0].manifestVersion.Should().Be(manifestsToUpdate[0].newVersion); + packInstaller.InstalledManifests[0].sdkFeatureBand.Should().Be(new SdkFeatureBand(newSdkFeatureBand)); + packInstaller.InstalledManifests[0].offlineCache.Should().Be(null); + } + + [Fact] + public void ApplyRollbackWithMultipleManifestsAcrossFeatureBand() + { + var parseResult = Parser.Instance.Parse(new string[] { "dotnet", "workload", "update", "--from-rollback-file", "rollback.json" }); + + var manifestsToUpdate = + new (ManifestId manifestId, + ManifestVersion existingVersion, + SdkFeatureBand existingFeatureBand, + ManifestVersion newVersion, + SdkFeatureBand newFeatureBand, + Dictionary Workloads)[] + { + (new ManifestId("mock-manifest-1"), new ManifestVersion("1.0.0"), new SdkFeatureBand("6.0.300"), new ManifestVersion("2.0.0"), new SdkFeatureBand("6.0.100"), + null), + (new ManifestId("mock-manifest-2"), new ManifestVersion("1.0.0"), new SdkFeatureBand("6.0.100"), new ManifestVersion("2.0.0"), new SdkFeatureBand("6.0.300"), + null), + (new ManifestId("mock-manifest-3"), new ManifestVersion("1.0.0"), new SdkFeatureBand("5.0.100"), new ManifestVersion("2.0.0"), new SdkFeatureBand("6.0.100"), + null), + }; + + (_, var updateCommand, var packInstaller, var workloadResolver, var workloadManifestUpdater, var nuGetPackageDownloader) = GetTestInstallers(parseResult, manifestUpdates: manifestsToUpdate, sdkVersion: "6.0.300"); + + updateCommand.UpdateWorkloads(); + + packInstaller.InstalledManifests[0].manifestId.Should().Be(manifestsToUpdate[0].manifestId); + packInstaller.InstalledManifests[0].manifestVersion.Should().Be(manifestsToUpdate[0].newVersion); + packInstaller.InstalledManifests[0].sdkFeatureBand.Should().Be(new SdkFeatureBand("6.0.100")); + packInstaller.InstalledManifests[1].sdkFeatureBand.Should().Be(new SdkFeatureBand("6.0.300")); + packInstaller.InstalledManifests[2].sdkFeatureBand.Should().Be(new SdkFeatureBand("6.0.100")); + packInstaller.InstalledManifests[0].offlineCache.Should().Be(null); + } + internal (string, WorkloadUpdateCommand, MockPackWorkloadInstaller, IWorkloadResolver, MockWorkloadManifestUpdater, MockNuGetPackageDownloader) GetTestInstallers( ParseResult parseResult, [CallerMemberName] string testName = "", string failingWorkload = null, string failingPack = null, - IEnumerable<(ManifestId, ManifestVersion, ManifestVersion, Dictionary Workloads)> manifestUpdates = null, + IEnumerable<(ManifestId manifestId, + ManifestVersion existingVersion, + SdkFeatureBand existingFeatureBand, + ManifestVersion newVersion, + SdkFeatureBand newFeatureBand, + Dictionary Workloads)> manifestUpdates = null, IList installedWorkloads = null, - bool includeInstalledPacks = false) + bool includeInstalledPacks = false, + string sdkVersion = "6.0.100", + string identifier = null) { _reporter.Clear(); - var testDirectory = _testAssetsManager.CreateTestDirectory(testName: testName).Path; + var testDirectory = _testAssetsManager.CreateTestDirectory(testName: testName, identifier).Path; var dotnetRoot = Path.Combine(testDirectory, "dotnet"); var installedPacks = new PackInfo[] { CreatePackInfo("Xamarin.Android.Sdk", "8.4.7", WorkloadPackKind.Sdk, Path.Combine(dotnetRoot, "packs", "Xamarin.Android.Sdk", "8.4.7"), "Xamarin.Android.Sdk"), @@ -369,7 +443,7 @@ public void GivenPrintRollbackDefinitionItIncludesAllInstalledManifests() workloadManifestUpdater: manifestUpdater, dotnetDir: dotnetRoot, userProfileDir: testDirectory, - version: "6.0.100"); + version: sdkVersion); return (testDirectory, installManager, installer, workloadResolver, manifestUpdater, nugetDownloader); }