Skip to content

Commit 102a5c3

Browse files
Add version check and prompt for self update (#313)
* feat: add version check and defer print till end of func * feat: move version check inside `validateSwiftly` * fix: discard update handler for `self-update` * feat: print update msg to stderr * chore: rename variable * fix: await async Config.load() op * chore: add period * fix: non faliure version checking with `try?` * fix(ListTests): mocked Swiftly Version * test(Platform): mock swiftly verison * test(Run): mock swiftly verison * test(Uninstall): mock swiftly verison * test(Use): mock swiftly version * feat: add MockSwiftlyVersion Test Trait
1 parent df0e91c commit 102a5c3

File tree

15 files changed

+121
-49
lines changed

15 files changed

+121
-49
lines changed

Sources/Swiftly/Install.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,10 @@ struct Install: SwiftlyCommand {
8282
}
8383

8484
mutating func run(_ ctx: SwiftlyCoreContext) async throws {
85-
try await validateSwiftly(ctx)
85+
let versionUpdateReminder = try await validateSwiftly(ctx)
86+
defer {
87+
versionUpdateReminder()
88+
}
8689

8790
var config = try await Config.load(ctx)
8891

Sources/Swiftly/List.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,11 @@ struct List: SwiftlyCommand {
3838
}
3939

4040
mutating func run(_ ctx: SwiftlyCoreContext) async throws {
41-
try await validateSwiftly(ctx)
41+
let versionUpdateReminder = try await validateSwiftly(ctx)
42+
defer {
43+
versionUpdateReminder()
44+
}
45+
4246
let selector = try self.toolchainSelector.map { input in
4347
try ToolchainSelector(parsing: input)
4448
}

Sources/Swiftly/ListAvailable.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,11 @@ struct ListAvailable: SwiftlyCommand {
4444
}
4545

4646
mutating func run(_ ctx: SwiftlyCoreContext) async throws {
47-
try await validateSwiftly(ctx)
47+
let versionUpdateReminder = try await validateSwiftly(ctx)
48+
defer {
49+
versionUpdateReminder()
50+
}
51+
4852
let selector = try self.toolchainSelector.map { input in
4953
try ToolchainSelector(parsing: input)
5054
}

Sources/Swiftly/Run.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,10 @@ struct Run: SwiftlyCommand {
5858
}
5959

6060
mutating func run(_ ctx: SwiftlyCoreContext) async throws {
61-
try await validateSwiftly(ctx)
61+
let versionUpdateReminder = try await validateSwiftly(ctx)
62+
defer {
63+
versionUpdateReminder()
64+
}
6265

6366
// Handle the specific case where help is requested of the run subcommand
6467
if command == ["--help"] {

Sources/Swiftly/SelfUpdate.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ struct SelfUpdate: SwiftlyCommand {
2121
}
2222

2323
mutating func run(_ ctx: SwiftlyCoreContext) async throws {
24-
try await validateSwiftly(ctx)
24+
let _ = try await validateSwiftly(ctx)
2525

2626
let swiftlyBin = Swiftly.currentPlatform.swiftlyBinDir(ctx) / "swiftly"
2727
guard try await fs.exists(atPath: swiftlyBin) else {

Sources/Swiftly/Swiftly.swift

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ extension Data {
9393
}
9494

9595
extension SwiftlyCommand {
96-
public mutating func validateSwiftly(_ ctx: SwiftlyCoreContext) async throws {
96+
public mutating func validateSwiftly(_ ctx: SwiftlyCoreContext) async throws -> () -> Void {
9797
for requiredDir in Swiftly.requiredDirectories(ctx) {
9898
guard try await fs.exists(atPath: requiredDir) else {
9999
do {
@@ -107,5 +107,27 @@ extension SwiftlyCommand {
107107

108108
// Verify that the configuration exists and can be loaded
109109
_ = try await Config.load(ctx)
110+
111+
let shouldUpdateSwiftly: Bool
112+
if let swiftlyRelease = try? await ctx.httpClient.getCurrentSwiftlyRelease() {
113+
shouldUpdateSwiftly = try swiftlyRelease.swiftlyVersion > SwiftlyCore.version
114+
} else {
115+
shouldUpdateSwiftly = false
116+
}
117+
118+
return {
119+
if shouldUpdateSwiftly {
120+
let updateMessage = """
121+
-----------------------------
122+
A new release of swiftly is available.
123+
Please run `swiftly self-update` to update.
124+
-----------------------------\n
125+
"""
126+
127+
if let data = updateMessage.data(using: .utf8) {
128+
FileHandle.standardError.write(data)
129+
}
130+
}
131+
}
110132
}
111133
}

Sources/Swiftly/Uninstall.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,11 @@ struct Uninstall: SwiftlyCommand {
4848
}
4949

5050
mutating func run(_ ctx: SwiftlyCoreContext) async throws {
51-
try await validateSwiftly(ctx)
51+
let versionUpdateReminder = try await validateSwiftly(ctx)
52+
defer {
53+
versionUpdateReminder()
54+
}
55+
5256
let startingConfig = try await Config.load(ctx)
5357

5458
let toolchains: [ToolchainVersion]

Sources/Swiftly/Update.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,11 @@ struct Update: SwiftlyCommand {
8383
}
8484

8585
public mutating func run(_ ctx: SwiftlyCoreContext) async throws {
86-
try await validateSwiftly(ctx)
86+
let versionUpdateReminder = try await validateSwiftly(ctx)
87+
defer {
88+
versionUpdateReminder()
89+
}
90+
8791
var config = try await Config.load(ctx)
8892

8993
guard let parameters = try await self.resolveUpdateParameters(ctx, &config) else {

Sources/Swiftly/Use.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,11 @@ struct Use: SwiftlyCommand {
6060
}
6161

6262
mutating func run(_ ctx: SwiftlyCoreContext) async throws {
63-
try await validateSwiftly(ctx)
63+
let versionUpdateReminder = try await validateSwiftly(ctx)
64+
defer {
65+
versionUpdateReminder()
66+
}
67+
6468
var config = try await Config.load(ctx)
6569

6670
// This is the bare use command where we print the selected toolchain version (or the path to it)

Tests/SwiftlyTests/ListTests.swift

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,21 @@ import Testing
1919
.oldReleaseSnapshot,
2020
]
2121

22+
private static let swiftlyVersion = SwiftlyVersion(major: SwiftlyCore.version.major, minor: 0, patch: 0)
23+
2224
/// Constructs a mock home directory with the toolchains listed above installed and runs the provided closure within
2325
/// the context of that home.
2426
func runListTest(f: () async throws -> Void) async throws {
2527
try await SwiftlyTests.withTestHome(name: Self.homeName) {
26-
for toolchain in Set<ToolchainVersion>.allToolchains() {
27-
try await SwiftlyTests.installMockedToolchain(toolchain: toolchain)
28-
}
28+
try await SwiftlyTests.withMockedSwiftlyVersion(latestSwiftlyVersion: Self.swiftlyVersion) {
29+
for toolchain in Set<ToolchainVersion>.allToolchains() {
30+
try await SwiftlyTests.installMockedToolchain(toolchain: toolchain)
31+
}
2932

30-
try await SwiftlyTests.runCommand(Use.self, ["use", "latest"])
33+
try await SwiftlyTests.runCommand(Use.self, ["use", "latest"])
3134

32-
try await f()
35+
try await f()
36+
}
3337
}
3438
}
3539

@@ -155,16 +159,18 @@ import Testing
155159

156160
/// Tests that `list` properly handles the case where no toolchains have been installed yet.
157161
@Test(.testHome(Self.homeName)) func listEmpty() async throws {
158-
var toolchains = try await self.runList(selector: nil)
159-
#expect(toolchains == [])
162+
try await SwiftlyTests.withMockedSwiftlyVersion(latestSwiftlyVersion: Self.swiftlyVersion) {
163+
var toolchains = try await self.runList(selector: nil)
164+
#expect(toolchains == [])
160165

161-
toolchains = try await self.runList(selector: "5")
162-
#expect(toolchains == [])
166+
toolchains = try await self.runList(selector: "5")
167+
#expect(toolchains == [])
163168

164-
toolchains = try await self.runList(selector: "main-snapshot")
165-
#expect(toolchains == [])
169+
toolchains = try await self.runList(selector: "main-snapshot")
170+
#expect(toolchains == [])
166171

167-
toolchains = try await self.runList(selector: "5.7-snapshot")
168-
#expect(toolchains == [])
172+
toolchains = try await self.runList(selector: "5.7-snapshot")
173+
#expect(toolchains == [])
174+
}
169175
}
170176
}

0 commit comments

Comments
 (0)