diff --git a/Sources/Swiftly/Uninstall.swift b/Sources/Swiftly/Uninstall.swift index 8200192b..6c7e4f2c 100644 --- a/Sources/Swiftly/Uninstall.swift +++ b/Sources/Swiftly/Uninstall.swift @@ -33,6 +33,10 @@ struct Uninstall: SwiftlyCommand { The latest installed stable release can be uninstalled by specifying 'latest': $ swiftly uninstall latest + + Finally, all installed toolchains can be uninstalled by specifying 'all': + + $ swiftly uninstall all """ )) var toolchain: String @@ -44,9 +48,19 @@ struct Uninstall: SwiftlyCommand { var assumeYes: Bool = false mutating func run() async throws { - let selector = try ToolchainSelector(parsing: self.toolchain) let startingConfig = try Config.load() - let toolchains = startingConfig.listInstalledToolchains(selector: selector) + + let toolchains: [ToolchainVersion] + if self.toolchain == "all" { + // Sort the uninstalled toolchains such that the in-use toolchain will be uninstalled last. + // This avoids printing any unnecessary output from using new toolchains while the uninstall is in progress. + toolchains = startingConfig.listInstalledToolchains(selector: nil).sorted { a, b in + a != startingConfig.inUse && (b == startingConfig.inUse || a < b) + } + } else { + let selector = try ToolchainSelector(parsing: self.toolchain) + toolchains = startingConfig.listInstalledToolchains(selector: selector) + } guard !toolchains.isEmpty else { SwiftlyCore.print("No toolchains matched \"\(self.toolchain)\"") diff --git a/Tests/SwiftlyTests/UninstallTests.swift b/Tests/SwiftlyTests/UninstallTests.swift index b7433cd3..5e17c611 100644 --- a/Tests/SwiftlyTests/UninstallTests.swift +++ b/Tests/SwiftlyTests/UninstallTests.swift @@ -283,4 +283,17 @@ final class UninstallTests: SwiftlyTests { ) } } + + /// Tests that providing "all" as an argument to uninstall will uninstall all toolchains. + func testUninstallAll() async throws { + let toolchains = Set([Self.oldStable, Self.newStable, Self.newMainSnapshot, Self.oldReleaseSnapshot]) + try await self.withMockedHome(homeName: Self.homeName, toolchains: toolchains, inUse: Self.newMainSnapshot) { + var uninstall = try self.parseCommand(Uninstall.self, ["uninstall", "-y", "all"]) + _ = try await uninstall.run() + try await self.validateInstalledToolchains( + [], + description: "uninstall did not uninstall all toolchains" + ) + } + } }