Skip to content

Implement update command #67

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Oct 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 17 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ Target: x86_64-unknown-linux-gnu

- Installing multiple toolchains, including both stable releases and snapshots
- Switching which installed toolchain is active (i.e. which one is discovered via `$PATH`)
- Updating installed toolchains to the latest available versions of those toolchains (not yet implemented)
- Updating installed toolchains to the latest available versions of those toolchains
- Uninstalling installed toolchains
- Listing the toolchains that are available to install (not yet implemented)

Expand Down Expand Up @@ -175,23 +175,27 @@ $ swiftly use main-snapshot

### Updating a toolchain

Update replaces a given toolchain with a later version of that toolchain. For a stable release, this means updating to a later patch version. For snapshots, this means updating to the most recently available snapshot.
Update replaces a given toolchain with a later version of that toolchain. For a stable release, this means updating to a later patch, minor, or major version. For snapshots, this means updating to the most recently available snapshot.

If no version is provided, update will update the currently selected toolchain to its latest version while removing the old version. The newly installed version will be used.

Note that this command isn't implemented yet, but it will be included in a future release.
If no version is provided, update will update the currently selected toolchain to its latest patch release if a release toolchain or the latest available snapshot if a snapshot. The newly installed version will be selected.

```
$ swiftly update
```

To update the latest installed stable version, the “latest” version can be provided:
To update the latest installed release version to the latest available release version, the “latest” version can be provided. Note that this may update the toolchain to the next minor or even major version.

```
swiftly update latest
```

To update to the latest patch release of a given major/minor version, only the major/minor pair need to be provided. This will update the latest installed toolchain associated with that major/minor version to the latest patch release for that major/minor version.
If only a major version is specified, the latest installed toolchain with that major version will be updated to the latest available release of that major version:

```
swiftly update 5
```

If the major and minor version are specified, the latest installed toolchain associated with that major/minor version will be updated to the latest available patch release for that major/minor version.

```
swiftly update 5.3
Expand All @@ -215,6 +219,12 @@ You can also update the latest installed main snapshot to the latest available o
swiftly update main-snapshot
```

A specific snapshot toolchain can be updated to the newest available snapshot for that branch by including the date:

```
swiftly update 5.9-snapshot-2023-09-20
```

### Listing toolchains available to install

The `list-available` command can be used to list the latest toolchains that Apple has made available to install.
Expand Down
32 changes: 21 additions & 11 deletions Sources/Swiftly/Install.swift
Original file line number Diff line number Diff line change
Expand Up @@ -53,16 +53,25 @@ struct Install: SwiftlyCommand {
))
var token: String?

public var httpClient = SwiftlyHTTPClient()

private enum CodingKeys: String, CodingKey {
case version, token
}

mutating func run() async throws {
let selector = try ToolchainSelector(parsing: self.version)
HTTP.githubToken = self.token
self.httpClient.githubToken = self.token
let toolchainVersion = try await self.resolve(selector: selector)
try await Self.execute(version: toolchainVersion)
}

internal static func execute(version: ToolchainVersion) async throws {
var config = try Config.load()
try await Self.execute(version: toolchainVersion, &config, self.httpClient)
}

