Skip to content

Commit e6d58f2

Browse files
committed
Force language server to update when it doesn't match the min version
1 parent c779a8c commit e6d58f2

File tree

3 files changed

+63
-5
lines changed

3 files changed

+63
-5
lines changed

Tool/Package.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,7 @@ let package = Package(
316316
"Preferences",
317317
"Terminal",
318318
"BuiltinExtension",
319+
"Toast",
319320
.product(name: "LanguageServerProtocol", package: "LanguageServerProtocol"),
320321
.product(name: "CopilotForXcodeKit", package: "CopilotForXcodeKit"),
321322
],

Tool/Sources/GitHubCopilotService/GitHubCopilotWorkspacePlugin.swift

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,35 @@
11
import Foundation
22
import Logger
33
import Workspace
4+
import Toast
5+
import Dependencies
46

57
public final class GitHubCopilotWorkspacePlugin: WorkspacePlugin {
8+
enum Error: Swift.Error, LocalizedError {
9+
case gitHubCopilotLanguageServerMustBeUpdated
10+
var errorDescription: String? {
11+
switch self {
12+
case .gitHubCopilotLanguageServerMustBeUpdated:
13+
return "GitHub Copilot language server must be updated. Update will start immediately. \nIf it fails, please go to Host app > Service > GitHub Copilot and check if there is an update available."
14+
}
15+
}
16+
}
17+
18+
@Dependency(\.toast) var toast
19+
20+
let installationManager = GitHubCopilotInstallationManager()
621
private var _gitHubCopilotService: GitHubCopilotService?
722
@GitHubCopilotSuggestionActor
823
var gitHubCopilotService: GitHubCopilotService? {
924
if let service = _gitHubCopilotService { return service }
1025
do {
1126
return try createGitHubCopilotService()
27+
} catch let error as Error {
28+
toast(error.localizedDescription, .warning)
29+
Task {
30+
await updateLanguageServerIfPossible()
31+
}
32+
return nil
1233
} catch {
1334
Logger.gitHubCopilot.error("Failed to create GitHub Copilot service: \(error)")
1435
return nil
@@ -23,6 +44,9 @@ public final class GitHubCopilotWorkspacePlugin: WorkspacePlugin {
2344

2445
@GitHubCopilotSuggestionActor
2546
func createGitHubCopilotService() throws -> GitHubCopilotService {
47+
if case .outdated(_, _, true) = installationManager.checkInstallation() {
48+
throw Error.gitHubCopilotLanguageServerMustBeUpdated
49+
}
2650
let newService = try GitHubCopilotService(projectRootURL: projectRootURL)
2751
_gitHubCopilotService = newService
2852
newService.localProcessServer?.terminationHandler = { [weak self] in
@@ -50,6 +74,30 @@ public final class GitHubCopilotWorkspacePlugin: WorkspacePlugin {
5074
}
5175
}
5276
}
77+
78+
@GitHubCopilotSuggestionActor
79+
func updateLanguageServerIfPossible() async {
80+
guard !GitHubCopilotInstallationManager.isInstalling else { return }
81+
let events = installationManager.installLatestVersion()
82+
do {
83+
for try await event in events {
84+
switch event {
85+
case .downloading:
86+
toast("Updating GitHub Copilot language server", .info)
87+
case .uninstalling:
88+
break
89+
case .decompressing:
90+
break
91+
case .done:
92+
toast("Finished updating GitHub Copilot language server", .info)
93+
}
94+
}
95+
} catch GitHubCopilotInstallationManager.Error.isInstalling {
96+
return
97+
} catch {
98+
toast(error.localizedDescription, .error)
99+
}
100+
}
53101

54102
func terminate() {
55103
_gitHubCopilotService = nil

Tool/Sources/GitHubCopilotService/LanguageServer/GitHubCopilotInstallationManager.swift

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ import Foundation
22
import Terminal
33

44
public struct GitHubCopilotInstallationManager {
5-
private static var isInstalling = false
5+
@GitHubCopilotSuggestionActor
6+
public private(set) static var isInstalling = false
67

78
static var downloadURL: URL {
89
let commitHash = "c79d711cbf7c6672c6c57d6df7c5ab7b6cac2b7a"
@@ -11,13 +12,14 @@ public struct GitHubCopilotInstallationManager {
1112
}
1213

1314
static let latestSupportedVersion = "1.33.0"
15+
static let minimumSupportedVersion = "1.32.0"
1416

1517
public init() {}
1618

1719
public enum InstallationStatus {
1820
case notInstalled
1921
case installed(String)
20-
case outdated(current: String, latest: String)
22+
case outdated(current: String, latest: String, mandatory: Bool)
2123
case unsupported(current: String, latest: String)
2224
}
2325

@@ -38,15 +40,22 @@ public struct GitHubCopilotInstallationManager {
3840
{
3941
switch version.compare(Self.latestSupportedVersion) {
4042
case .orderedAscending:
41-
return .outdated(current: version, latest: Self.latestSupportedVersion)
43+
switch version.compare(Self.minimumSupportedVersion) {
44+
case .orderedAscending:
45+
return .outdated(current: version, latest: Self.latestSupportedVersion, mandatory: true)
46+
case .orderedSame:
47+
return .outdated(current: version, latest: Self.latestSupportedVersion, mandatory: false)
48+
case .orderedDescending:
49+
return .outdated(current: version, latest: Self.latestSupportedVersion, mandatory: false)
50+
}
4251
case .orderedSame:
4352
return .installed(version)
4453
case .orderedDescending:
4554
return .unsupported(current: version, latest: Self.latestSupportedVersion)
4655
}
4756
}
4857

49-
return .outdated(current: "Unknown", latest: Self.latestSupportedVersion)
58+
return .outdated(current: "Unknown", latest: Self.latestSupportedVersion, mandatory: false)
5059
}
5160

5261
public enum InstallationStep {
@@ -75,7 +84,7 @@ public struct GitHubCopilotInstallationManager {
7584

7685
public func installLatestVersion() -> AsyncThrowingStream<InstallationStep, Swift.Error> {
7786
AsyncThrowingStream<InstallationStep, Swift.Error> { continuation in
78-
Task {
87+
Task { @GitHubCopilotSuggestionActor in
7988
guard !GitHubCopilotInstallationManager.isInstalling else {
8089
continuation.finish(throwing: Error.isInstalling)
8190
return

0 commit comments

Comments
 (0)