Skip to content

Commit 2af38f1

Browse files
authored
Complete the list command implementation on Linux (#23)
1 parent 784a234 commit 2af38f1

File tree

9 files changed

+350
-83
lines changed

9 files changed

+350
-83
lines changed

Sources/LinuxPlatform/Linux.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ public struct Linux: Platform {
4141
try FileManager.default.createDirectory(at: toolchainsDir, withIntermediateDirectories: false)
4242
}
4343

44-
print("Extracting toolchain...")
44+
SwiftlyCore.print("Extracting toolchain...")
4545
let toolchainDir = toolchainsDir.appendingPathComponent(version.name)
4646

4747
if toolchainDir.fileExists() {

Sources/Swiftly/Install.swift

+7-7
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,10 @@ struct Install: SwiftlyCommand {
6262

6363
internal static func execute(version: ToolchainVersion) async throws {
6464
guard try !Config.load().installedToolchains.contains(version) else {
65-
print("\(version) is already installed, exiting.")
65+
SwiftlyCore.print("\(version) is already installed, exiting.")
6666
return
6767
}
68-
print("Installing \(version)")
68+
SwiftlyCore.print("Installing \(version)")
6969

7070
let tmpFile = Swiftly.currentPlatform.getTempFilePath()
7171
FileManager.default.createFile(atPath: tmpFile.path, contents: nil)
@@ -133,7 +133,7 @@ struct Install: SwiftlyCommand {
133133
}
134134
)
135135
} catch _ as HTTP.DownloadNotFoundError {
136-
print("\(version) does not exist, exiting")
136+
SwiftlyCore.print("\(version) does not exist, exiting")
137137
return
138138
} catch {
139139
animation.complete(success: false)
@@ -153,15 +153,15 @@ struct Install: SwiftlyCommand {
153153
try await Use.execute(version)
154154
}
155155

156-
print("\(version) installed successfully!")
156+
SwiftlyCore.print("\(version) installed successfully!")
157157
}
158158

159159
/// Utilize the GitHub API along with the provided selector to select a toolchain for install.
160160
/// TODO: update this to use an official swift.org API
161161
func resolve(selector: ToolchainSelector) async throws -> ToolchainVersion {
162162
switch selector {
163163
case .latest:
164-
print("Fetching the latest stable Swift release...")
164+
SwiftlyCore.print("Fetching the latest stable Swift release...")
165165

166166
guard let release = try await HTTP.getReleaseToolchains(limit: 1).first else {
167167
throw Error(message: "couldn't get latest releases")
@@ -179,7 +179,7 @@ struct Install: SwiftlyCommand {
179179
return .stable(ToolchainVersion.StableRelease(major: major, minor: minor, patch: patch))
180180
}
181181

182-
print("Fetching the latest stable Swift \(major).\(minor) release...")
182+
SwiftlyCore.print("Fetching the latest stable Swift \(major).\(minor) release...")
183183
// If a patch was not provided, perform a lookup to get the latest patch release
184184
// of the provided major/minor version pair.
185185
let toolchain = try await HTTP.getReleaseToolchains(limit: 1) { release in
@@ -197,7 +197,7 @@ struct Install: SwiftlyCommand {
197197
return ToolchainVersion(snapshotBranch: branch, date: date)
198198
}
199199

200-
print("Fetching the latest \(branch) branch snapshot...")
200+
SwiftlyCore.print("Fetching the latest \(branch) branch snapshot...")
201201
// If a date was not provided, perform a lookup to find the most recent snapshot
202202
// for the given branch.
203203
let snapshot = try await HTTP.getSnapshotToolchains(limit: 1) { snapshot in

Sources/Swiftly/List.swift

+14-11
Original file line numberDiff line numberDiff line change
@@ -40,15 +40,15 @@ struct List: SwiftlyCommand {
4040

4141
let config = try Config.load()
4242

43-
let toolchains = config.listInstalledToolchains(selector: selector)
43+
let toolchains = config.listInstalledToolchains(selector: selector).sorted { $0 > $1 }
4444
let activeToolchain = config.inUse
4545

4646
let printToolchain = { (toolchain: ToolchainVersion) in
4747
var message = "\(toolchain)"
4848
if toolchain == activeToolchain {
4949
message += " (in use)"
5050
}
51-
print(message)
51+
SwiftlyCore.print(message)
5252
}
5353

5454
if let selector {
@@ -68,22 +68,25 @@ struct List: SwiftlyCommand {
6868
modifier = "matching"
6969
}
7070

71-
let message = "installed \(modifier) toolchains"
72-
print(message)
73-
print(String(repeating: "-", count: message.utf8.count))
71+
let message = "Installed \(modifier) toolchains"
72+
SwiftlyCore.print(message)
73+
SwiftlyCore.print(String(repeating: "-", count: message.utf8.count))
7474
for toolchain in toolchains {
7575
printToolchain(toolchain)
7676
}
7777
} else {
78-
print("installed release toolchains")
79-
print("----------------------------")
80-
for toolchain in toolchains where toolchain.isStableRelease() {
78+
SwiftlyCore.print("Installed release toolchains")
79+
SwiftlyCore.print("----------------------------")
80+
for toolchain in toolchains {
81+
guard toolchain.isStableRelease() else {
82+
continue
83+
}
8184
printToolchain(toolchain)
8285
}
8386

84-
print("")
85-
print("installed snapshot toolchains")
86-
print("-----------------------------")
87+
SwiftlyCore.print("")
88+
SwiftlyCore.print("Installed snapshot toolchains")
89+
SwiftlyCore.print("-----------------------------")
8790
for toolchain in toolchains where toolchain.isSnapshot() {
8891
printToolchain(toolchain)
8992
}

Sources/Swiftly/Use.swift

+3-3
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ internal struct Use: SwiftlyCommand {
4343
let config = try Config.load()
4444

4545
guard let toolchain = config.listInstalledToolchains(selector: selector).max() else {
46-
print("No installed toolchains match \"\(self.toolchain)\"")
46+
SwiftlyCore.print("No installed toolchains match \"\(self.toolchain)\"")
4747
return
4848
}
4949

@@ -55,7 +55,7 @@ internal struct Use: SwiftlyCommand {
5555
let previousToolchain = config.inUse
5656

5757
guard toolchain != previousToolchain else {
58-
print("\(toolchain) is already in use")
58+
SwiftlyCore.print("\(toolchain) is already in use")
5959
return
6060
}
6161

@@ -68,6 +68,6 @@ internal struct Use: SwiftlyCommand {
6868
message += " (was \(previousToolchain))"
6969
}
7070

71-
print(message)
71+
SwiftlyCore.print(message)
7272
}
7373
}

Sources/SwiftlyCore/SwiftlyCore.swift

+19
Original file line numberDiff line numberDiff line change
@@ -44,3 +44,22 @@ public var requiredDirectories: [URL] {
4444
SwiftlyCore.toolchainsDir,
4545
]
4646
}
47+
48+
/// Protocol defining a handler for information swiftly intends to print to stdout.
49+
/// This is currently only used to intercept print statements for testing.
50+
public protocol OutputHandler {
51+
func handleOutputLine(_ string: String)
52+
}
53+
54+
/// The output handler to use, if any.
55+
public var outputHandler: (any OutputHandler)?
56+
57+
/// Pass the provided string to the set output handler if any.
58+
/// If no output handler has been set, just print to stdout.
59+
public func print(_ string: String) {
60+
guard let handler = SwiftlyCore.outputHandler else {
61+
Swift.print(string)
62+
return
63+
}
64+
handler.handleOutputLine(string)
65+
}

Sources/SwiftlyCore/ToolchainVerison.swift

+24-4
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import _StringProcessing
22

33
/// Enum representing a fully resolved toolchain version (e.g. 5.6.7 or 5.7-snapshot-2022-07-05).
44
public enum ToolchainVersion {
5-
public struct Snapshot: Equatable, Hashable, CustomStringConvertible {
5+
public struct Snapshot: Equatable, Hashable, CustomStringConvertible, Comparable {
66
public enum Branch: Equatable, Hashable, CustomStringConvertible {
77
case main
88
case release(major: Int, minor: Int)
@@ -15,6 +15,20 @@ public enum ToolchainVersion {
1515
return "\(major).\(minor) development"
1616
}
1717
}
18+
19+
public var major: Int? {
20+
guard case let .release(major, _) = self else {
21+
return nil
22+
}
23+
return major
24+
}
25+
26+
public var minor: Int? {
27+
guard case let .release(_, minor) = self else {
28+
return nil
29+
}
30+
return minor
31+
}
1832
}
1933

2034
public let branch: Branch
@@ -33,6 +47,10 @@ public enum ToolchainVersion {
3347
return "\(major).\(minor)-snapshot-\(self.date)"
3448
}
3549
}
50+
51+
public static func < (lhs: Self, rhs: Self) -> Bool {
52+
lhs.date < rhs.date
53+
}
3654
}
3755

3856
public struct StableRelease: Equatable, Comparable, Hashable, CustomStringConvertible {
@@ -177,10 +195,12 @@ extension ToolchainVersion: Comparable {
177195
switch (lhs, rhs) {
178196
case let (.stable(lhsRelease), .stable(rhsRelease)):
179197
return lhsRelease < rhsRelease
180-
case let (.snapshot(lhsRelease), .snapshot(rhsRelease)):
181-
return lhsRelease.branch == rhsRelease.branch && lhsRelease.date < rhsRelease.date
182-
default:
198+
case let (.snapshot(lhsSnapshot), .snapshot(rhsSnapshot)):
199+
return lhsSnapshot < rhsSnapshot
200+
case (.snapshot, .stable):
183201
return false
202+
case (.stable, .snapshot):
203+
return !(rhs < lhs)
184204
}
185205
}
186206
}

0 commit comments

Comments
 (0)