From fee2de1cf3186c2ea15af23ddcc7e478ef2b2dd4 Mon Sep 17 00:00:00 2001 From: Chris McGee Date: Sat, 31 May 2025 10:29:48 -0400 Subject: [PATCH 1/8] Add a hidden option to self-update to provide the swiftly version to update --- Sources/Swiftly/SelfUpdate.swift | 91 ++++++++++++++++++++++---------- 1 file changed, 64 insertions(+), 27 deletions(-) diff --git a/Sources/Swiftly/SelfUpdate.swift b/Sources/Swiftly/SelfUpdate.swift index 49a76e12..578728aa 100644 --- a/Sources/Swiftly/SelfUpdate.swift +++ b/Sources/Swiftly/SelfUpdate.swift @@ -5,6 +5,12 @@ import SwiftlyWebsiteAPI @preconcurrency import TSCBasic import TSCUtility +extension SwiftlyVersion: ExpressibleByArgument { + public init?(argument: String) { + try? self.init(parsing: argument) + } +} + struct SelfUpdate: SwiftlyCommand { public static let configuration = CommandConfiguration( abstract: "Update the version of swiftly itself." @@ -12,8 +18,10 @@ struct SelfUpdate: SwiftlyCommand { @OptionGroup var root: GlobalOptions + @Option(help: .hidden) var toVersion: SwiftlyVersion + private enum CodingKeys: String, CodingKey { - case root + case root, toVersion } mutating func run() async throws { @@ -31,50 +39,79 @@ struct SelfUpdate: SwiftlyCommand { ) } - let _ = try await Self.execute(ctx, verbose: self.root.verbose) + let _ = try await Self.execute(ctx, verbose: self.root.verbose, version: self.toVersion) } - public static func execute(_ ctx: SwiftlyCoreContext, verbose: Bool) async throws + public static func execute(_ ctx: SwiftlyCoreContext, verbose: Bool, version swiftlyVersion: SwiftlyVersion?) async throws -> SwiftlyVersion { - await ctx.print("Checking for swiftly updates...") + var downloadURL: Foundation.URL? + var version: SwiftlyVersion? = swiftlyVersion - let swiftlyRelease = try await ctx.httpClient.getCurrentSwiftlyRelease() + if let version { + guard let version > SwiftlyCore.version - guard try swiftlyRelease.swiftlyVersion > SwiftlyCore.version else { - await ctx.print("Already up to date.") - return SwiftlyCore.version +#if os(macOS) + downloadURL = URL(string: "https://download.swift.org/swiftly/darwin/swiftly-\(version).pkg") +#elseif os(Linux) +#if arch(x86_64) + downloadURL = URL(string: "https://download.swift.org/swiftly/linux/swiftly-\(version)-x86_64.tar.gz") +#elseif arch(arm64) + downloadURL = URL(string: "https://download.swift.org/swiftly/linux/swiftly-\(version)-aarch64.tar.gz") +#else + #error("Processor architecture is unsupported") +#endif + #error("Operating system is unsupported") +#endif + + guard try 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 + } + + await ctx.print("Self-update requested to swiftly version \(version)") } - var downloadURL: Foundation.URL? - for platform in swiftlyRelease.platforms { -#if os(macOS) - guard platform.isDarwin else { - continue + if downloadURL == nil { + await ctx.print("Checking for swiftly updates...") + + let swiftlyRelease = try await ctx.httpClient.getCurrentSwiftlyRelease() + + guard try swiftlyRelease.swiftlyVersion > SwiftlyCore.version else { + await ctx.print("Already up to date.") + return SwiftlyCore.version } + for platform in swiftlyRelease.platforms { +#if os(macOS) + guard platform.isDarwin else { + continue + } #elseif os(Linux) - guard platform.isLinux else { - continue - } + guard platform.isLinux else { + continue + } #endif #if arch(x86_64) - downloadURL = try platform.x86_64URL + downloadURL = try platform.x86_64URL #elseif arch(arm64) - downloadURL = try platform.arm64URL + downloadURL = try platform.arm64URL #endif - } + } - guard let downloadURL else { - throw SwiftlyError( - message: - "The newest release of swiftly is incompatible with your current OS and/or processor architecture." - ) - } + guard let downloadURL else { + throw SwiftlyError( + message: + "The newest release of swiftly is incompatible with your current OS and/or processor architecture." + ) + } + + version = try swiftlyRelease.swiftlyVersion - let version = try swiftlyRelease.swiftlyVersion + await ctx.print("A new version of swiftly is available: \(version)") + } - await ctx.print("A new version is available: \(version)") + guard let version, let downloadURL else { fatalError() } let tmpFile = fs.mktemp() try await fs.create(file: tmpFile, contents: nil) From c827e6a996922b6eca505a7009ee8cb7283de612 Mon Sep 17 00:00:00 2001 From: Chris McGee Date: Sat, 31 May 2025 10:43:51 -0400 Subject: [PATCH 2/8] Fix compile error --- Sources/Swiftly/SelfUpdate.swift | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Sources/Swiftly/SelfUpdate.swift b/Sources/Swiftly/SelfUpdate.swift index 578728aa..69f49589 100644 --- a/Sources/Swiftly/SelfUpdate.swift +++ b/Sources/Swiftly/SelfUpdate.swift @@ -49,7 +49,6 @@ struct SelfUpdate: SwiftlyCommand { var version: SwiftlyVersion? = swiftlyVersion if let version { - guard let version > SwiftlyCore.version #if os(macOS) downloadURL = URL(string: "https://download.swift.org/swiftly/darwin/swiftly-\(version).pkg") @@ -64,7 +63,7 @@ struct SelfUpdate: SwiftlyCommand { #error("Operating system is unsupported") #endif - guard try version > SwiftlyCore.version else { + 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 } @@ -108,7 +107,7 @@ struct SelfUpdate: SwiftlyCommand { version = try swiftlyRelease.swiftlyVersion - await ctx.print("A new version of swiftly is available: \(version)") + await ctx.print("A new version of swiftly is available: \(version!)") } guard let version, let downloadURL else { fatalError() } From 1d924577f21b69ef805ce345ea3f23223b80220a Mon Sep 17 00:00:00 2001 From: Chris McGee Date: Sun, 1 Jun 2025 14:01:12 -0400 Subject: [PATCH 3/8] Update tests to pass the optional explicit version --- Tests/SwiftlyTests/SelfUpdateTests.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/SwiftlyTests/SelfUpdateTests.swift b/Tests/SwiftlyTests/SelfUpdateTests.swift index 0f5e355d..badbf5a3 100644 --- a/Tests/SwiftlyTests/SelfUpdateTests.swift +++ b/Tests/SwiftlyTests/SelfUpdateTests.swift @@ -21,7 +21,7 @@ import Testing func runSelfUpdateTest(latestVersion: SwiftlyVersion) async throws { try await SwiftlyTests.withTestHome { try await SwiftlyTests.withMockedSwiftlyVersion(latestSwiftlyVersion: latestVersion) { - let updatedVersion = try await SelfUpdate.execute(SwiftlyTests.ctx, verbose: true) + let updatedVersion = try await SelfUpdate.execute(SwiftlyTests.ctx, verbose: true, version: nil) #expect(latestVersion == updatedVersion) } } From f1542a69ef1685056d81a73fc2b3a71308e9dfb0 Mon Sep 17 00:00:00 2001 From: Chris McGee Date: Sun, 1 Jun 2025 14:17:02 -0400 Subject: [PATCH 4/8] Fix if checks for OS and arch --- Sources/Swiftly/SelfUpdate.swift | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Sources/Swiftly/SelfUpdate.swift b/Sources/Swiftly/SelfUpdate.swift index 69f49589..c7099a59 100644 --- a/Sources/Swiftly/SelfUpdate.swift +++ b/Sources/Swiftly/SelfUpdate.swift @@ -52,15 +52,14 @@ struct SelfUpdate: SwiftlyCommand { #if os(macOS) downloadURL = URL(string: "https://download.swift.org/swiftly/darwin/swiftly-\(version).pkg") -#elseif os(Linux) +#endif + +#f os(Linux) #if arch(x86_64) downloadURL = URL(string: "https://download.swift.org/swiftly/linux/swiftly-\(version)-x86_64.tar.gz") #elseif arch(arm64) downloadURL = URL(string: "https://download.swift.org/swiftly/linux/swiftly-\(version)-aarch64.tar.gz") -#else - #error("Processor architecture is unsupported") #endif - #error("Operating system is unsupported") #endif guard version > SwiftlyCore.version else { From eb3a02df4e31cb7d4b6b50c669cc7f9f64cfd483 Mon Sep 17 00:00:00 2001 From: Chris McGee Date: Sun, 1 Jun 2025 14:22:44 -0400 Subject: [PATCH 5/8] Fix formatting problem and bad #if --- Sources/Swiftly/SelfUpdate.swift | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Sources/Swiftly/SelfUpdate.swift b/Sources/Swiftly/SelfUpdate.swift index c7099a59..70a2bc8b 100644 --- a/Sources/Swiftly/SelfUpdate.swift +++ b/Sources/Swiftly/SelfUpdate.swift @@ -49,12 +49,11 @@ struct SelfUpdate: SwiftlyCommand { var version: SwiftlyVersion? = swiftlyVersion if let version { - #if os(macOS) downloadURL = URL(string: "https://download.swift.org/swiftly/darwin/swiftly-\(version).pkg") #endif -#f os(Linux) +#if os(Linux) #if arch(x86_64) downloadURL = URL(string: "https://download.swift.org/swiftly/linux/swiftly-\(version)-x86_64.tar.gz") #elseif arch(arm64) From 0a5cfd18870e7aa61ff00d3768df0298bb486781 Mon Sep 17 00:00:00 2001 From: Chris McGee Date: Sun, 1 Jun 2025 14:38:42 -0400 Subject: [PATCH 6/8] Fix documentation --- Documentation/SwiftlyDocs.docc/swiftly-cli-reference.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/SwiftlyDocs.docc/swiftly-cli-reference.md b/Documentation/SwiftlyDocs.docc/swiftly-cli-reference.md index 31e2fd1e..72b7159c 100644 --- a/Documentation/SwiftlyDocs.docc/swiftly-cli-reference.md +++ b/Documentation/SwiftlyDocs.docc/swiftly-cli-reference.md @@ -464,7 +464,7 @@ swiftly init [--no-modify-profile] [--overwrite] [--platform=] [--skip Update the version of swiftly itself. ``` -swiftly self-update [--assume-yes] [--verbose] [--version] [--help] +swiftly self-update [--assume-yes] [--verbose] [--version] [--help] ``` **--assume-yes:** From 3d93a511c23f7641a83e7be2ba7e5da0d3d310ab Mon Sep 17 00:00:00 2001 From: Chris McGee Date: Tue, 3 Jun 2025 12:06:50 -0400 Subject: [PATCH 7/8] Produce fatal errors on unsupported OS/arch --- Sources/Swiftly/SelfUpdate.swift | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Sources/Swiftly/SelfUpdate.swift b/Sources/Swiftly/SelfUpdate.swift index 70a2bc8b..e262aa23 100644 --- a/Sources/Swiftly/SelfUpdate.swift +++ b/Sources/Swiftly/SelfUpdate.swift @@ -58,7 +58,11 @@ struct SelfUpdate: SwiftlyCommand { downloadURL = URL(string: "https://download.swift.org/swiftly/linux/swiftly-\(version)-x86_64.tar.gz") #elseif arch(arm64) downloadURL = URL(string: "https://download.swift.org/swiftly/linux/swiftly-\(version)-aarch64.tar.gz") +#else + fatalError("Unsupported architecture") #endif +#else + fatalError("Unsupported OS") #endif guard version > SwiftlyCore.version else { From f6a85fd58e5100da9ca49c1c7c5f958dffa49200 Mon Sep 17 00:00:00 2001 From: Chris McGee <87777443+cmcgee1024@users.noreply.github.com> Date: Mon, 16 Jun 2025 13:46:36 -0400 Subject: [PATCH 8/8] Update SelfUpdate.swift --- Sources/Swiftly/SelfUpdate.swift | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Sources/Swiftly/SelfUpdate.swift b/Sources/Swiftly/SelfUpdate.swift index 80607e10..2a9b45bc 100644 --- a/Sources/Swiftly/SelfUpdate.swift +++ b/Sources/Swiftly/SelfUpdate.swift @@ -75,11 +75,6 @@ struct SelfUpdate: SwiftlyCommand { await ctx.print("Self-update requested to swiftly version \(version)") } - guard version > SwiftlyCore.version else { - await ctx.message("Already up to date.") - return SwiftlyCore.version - } - if downloadURL == nil { await ctx.print("Checking for swiftly updates...")