internal static func execute(
version: ToolchainVersion,
_ config: inout Config,
_ httpClient: SwiftlyHTTPClient
) async throws {
guard !config.installedToolchains.contains(version) else {
SwiftlyCore.print("\(version) is already installed, exiting.")
return
Expand Down Expand Up @@ -121,7 +130,8 @@ struct Install: SwiftlyCommand {
var lastUpdate = Date()

do {
try await HTTP.downloadToolchain(
try await httpClient.downloadToolchain(
version,
url: url,
to: tmpFile.path,
reportProgress: { progress in
Expand All @@ -143,7 +153,7 @@ struct Install: SwiftlyCommand {
)
}
)
} catch _ as HTTP.DownloadNotFoundError {
} catch _ as SwiftlyHTTPClient.DownloadNotFoundError {
SwiftlyCore.print("\(version) does not exist, exiting")
return
} catch {
Expand All @@ -160,7 +170,7 @@ struct Install: SwiftlyCommand {

// If this is the first installed toolchain, mark it as in-use.
if config.inUse == nil {
try await Use.execute(version, config: &config)
try await Use.execute(version, &config)
}

SwiftlyCore.print("\(version) installed successfully!")
Expand All @@ -173,7 +183,7 @@ struct Install: SwiftlyCommand {
case .latest:
SwiftlyCore.print("Fetching the latest stable Swift release...")

guard let release = try await HTTP.getReleaseToolchains(limit: 1).first else {
guard let release = try await self.httpClient.getReleaseToolchains(limit: 1).first else {
throw Error(message: "couldn't get latest releases")
}
return .stable(release)
Expand All @@ -192,7 +202,7 @@ struct Install: SwiftlyCommand {
SwiftlyCore.print("Fetching the latest stable Swift \(major).\(minor) release...")
// If a patch was not provided, perform a lookup to get the latest patch release
// of the provided major/minor version pair.
let toolchain = try await HTTP.getReleaseToolchains(limit: 1) { release in
let toolchain = try await self.httpClient.getReleaseToolchains(limit: 1) { release in
release.major == major && release.minor == minor
}.first

Expand All @@ -210,7 +220,7 @@ struct Install: SwiftlyCommand {
SwiftlyCore.print("Fetching the latest \(branch) branch snapshot...")
// If a date was not provided, perform a lookup to find the most recent snapshot
// for the given branch.
let snapshot = try await HTTP.getSnapshotToolchains(limit: 1) { snapshot in
let snapshot = try await self.httpClient.getSnapshotToolchains(limit: 1) { snapshot in
snapshot.branch == branch
}.first

Expand Down
8 changes: 7 additions & 1 deletion Sources/Swiftly/ListAvailable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ struct ListAvailable: SwiftlyCommand {
))
var toolchainSelector: String?

public var httpClient = SwiftlyHTTPClient()

private enum CodingKeys: String, CodingKey {
case toolchainSelector
}

internal mutating func run() async throws {
let selector = try self.toolchainSelector.map { input in
try ToolchainSelector(parsing: input)
Expand All @@ -47,7 +53,7 @@ struct ListAvailable: SwiftlyCommand {
}
}

let toolchains = try await HTTP.getReleaseToolchains()
let toolchains = try await self.httpClient.getReleaseToolchains()
.map(ToolchainVersion.stable)
.filter { selector?.matches(toolchain: $0) ?? true }

Expand Down
1 change: 1 addition & 0 deletions Sources/Swiftly/Swiftly.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ public struct Swiftly: SwiftlyCommand {
Use.self,
Uninstall.self,
List.self,
Update.self,
]
)

Expand Down
19 changes: 11 additions & 8 deletions Sources/Swiftly/Uninstall.swift
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,8 @@ struct Uninstall: SwiftlyCommand {
for toolchain in toolchains {
SwiftlyCore.print(" \(toolchain)")
}
let proceed = SwiftlyCore.readLine(prompt: "Proceed? (y/n)") ?? "n"

guard proceed == "y" else {
guard SwiftlyCore.promptForConfirmation(defaultBehavior: true) else {
SwiftlyCore.print("Aborting uninstall")
return
}
Expand Down Expand Up @@ -90,7 +89,7 @@ struct Uninstall: SwiftlyCommand {
?? config.listInstalledToolchains(selector: .latest).filter({ !toolchains.contains($0) }).max()
?? config.installedToolchains.filter({ !toolchains.contains($0) }).max()
{
try await Use.execute(toUse, config: &config)
try await Use.execute(toUse, &config)
} else {
// If there are no more toolchains installed, just unuse the currently active toolchain.
try Swiftly.currentPlatform.unUse(currentToolchain: toolchain)
Expand All @@ -99,14 +98,18 @@ struct Uninstall: SwiftlyCommand {
}
}

SwiftlyCore.print("Uninstalling \(toolchain)...", terminator: "")
try Swiftly.currentPlatform.uninstall(toolchain)
config.installedToolchains.remove(toolchain)
try config.save()
SwiftlyCore.print("done")
try await Self.execute(toolchain, &config)
}

SwiftlyCore.print()
SwiftlyCore.print("\(toolchains.count) toolchain(s) successfully uninstalled")
}

static func execute(_ toolchain: ToolchainVersion, _ config: inout Config) async throws {
SwiftlyCore.print("Uninstalling \(toolchain)...", terminator: "")
try Swiftly.currentPlatform.uninstall(toolchain)
config.installedToolchains.remove(toolchain)
try config.save()
SwiftlyCore.print("done")
}
}
Loading