From 6310edaa4be6d2153ffe8e6a213ea7b22779474a Mon Sep 17 00:00:00 2001 From: Chris McGee Date: Fri, 17 Oct 2025 15:36:51 -0400 Subject: [PATCH 1/5] Fix the self update for macOS so that the installer is executed --- Sources/MacOSPlatform/MacOS.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/MacOSPlatform/MacOS.swift b/Sources/MacOSPlatform/MacOS.swift index 5f8fb0c4..3e9b40de 100644 --- a/Sources/MacOSPlatform/MacOS.swift +++ b/Sources/MacOSPlatform/MacOS.swift @@ -117,10 +117,10 @@ public struct MacOS: Platform { if ctx.mockedHomeDir == nil { await ctx.message("Extracting the swiftly package...") - _ = sys.installer( + try await sys.installer( .pkg(archive), .target("CurrentUserHomeDirectory") - ) + ).run(self) try? await sys.pkgutil(.volume(userHomeDir)).forget(pkg_id: "org.swift.swiftly").run(self) } else { let installDir = userHomeDir / ".swiftly" From 7bf6a5ddc3448e544ce9b661ab1d812b3c82d3e4 Mon Sep 17 00:00:00 2001 From: Chris McGee Date: Fri, 17 Oct 2025 16:47:56 -0400 Subject: [PATCH 2/5] Add compatible configuration versions to init command for updates --- Sources/Swiftly/Init.swift | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Sources/Swiftly/Init.swift b/Sources/Swiftly/Init.swift index 4fc9c211..268de8e6 100644 --- a/Sources/Swiftly/Init.swift +++ b/Sources/Swiftly/Init.swift @@ -48,7 +48,9 @@ struct Init: SwiftlyCommand { ( config.version == SwiftlyVersion(major: 0, minor: 4, patch: 0, suffix: "dev") || config.version == SwiftlyVersion(major: 0, minor: 4, patch: 0) || - (config.version.major == 1 && config.version.minor == 0) + (config.version.major == 1 && config.version.minor == 0) || + (config.version.major == 1 && config.version.minor == 1) || + (config.version.major == 2 && config.version.minor == 0) ) { // This is a simple upgrade from the 0.4.0 pre-releases, or 1.x From 49ee4b5b91336c72a38513c231cc75515adb0f97 Mon Sep 17 00:00:00 2001 From: Chris McGee Date: Fri, 17 Oct 2025 16:48:41 -0400 Subject: [PATCH 3/5] Fix version major --- Sources/Swiftly/Init.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/Swiftly/Init.swift b/Sources/Swiftly/Init.swift index 268de8e6..031307dd 100644 --- a/Sources/Swiftly/Init.swift +++ b/Sources/Swiftly/Init.swift @@ -50,7 +50,7 @@ struct Init: SwiftlyCommand { config.version == SwiftlyVersion(major: 0, minor: 4, patch: 0) || (config.version.major == 1 && config.version.minor == 0) || (config.version.major == 1 && config.version.minor == 1) || - (config.version.major == 2 && config.version.minor == 0) + (config.version.major == 1 && config.version.minor == 2) ) { // This is a simple upgrade from the 0.4.0 pre-releases, or 1.x From 893c837a078ae8dd900d2b40c34d308823eb0568 Mon Sep 17 00:00:00 2001 From: Chris McGee Date: Tue, 28 Oct 2025 11:25:55 -0400 Subject: [PATCH 4/5] Add test for a migration for the current swiftly version to capture branching problems --- Sources/Swiftly/Init.swift | 34 ++++++++++++++++++++++-------- Tests/SwiftlyTests/InitTests.swift | 6 ++++++ 2 files changed, 31 insertions(+), 9 deletions(-) diff --git a/Sources/Swiftly/Init.swift b/Sources/Swiftly/Init.swift index 031307dd..3c17c7b5 100644 --- a/Sources/Swiftly/Init.swift +++ b/Sources/Swiftly/Init.swift @@ -3,6 +3,30 @@ import Foundation import SwiftlyCore import SystemPackage +public enum SwiftlyVersionMigration { + case exact(SwiftlyVersion) + case minor(SwiftlyVersion) + + public func matches(_ version: SwiftlyVersion) -> Bool { + switch self { + case let .exact(v): + return version.major == v.major && version.minor == v.minor && version.patch == v.patch && version.suffix == v.suffix + case let .minor(v): + return version.major == v.major && version.minor == v.minor + } + } +} + +public var migrations: [SwiftlyVersionMigration] { + [ + .exact(.init(major: 0, minor: 4, patch: 0, suffix: "dev")), + .exact(.init(major: 0, minor: 4, patch: 0)), + .minor(.init(major: 1, minor: 0, patch: 0)), + .minor(.init(major: 1, minor: 1, patch: 0)), + .minor(.init(major: 1, minor: 2, patch: 0)), + ] +} + struct Init: SwiftlyCommand { public static let configuration = CommandConfiguration( abstract: "Perform swiftly initialization into your user account." @@ -44,15 +68,7 @@ struct Init: SwiftlyCommand { var config = try? await Config.load(ctx) - if var config, !overwrite && - ( - config.version == SwiftlyVersion(major: 0, minor: 4, patch: 0, suffix: "dev") || - config.version == SwiftlyVersion(major: 0, minor: 4, patch: 0) || - (config.version.major == 1 && config.version.minor == 0) || - (config.version.major == 1 && config.version.minor == 1) || - (config.version.major == 1 && config.version.minor == 2) - ) - { + if var config, !overwrite && !migrations.filter({ $0.matches(config.version) }).isEmpty { // This is a simple upgrade from the 0.4.0 pre-releases, or 1.x // Move our executable over to the correct place diff --git a/Tests/SwiftlyTests/InitTests.swift b/Tests/SwiftlyTests/InitTests.swift index 7d41a208..c182bcae 100644 --- a/Tests/SwiftlyTests/InitTests.swift +++ b/Tests/SwiftlyTests/InitTests.swift @@ -5,6 +5,12 @@ import SystemPackage import Testing @Suite struct InitTests { + @Test func migrationsHasCurrentSwiftlyVersion() async throws { + // If the current swiftly version isn't in the migration list then it should be added there to + // support future self updates. + #expect(!migrations.filter { $0.matches(SwiftlyCore.version) }.isEmpty) + } + @Test(.testHome(), arguments: ["/bin/bash", "/bin/zsh", "/bin/fish"]) func initFresh(_ shell: String) async throws { // GIVEN: a fresh user account without swiftly installed try? await fs.remove(atPath: Swiftly.currentPlatform.swiftlyConfigFile(SwiftlyTests.ctx)) From 7831f67c90bef8f75d20b00fc032f9c69fac3a97 Mon Sep 17 00:00:00 2001 From: Chris McGee Date: Tue, 28 Oct 2025 12:04:48 -0400 Subject: [PATCH 5/5] Permit self-updates to identical version using the hidden --to-version option. --- Sources/Swiftly/SelfUpdate.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Sources/Swiftly/SelfUpdate.swift b/Sources/Swiftly/SelfUpdate.swift index f5dcafac..2e298e97 100644 --- a/Sources/Swiftly/SelfUpdate.swift +++ b/Sources/Swiftly/SelfUpdate.swift @@ -65,7 +65,8 @@ struct SelfUpdate: SwiftlyCommand { fatalError("Unsupported OS") #endif - guard version > SwiftlyCore.version else { + // Allow newer or identical versions to help self-update testing of a release + guard version >= SwiftlyCore.version else { await ctx.print("Self-update does not support downgrading to an older version or re-installing the current version. Current version is \(SwiftlyCore.version) and requested version is \(version).") return SwiftlyCore.version }