forked from intitni/CopilotForXcode
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathGitHubCopilotInstallationManager.swift
More file actions
96 lines (81 loc) · 3.38 KB
/
GitHubCopilotInstallationManager.swift
File metadata and controls
96 lines (81 loc) · 3.38 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
import Foundation
import Terminal
public struct GitHubCopilotInstallationManager {
private static var isInstalling = false
public init() {}
public enum InstallationStatus {
case notInstalled
case installed
}
public func checkInstallation() -> InstallationStatus {
guard let urls = try? GitHubCopilotBaseService.createFoldersIfNeeded()
else { return .notInstalled }
let executableFolderURL = urls.executableURL
let binaryURL = executableFolderURL.appendingPathComponent("copilot")
if !FileManager.default.fileExists(atPath: binaryURL.path) {
return .notInstalled
}
return .installed
}
public enum InstallationStep {
case downloading
case uninstalling
case decompressing
case done
}
public enum Error: Swift.Error, LocalizedError {
case isInstalling
case failedToFindLanguageServer
public var errorDescription: String? {
switch self {
case .isInstalling:
return "Language server is installing."
case .failedToFindLanguageServer:
return "Failed to find language server. Please open an issue on GitHub."
}
}
}
public func installLatestVersion() -> AsyncThrowingStream<InstallationStep, Swift.Error> {
AsyncThrowingStream<InstallationStep, Swift.Error> { continuation in
Task {
guard !GitHubCopilotInstallationManager.isInstalling else {
continuation.finish(throwing: Error.isInstalling)
return
}
GitHubCopilotInstallationManager.isInstalling = true
defer { GitHubCopilotInstallationManager.isInstalling = false }
do {
continuation.yield(.downloading)
let urls = try GitHubCopilotBaseService.createFoldersIfNeeded()
let executable = Bundle.main.bundleURL.appendingPathComponent("Contents/Applications/CopilotForXcodeExtensionService.app/Contents/Resources/copilot")
guard FileManager.default.fileExists(atPath: executable.path) else {
throw Error.failedToFindLanguageServer
}
let targetURL = urls.executableURL.appendingPathComponent("copilot")
try FileManager.default.copyItem(
at: executable,
to: targetURL
)
// update permission 755
try FileManager.default.setAttributes(
[.posixPermissions: 0o755],
ofItemAtPath: targetURL.path
)
continuation.yield(.done)
continuation.finish()
} catch {
continuation.finish(throwing: error)
}
}
}
}
public func uninstall() async throws {
guard let urls = try? GitHubCopilotBaseService.createFoldersIfNeeded()
else { return }
let executableFolderURL = urls.executableURL
let binaryURL = executableFolderURL.appendingPathComponent("copilot")
if FileManager.default.fileExists(atPath: binaryURL.path) {
try FileManager.default.removeItem(at: binaryURL)
}
}
}