Skip to content

Commit 5645873

Browse files
authored
Migrate swiftly to Swift 6 with concurrency checks (#310)
* Migrate swiftly to Swift 6 with concurrency checks
1 parent ea71330 commit 5645873

22 files changed

+192
-179
lines changed

Package.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// swift-tools-version:5.10
1+
// swift-tools-version:6.0
22

33
import PackageDescription
44

Plugins/GenerateDocsReference/GenerateDocsReferenceError.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import Foundation
2-
import PackagePlugin
2+
@preconcurrency import PackagePlugin
33

4+
@preconcurrency
45
enum GenerateDocsReferencePluginError: Error {
56
case unknownBuildConfiguration(String)
67
case buildFailed(String)

Sources/LinuxPlatform/Linux.swift

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,7 @@ public struct Linux: Platform {
334334

335335
public func install(
336336
_ ctx: SwiftlyCoreContext, from tmpFile: URL, version: ToolchainVersion, verbose: Bool
337-
) throws {
337+
) async throws {
338338
guard tmpFile.fileExists() else {
339339
throw SwiftlyError(message: "\(tmpFile) doesn't exist")
340340
}
@@ -345,7 +345,7 @@ public struct Linux: Platform {
345345
)
346346
}
347347

348-
ctx.print("Extracting toolchain...")
348+
await ctx.print("Extracting toolchain...")
349349
let toolchainDir = self.swiftlyToolchainsDir(ctx).appendingPathComponent(version.name)
350350

351351
if toolchainDir.fileExists() {
@@ -360,15 +360,18 @@ public struct Linux: Platform {
360360
let destination = toolchainDir.appendingPathComponent(String(relativePath))
361361

362362
if verbose {
363-
ctx.print("\(destination.path)")
363+
// To avoid having to make extractArchive async this is a regular print
364+
// to stdout. Note that it is unlikely that the test mocking will require
365+
// capturing this output.
366+
print("\(destination.path)")
364367
}
365368

366369
// prepend /path/to/swiftlyHomeDir/toolchains/<toolchain> to each file name
367370
return destination
368371
}
369372
}
370373

371-
public func extractSwiftlyAndInstall(_ ctx: SwiftlyCoreContext, from archive: URL) throws {
374+
public func extractSwiftlyAndInstall(_ ctx: SwiftlyCoreContext, from archive: URL) async throws {
372375
guard archive.fileExists() else {
373376
throw SwiftlyError(message: "\(archive) doesn't exist")
374377
}
@@ -379,7 +382,7 @@ public struct Linux: Platform {
379382
}
380383
try FileManager.default.createDirectory(atPath: tmpDir.path, withIntermediateDirectories: true)
381384

382-
ctx.print("Extracting new swiftly...")
385+
await ctx.print("Extracting new swiftly...")
383386
try extractArchive(atPath: archive) { name in
384387
// Extract to the temporary directory
385388
tmpDir.appendingPathComponent(String(name))
@@ -409,7 +412,7 @@ public struct Linux: Platform {
409412
_ ctx: SwiftlyCoreContext, toolchainFile: ToolchainFile, archive: URL, verbose: Bool
410413
) async throws {
411414
if verbose {
412-
ctx.print("Downloading toolchain signature...")
415+
await ctx.print("Downloading toolchain signature...")
413416
}
414417

415418
let sigFile = self.getTempFilePath()
@@ -420,7 +423,7 @@ public struct Linux: Platform {
420423

421424
try await ctx.httpClient.getSwiftToolchainFileSignature(toolchainFile).download(to: sigFile)
422425

423-
ctx.print("Verifying toolchain signature...")
426+
await ctx.print("Verifying toolchain signature...")
424427
do {
425428
if let mockedHomeDir = ctx.mockedHomeDir {
426429
try self.runProgram(
@@ -439,7 +442,7 @@ public struct Linux: Platform {
439442
_ ctx: SwiftlyCoreContext, archiveDownloadURL: URL, archive: URL, verbose: Bool
440443
) async throws {
441444
if verbose {
442-
ctx.print("Downloading swiftly signature...")
445+
await ctx.print("Downloading swiftly signature...")
443446
}
444447

445448
let sigFile = self.getTempFilePath()
@@ -452,7 +455,7 @@ public struct Linux: Platform {
452455
url: archiveDownloadURL.appendingPathExtension("sig")
453456
).download(to: sigFile)
454457

455-
ctx.print("Verifying swiftly signature...")
458+
await ctx.print("Verifying swiftly signature...")
456459
do {
457460
if let mockedHomeDir = ctx.mockedHomeDir {
458461
try self.runProgram(
@@ -492,7 +495,7 @@ public struct Linux: Platform {
492495
""")
493496

494497
let choice =
495-
ctx.readLine(prompt: "Pick one of the available selections [0-\(self.linuxPlatforms.count)] ")
498+
await ctx.readLine(prompt: "Pick one of the available selections [0-\(self.linuxPlatforms.count)] ")
496499
?? "0"
497500

498501
guard let choiceNum = Int(choice) else {

Sources/MacOSPlatform/MacOS.swift

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ public struct MacOS: Platform {
5151

5252
public func install(
5353
_ ctx: SwiftlyCoreContext, from tmpFile: URL, version: ToolchainVersion, verbose: Bool
54-
) throws {
54+
) async throws {
5555
guard tmpFile.fileExists() else {
5656
throw SwiftlyError(message: "\(tmpFile) doesn't exist")
5757
}
@@ -63,15 +63,15 @@ public struct MacOS: Platform {
6363
}
6464

6565
if ctx.mockedHomeDir == nil {
66-
ctx.print("Installing package in user home directory...")
66+
await ctx.print("Installing package in user home directory...")
6767
try runProgram(
6868
"installer", "-verbose", "-pkg", tmpFile.path, "-target", "CurrentUserHomeDirectory",
6969
quiet: !verbose
7070
)
7171
} else {
7272
// In the case of a mock for testing purposes we won't use the installer, perferring a manual process because
7373
// the installer will not install to an arbitrary path, only a volume or user home directory.
74-
ctx.print("Expanding pkg...")
74+
await ctx.print("Expanding pkg...")
7575
let tmpDir = self.getTempFilePath()
7676
let toolchainDir = self.swiftlyToolchainsDir(ctx).appendingPathComponent(
7777
"\(version.identifier).xctoolchain", isDirectory: true
@@ -89,12 +89,12 @@ public struct MacOS: Platform {
8989
payload = tmpDir.appendingPathComponent("\(version.identifier)-osx-package.pkg/Payload")
9090
}
9191

92-
ctx.print("Untarring pkg Payload...")
92+
await ctx.print("Untarring pkg Payload...")
9393
try runProgram("tar", "-C", toolchainDir.path, "-xvf", payload.path, quiet: !verbose)
9494
}
9595
}
9696

97-
public func extractSwiftlyAndInstall(_ ctx: SwiftlyCoreContext, from archive: URL) throws {
97+
public func extractSwiftlyAndInstall(_ ctx: SwiftlyCoreContext, from archive: URL) async throws {
9898
guard archive.fileExists() else {
9999
throw SwiftlyError(message: "\(archive) doesn't exist")
100100
}
@@ -104,7 +104,7 @@ public struct MacOS: Platform {
104104
if ctx.mockedHomeDir == nil {
105105
homeDir = FileManager.default.homeDirectoryForCurrentUser
106106

107-
ctx.print("Extracting the swiftly package...")
107+
await ctx.print("Extracting the swiftly package...")
108108
try runProgram("installer", "-pkg", archive.path, "-target", "CurrentUserHomeDirectory")
109109
try? runProgram("pkgutil", "--volume", homeDir.path, "--forget", "org.swift.swiftly")
110110
} else {
@@ -127,17 +127,17 @@ public struct MacOS: Platform {
127127
throw SwiftlyError(message: "Payload file could not be found at \(tmpDir).")
128128
}
129129

130-
ctx.print("Extracting the swiftly package into \(installDir.path)...")
130+
await ctx.print("Extracting the swiftly package into \(installDir.path)...")
131131
try runProgram("tar", "-C", installDir.path, "-xvf", payload.path, quiet: false)
132132
}
133133

134134
try self.runProgram(homeDir.appendingPathComponent(".swiftly/bin/swiftly").path, "init")
135135
}
136136

137137
public func uninstall(_ ctx: SwiftlyCoreContext, _ toolchain: ToolchainVersion, verbose: Bool)
138-
throws
138+
async throws
139139
{
140-
ctx.print("Uninstalling package in user home directory...")
140+
await ctx.print("Uninstalling package in user home directory...")
141141

142142
let toolchainDir = self.swiftlyToolchainsDir(ctx).appendingPathComponent(
143143
"\(toolchain.identifier).xctoolchain", isDirectory: true

Sources/Swiftly/Init.swift

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import Foundation
33
import SwiftlyCore
44

55
struct Init: SwiftlyCommand {
6-
public static var configuration = CommandConfiguration(
6+
public static let configuration = CommandConfiguration(
77
abstract: "Perform swiftly initialization into your user account."
88
)
99

@@ -53,7 +53,7 @@ struct Init: SwiftlyCommand {
5353
// This is a simple upgrade from the 0.4.0 pre-releases, or 1.x
5454

5555
// Move our executable over to the correct place
56-
try Swiftly.currentPlatform.installSwiftlyBin(ctx)
56+
try await Swiftly.currentPlatform.installSwiftlyBin(ctx)
5757

5858
// Update and save the version
5959
config.version = SwiftlyCore.version
@@ -113,9 +113,9 @@ struct Init: SwiftlyCommand {
113113
"""
114114
}
115115

116-
ctx.print(msg)
116+
await ctx.print(msg)
117117

118-
guard ctx.promptForConfirmation(defaultBehavior: true) else {
118+
guard await ctx.promptForConfirmation(defaultBehavior: true) else {
119119
throw SwiftlyError(message: "swiftly installation has been cancelled")
120120
}
121121
}
@@ -177,10 +177,10 @@ struct Init: SwiftlyCommand {
177177
guard var config else { throw SwiftlyError(message: "Configuration could not be set") }
178178

179179
// Move our executable over to the correct place
180-
try Swiftly.currentPlatform.installSwiftlyBin(ctx)
180+
try await Swiftly.currentPlatform.installSwiftlyBin(ctx)
181181

182182
if overwrite || !FileManager.default.fileExists(atPath: envFile.path) {
183-
ctx.print("Creating shell environment file for the user...")
183+
await ctx.print("Creating shell environment file for the user...")
184184
var env = ""
185185
if shell.hasSuffix("fish") {
186186
env = """
@@ -206,7 +206,7 @@ struct Init: SwiftlyCommand {
206206
}
207207

208208
if !noModifyProfile {
209-
ctx.print("Updating profile...")
209+
await ctx.print("Updating profile...")
210210

211211
let userHome = ctx.mockedHomeDir ?? FileManager.default.homeDirectoryForCurrentUser
212212

@@ -262,7 +262,7 @@ struct Init: SwiftlyCommand {
262262
try Data(sourceLine.utf8).append(to: profileHome)
263263

264264
if !quietShellFollowup {
265-
ctx.print("""
265+
await ctx.print("""
266266
To begin using installed swiftly from your current shell, first run the following command:
267267
\(sourceLine)
268268
@@ -272,7 +272,7 @@ struct Init: SwiftlyCommand {
272272

273273
// Fish doesn't have path caching, so this might only be needed for bash/zsh
274274
if pathChanged && !quietShellFollowup && !shell.hasSuffix("fish") {
275-
ctx.print("""
275+
await ctx.print("""
276276
Your shell caches items on your path for better performance. Swiftly has added
277277
items to your path that may not get picked up right away. You can update your
278278
shell's environment by running
@@ -285,7 +285,7 @@ struct Init: SwiftlyCommand {
285285
}
286286

287287
if let postInstall {
288-
ctx.print("""
288+
await ctx.print("""
289289
There are some dependencies that should be installed before using this toolchain.
290290
You can run the following script as the system administrator (e.g. root) to prepare
291291
your system:

Sources/Swiftly/Install.swift

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@ import _StringProcessing
22
import ArgumentParser
33
import Foundation
44
import SwiftlyCore
5-
import TSCBasic
5+
@preconcurrency import TSCBasic
66
import TSCUtility
77

88
struct Install: SwiftlyCommand {
9-
public static var configuration = CommandConfiguration(
9+
public static let configuration = CommandConfiguration(
1010
abstract: "Install a new toolchain."
1111
)
1212

@@ -129,7 +129,7 @@ struct Install: SwiftlyCommand {
129129

130130
// Fish doesn't cache its path, so this instruction is not necessary.
131131
if pathChanged && !shell.hasSuffix("fish") {
132-
ctx.print(
132+
await ctx.print(
133133
"""
134134
NOTE: Swiftly has updated some elements in your path and your shell may not yet be
135135
aware of the changes. You can update your shell's environment by running
@@ -170,7 +170,7 @@ struct Install: SwiftlyCommand {
170170
assumeYes: Bool
171171
) async throws -> (postInstall: String?, pathChanged: Bool) {
172172
guard !config.installedToolchains.contains(version) else {
173-
ctx.print("\(version) is already installed.")
173+
await ctx.print("\(version) is already installed.")
174174
return (nil, false)
175175
}
176176

@@ -182,7 +182,7 @@ struct Install: SwiftlyCommand {
182182
requireSignatureValidation: verifySignature
183183
)
184184

185-
ctx.print("Installing \(version)")
185+
await ctx.print("Installing \(version)")
186186

187187
let tmpFile = Swiftly.currentPlatform.getTempFilePath()
188188
FileManager.default.createFile(atPath: tmpFile.path, contents: nil)
@@ -272,7 +272,7 @@ struct Install: SwiftlyCommand {
272272
)
273273
}
274274

275-
try Swiftly.currentPlatform.install(ctx, from: tmpFile, version: version, verbose: verbose)
275+
try await Swiftly.currentPlatform.install(ctx, from: tmpFile, version: version, verbose: verbose)
276276

277277
var pathChanged = false
278278

@@ -297,19 +297,19 @@ struct Install: SwiftlyCommand {
297297
let overwrite = Set(toolchainBinDirContents).subtracting(existingProxies).intersection(
298298
swiftlyBinDirContents)
299299
if !overwrite.isEmpty && !assumeYes {
300-
ctx.print("The following existing executables will be overwritten:")
300+
await ctx.print("The following existing executables will be overwritten:")
301301

302302
for executable in overwrite {
303-
ctx.print(" \(swiftlyBinDir.appendingPathComponent(executable).path)")
303+
await ctx.print(" \(swiftlyBinDir.appendingPathComponent(executable).path)")
304304
}
305305

306-
guard ctx.promptForConfirmation(defaultBehavior: false) else {
306+
guard await ctx.promptForConfirmation(defaultBehavior: false) else {
307307
throw SwiftlyError(message: "Toolchain installation has been cancelled")
308308
}
309309
}
310310

311311
if verbose {
312-
ctx.print("Setting up toolchain proxies...")
312+
await ctx.print("Setting up toolchain proxies...")
313313
}
314314

315315
let proxiesToCreate = Set(toolchainBinDirContents).subtracting(swiftlyBinDirContents).union(
@@ -346,10 +346,10 @@ struct Install: SwiftlyCommand {
346346
if config.inUse == nil {
347347
config.inUse = version
348348
try config.save(ctx)
349-
ctx.print("The global default toolchain has been set to `\(version)`")
349+
await ctx.print("The global default toolchain has been set to `\(version)`")
350350
}
351351

352-
ctx.print("\(version) installed successfully!")
352+
await ctx.print("\(version) installed successfully!")
353353
return (postInstallScript, pathChanged)
354354
}
355355

@@ -359,7 +359,7 @@ struct Install: SwiftlyCommand {
359359
{
360360
switch selector {
361361
case .latest:
362-
ctx.print("Fetching the latest stable Swift release...")
362+
await ctx.print("Fetching the latest stable Swift release...")
363363

364364
guard
365365
let release = try await ctx.httpClient.getReleaseToolchains(
@@ -382,7 +382,7 @@ struct Install: SwiftlyCommand {
382382
return .stable(ToolchainVersion.StableRelease(major: major, minor: minor, patch: patch))
383383
}
384384

385-
ctx.print("Fetching the latest stable Swift \(major).\(minor) release...")
385+
await ctx.print("Fetching the latest stable Swift \(major).\(minor) release...")
386386
// If a patch was not provided, perform a lookup to get the latest patch release
387387
// of the provided major/minor version pair.
388388
let toolchain = try await ctx.httpClient.getReleaseToolchains(
@@ -402,7 +402,7 @@ struct Install: SwiftlyCommand {
402402
return ToolchainVersion(snapshotBranch: branch, date: date)
403403
}
404404

405-
ctx.print("Fetching the latest \(branch) branch snapshot...")
405+
await ctx.print("Fetching the latest \(branch) branch snapshot...")
406406

407407
// If a date was not provided, perform a lookup to find the most recent snapshot
408408
// for the given branch.

0 commit comments

Comments
 (0)