Skip to content

Commit

Permalink
Merge pull request #235 from dotnet/enable-removing-7
Browse files Browse the repository at this point in the history
allow management of 7.0 SDKs and Runtimes
  • Loading branch information
marcpopMSFT authored Dec 13, 2022
2 parents 332017a + 0eab6c3 commit 9b354de
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 26 deletions.
9 changes: 9 additions & 0 deletions src/dotnet-core-uninstall/Shared/BundleInfo/Bundle.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@ public override string ToString()
{
return $"{Version.ToString()} ({Arch.ToString().ToLower()})";
}

public virtual string ToDebugString()
{
return $"{Version.ToString()} ({Arch.ToString().ToLower()})";
}
}

internal class Bundle<TBundleVersion> : Bundle, IComparable, IComparable<Bundle>, IEquatable<Bundle<TBundleVersion>>
Expand Down Expand Up @@ -104,5 +109,9 @@ public override int GetHashCode()
{
return HashCode.Combine(base.GetHashCode());
}

public override string ToDebugString() {
return $"{nameof(TBundleVersion)} {Version.ToString()} ({Arch.ToString().ToLower()}) - {UninstallCommand ?? "n/a"}";
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ namespace Microsoft.DotNet.Tools.Uninstall.Shared.VSVersioning
internal static class VisualStudioSafeVersionsExtractor
{
// The tool should not be used to uninstall any more recent versions of the sdk
public static readonly SemanticVersion UpperLimit = new SemanticVersion(7, 0, 0);
public static readonly SemanticVersion UpperLimit = new SemanticVersion(8, 0, 0);

// Must keep one of each of these divisions to ensure Visual Studio works.
// Pairs are [inclusive, exclusive)
Expand All @@ -25,7 +25,8 @@ internal static class VisualStudioSafeVersionsExtractor
{ (new SemanticVersion(2, 1, 600), new SemanticVersion(2, 1, 900)), string.Format(LocalizableStrings.WindowsRequirementExplainationString, " 2019") },
{ (new SemanticVersion(2, 2, 100), new SemanticVersion(2, 2, 200)), string.Format(LocalizableStrings.WindowsRequirementExplainationString, " 2017") },
{ (new SemanticVersion(2, 2, 200), new SemanticVersion(2, 2, 500)), string.Format(LocalizableStrings.WindowsRequirementExplainationString, " 2019") },
{ (new SemanticVersion(2, 2, 500), UpperLimit), string.Format(LocalizableStrings.WindowsRequirementExplainationString, "") }
{ (new SemanticVersion(3, 0, 100), new SemanticVersion(5, 0, 600)), string.Format(LocalizableStrings.WindowsRequirementExplainationString, " 2019") },
{ (new SemanticVersion(6, 0, 100), UpperLimit), string.Format(LocalizableStrings.WindowsRequirementExplainationString, "") }
};

private static (IDictionary<IEnumerable<Bundle>, string>, IEnumerable<Bundle>) ApplyWindowsVersionDivisions(IEnumerable<Bundle> bundleList)
Expand Down
1 change: 1 addition & 0 deletions src/dotnet-core-uninstall/dotnet-core-uninstall.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
<RuntimeIdentifiers>win-x86;osx-x64</RuntimeIdentifiers>
<SignAssembly>true</SignAssembly>
<TargetFramework>netcoreapp3.1</TargetFramework>
<RollForward>LatestMajor</RollForward>
</PropertyGroup>

<PropertyGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.CommandLine.Parsing;
using System.Linq;
using FluentAssertions;
using FluentAssertions.Execution;
using Microsoft.DotNet.Tools.Uninstall.Shared.BundleInfo;
using Microsoft.DotNet.Tools.Uninstall.Shared.BundleInfo.Versioning;
using Microsoft.DotNet.Tools.Uninstall.Shared.Commands;
Expand All @@ -19,7 +20,7 @@ namespace Microsoft.DotNet.Tools.Uninstall.Tests.Shared.Commands
{
public class CommandBundleFilterTests
{
private static readonly string[] versions = { "1.0.0", "1.0.1", "1.1.0", "2.1.0", "2.1.500", "2.1.600", "2.2.100", "2.2.200", "5.0.0", "7.0.1", "10.10.10" };
private static readonly string[] versions = { "1.0.0", "1.0.1", "1.1.0", "2.1.0", "2.1.500", "2.1.600", "2.2.100", "2.2.200", "5.0.0", "7.0.1", "8.0.1", "10.10.10" };
private Dictionary<string, BundleArch> versionsWithArch = new Dictionary<string, BundleArch>
{
{ "3.0.0", BundleArch.X64 },
Expand All @@ -42,7 +43,7 @@ public class CommandBundleFilterTests
[InlineData("remove --sdk 1.0.1", new string[] { "1.0.1" })]
[InlineData("remove --sdk 1.0.0", new string[] { "1.0.0" })]
[InlineData("remove --sdk 1.0.1 2.1.0 1.0.1", new string[] { "2.1.0", "1.0.1", "1.0.1" })]
[InlineData("remove --sdk 1.0.0 1.0.1 1.1.0 2.1.0 2.1.500 2.1.600 2.2.100 2.2.200",
[InlineData("remove --sdk 1.0.0 1.0.1 1.1.0 2.1.0 2.1.500 2.1.600 2.2.100 2.2.200",
new string[] { "1.0.0", "1.0.1", "1.1.0", "2.1.0", "2.1.500", "2.1.600", "2.2.100", "2.2.200" })]
internal void TestRequiredUninstallableWhenExplicitlyAddedWindows(string command, string[] expectedUninstallable)
{
Expand Down Expand Up @@ -103,8 +104,14 @@ internal void TestRequiredUninstallableWithOptionsMac(string command, string[] e

internal void TestRequiredUninstallableWhenExplicitlyAdded(IEnumerable<Bundle> bundles, string command, string[] expectedUninstallableSdk, string[] expectedUninstallableRuntime)
{
using var scope = new AssertionScope();
scope.AddReportable("bundles", () => String.Join(Environment.NewLine, bundles.Select(b => b.ToDebugString())));
scope.AddReportable("command", () => command);
scope.AddReportable("expectedUninstallableSdk", () => String.Join(Environment.NewLine, expectedUninstallableSdk));
scope.AddReportable("expectedUninstallableRuntime", () => String.Join(Environment.NewLine, expectedUninstallableRuntime));
var parseResult = CommandLineConfigs.UninstallRootCommand.Parse(command);
var uninstallableBundles = CommandBundleFilter.GetFilteredBundles(bundles, parseResult);
scope.AddReportable("uninstallableBundles", () => String.Join(Environment.NewLine, uninstallableBundles.Select(b => b.ToDebugString())));

var uninstallableSdks = uninstallableBundles.Where(b => b.Version is SdkVersion).Select(b => b.DisplayName);
var requiredSdks = bundles.Except(uninstallableBundles).Where(b => b.Version is SdkVersion).Select(b => b.DisplayName);
Expand All @@ -122,7 +129,7 @@ internal void TestRequiredUninstallableWhenExplicitlyAdded(IEnumerable<Bundle> b
}

[Theory]
[InlineData("remove {0} 7.0.1")]
[InlineData("remove {0} 8.0.1")]
[InlineData("remove {0} 10.10.10")]
[InlineData("remove {0} --all --force")]
[InlineData("remove {0} 1.0.0 1.0.1 1.1.0 2.1.0 2.1.500 2.1.600 2.2.100 2.2.200 5.0.0 7.0.1 10.10.10")]
Expand Down Expand Up @@ -158,13 +165,13 @@ internal void CheckUpperLimitAlwaysRequired(string command, IEnumerable<Bundle>
{
var parseResult = CommandLineConfigs.UninstallRootCommand.Parse(command);
Action filteringAction = () => CommandBundleFilter.GetFilteredBundles(bundles, parseResult);
filteringAction.Should().Throw<UninstallationNotAllowedException>();
filteringAction.Should().Throw<UninstallationNotAllowedException>("Expected command '{0}' to fail when the following bundles were installed: {1}", command, String.Join(", ", bundles.Select(b => b.DisplayName).ToList()));
}

[Fact]
public void TestHelpOutputContainsExplainationParagraph()
{
foreach (var command in new string[] { "dry-run -h", "whatif -h", "remove -h" })
foreach (var command in new string[] { "dry-run -h", "whatif -h", "remove -h" })
{
var console = new TestConsole();
_ = CommandLineConfigs.UninstallCommandParser.InvokeAsync(command, console).Result;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Linq;
using FluentAssertions;
using FluentAssertions.Execution;
using Microsoft.DotNet.Tools.Uninstall.Shared.BundleInfo;
using Microsoft.DotNet.Tools.Uninstall.Shared.BundleInfo.Versioning;
using Microsoft.DotNet.Tools.Uninstall.Shared.VSVersioning;
Expand All @@ -25,8 +27,8 @@ public class VSVersionTests
[InlineData(new string[] { "2.2.100", "2.2.200" }, new bool[] { false, false })]
[InlineData(new string[] { "2.2.100", "2.2.200", "2.2.300" }, new bool[] { false, true, false })]
[InlineData(new string[] { "3.0.0", "3.0.1", "5.0.0" }, new bool[] { true, true, false })]
[InlineData(new string[] { "5.0.0", "5.0.1", "6.0.1" }, new bool[] { true, true, false })]
[InlineData(new string[] { "6.0.0", "6.0.1", "7.0.0" }, new bool[] { true, false, false })]
[InlineData(new string[] { "5.0.0", "5.0.1", "6.0.1" }, new bool[] { true, false, true })]
[InlineData(new string[] { "6.0.0", "6.0.1", "7.0.0" }, new bool[] { true, true, false })]
[InlineData(new string[] { "9.0.0", "9.0.1", "10.100.100" }, new bool[] { false, false, false })]
internal void TestGetUninstallableWindows(string[] versions, bool[] allowed)
{
Expand All @@ -48,7 +50,7 @@ internal void TestGetUninstallableWindows(string[] versions, bool[] allowed)
[InlineData(new string[] { "1.0.0" }, new bool[] { false }, new string[] { "1.0.0" }, new bool[] { false })]
[InlineData(new string[] { "1.0.0", "1.0.1" }, new bool[] { true, false }, new string[] { "1.0.0", "1.0.1" }, new bool[] { true, false })]
[InlineData(new string[] { "2.1.0", "1.0.1" }, new bool[] { false, true }, new string[] { "1.0.0", "1.1.0" }, new bool[] { false, false })]
[InlineData(new string[] { "3.0.0", "7.0.0" }, new bool[] { false, false }, new string[] { "1.0.0", "1.1.0", "1.0.1", "1.0.2", "1.1.3" }, new bool[] { true, true, true, false, false })]
[InlineData(new string[] { "3.0.0", "7.0.0" }, new bool[] { true, false }, new string[] { "1.0.0", "1.1.0", "1.0.1", "1.0.2", "1.1.3" }, new bool[] { true, true, true, false, false })]
[InlineData(new string[] { "3.0.0", "5.0.0" }, new bool[] { true, false }, new string[] { "1.0.0", "1.1.0", "1.0.1", "5.0.0" }, new bool[] { true, false, false, false })]
[InlineData(new string[] { "5.0.0", "5.0.1", "10.100.100" }, new bool[] { true, false, false }, new string[] { "5.0.0", "10.0.0" }, new bool[] { false, false })]
[InlineData(new string[] { "5.0.0", "6.0.0", "6.0.1" }, new bool[] { true, true, false }, new string[] { "5.0.0" }, new bool[] { false })]
Expand Down Expand Up @@ -77,7 +79,7 @@ internal void TestGetUninstallableMac(string[] sdkVersions, bool[] sdkAllowed, s
[InlineData(new string[] { "2.1.500", "2.1.400", "2.1.600" }, new bool[] { false, true, false })]
[InlineData(new string[] { "2.2.100", "2.2.200", "2.2.300" }, new bool[] { false, true, false })]
[InlineData(new string[] { "5.0.0", "5.0.1", "10.0.1" }, new bool[] { true, false, false })]
[InlineData(new string[] { "5.0.0", "6.0.0", "6.0.1" }, new bool[] { true, true, false })]
[InlineData(new string[] { "5.0.0", "6.0.0", "6.0.1" }, new bool[] { false, true, true })]
[InlineData(new string[] { "9.0.0", "9.0.1", "10.100.100" }, new bool[] { false, false, false })]
internal void TestGetUninstallableNonSdkVersionsWindows(string[] versions, bool[] allowed)
{
Expand Down Expand Up @@ -113,7 +115,7 @@ internal void TestGetUninstallableNonSdkVersionsMac(string[] sdkVersions, bool[]
internal void TestGetUninstallableNonSdkVersions(IEnumerable<Bundle> bundles, bool[] sdkAllowed, bool[] runtimeAllowed)
{
bundles = bundles.Concat(new List<Bundle>
{
{
new Bundle<AspNetRuntimeVersion>(new AspNetRuntimeVersion("1.0.0"), new BundleArch(), string.Empty, "AspNetVersion"),
new Bundle<AspNetRuntimeVersion>(new AspNetRuntimeVersion("10.0.0"), new BundleArch(), string.Empty, "AspNetVersion"),
new Bundle<HostingBundleVersion>(new HostingBundleVersion("1.0.0"), new BundleArch(), string.Empty, "HostingBundleVersion"),
Expand All @@ -129,52 +131,55 @@ internal void TestGetUninstallableNonSdkVersions(IEnumerable<Bundle> bundles, bo
CheckAllowed(bundles, uninstallable, sdkAllowed, runtimeAllowed);
}

private void CheckAllowed(IEnumerable<Bundle> bundles, IEnumerable<Bundle> uninstallable, bool[] sdkAllowed, bool[] runtimeAllowed)
private void CheckAllowed(IEnumerable<Bundle> allBundles, IEnumerable<Bundle> uninstallableBundles, bool[] sdkAllowed, bool[] runtimeAllowed)
{
var sdkBundles = bundles.Where(bundle => bundle.Version is SdkVersion).ToArray();
var runtimeBundles = bundles.Where(bundle => bundle.Version is RuntimeVersion).ToArray();
var otherBundles = bundles.Except(sdkBundles).Except(runtimeBundles);
using var scope = new AssertionScope();
scope.AddReportable("allBundles", () => String.Join(Environment.NewLine, allBundles.Select(b => b.ToDebugString())));
scope.AddReportable("uninstallableBundles", () => String.Join(Environment.NewLine, uninstallableBundles.Select(b => b.ToDebugString())));
var sdkBundles = allBundles.Where(bundle => bundle.Version is SdkVersion).ToArray();
var runtimeBundles = allBundles.Where(bundle => bundle.Version is RuntimeVersion).ToArray();
var otherBundles = allBundles.Except(sdkBundles).Except(runtimeBundles);
for (int i = 0; i < sdkBundles.Count(); i++)
{
if (sdkAllowed[i])
{
uninstallable.Should().Contain(sdkBundles[i]);
uninstallableBundles.Should().Contain(sdkBundles[i]);
}
else
{
uninstallable.Should().NotContain(sdkBundles[i]);
uninstallableBundles.Should().NotContain(sdkBundles[i]);
}
}

for (int i = 0; i < runtimeBundles.Count(); i++)
{
if (runtimeAllowed[i])
{
uninstallable.Should().Contain(runtimeBundles[i]);
uninstallableBundles.Should().Contain(runtimeBundles[i]);
}
else
{
uninstallable.Should().NotContain(runtimeBundles[i]);
uninstallableBundles.Should().NotContain(runtimeBundles[i]);
}
}
// Check others are uninstallable unless their version is above the upper limit
foreach (Bundle bundle in otherBundles)
{
if (bundle.Version.SemVer > VisualStudioSafeVersionsExtractor.UpperLimit)
{
uninstallable.Should().NotContain(bundle);
uninstallableBundles.Should().NotContain(bundle);
}
else
{
uninstallable.Should().Contain(bundle);
uninstallableBundles.Should().Contain(bundle);
}
}
}

[WindowsOnlyTheory]
[InlineData(new string[] { }, new string[] { })]
[InlineData(new string[] { "1.0.1", "1.0.0" }, new string[] { "", "None" })]
[InlineData(new string[] { "2.3.0", "2.1.800", "2.1.300" }, new string[] { "", " 2019", " 2017" })]
[InlineData(new string[] { "2.3.0", "2.1.800", "2.1.300" }, new string[] { "None", " 2019", " 2017" })]
[InlineData(new string[] { "2.1.500", "2.1.400", "2.1.600" }, new string[] { " 2017", "None", " 2019" })]
[InlineData(new string[] { "2.1.500", "10.0.1", "10.0.0" }, new string[] { " 2017", "UpperLimit", "UpperLimit" })]
internal void TestGetListCommandUninstallableStringsWindows(string[] versions, string[] expectedStrings)
Expand Down Expand Up @@ -262,7 +267,7 @@ private string[] ExpandExpectationShortHand(string[] input)
{ "Runtime", LocalizableStrings.MacRuntimeRequirementExplainationString}
};
var output = new string[input.Length];

for (int i = 0; i < input.Length; i++)
{
output[i] = shortHandToFullExpectedString[input[i]];
Expand Down

0 comments on commit 9b354de

Please sign in to comment.