-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Expand file tree
/
Copy pathConfigPathUtils.swift
More file actions
87 lines (78 loc) · 3.55 KB
/
ConfigPathUtils.swift
File metadata and controls
87 lines (78 loc) · 3.55 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
import Foundation
import CryptoKit
import Logger
let BaseAppDirectory = "github-copilot/xcode"
/// String extension for hashing functionality
extension String {
/// Generates a SHA256 hash of the string
/// - Parameter length: The length of the hash to return, defaults to 16 characters
/// - Returns: The hashed string
func hashed(_ length: Int = 16) -> String {
let data = Data(self.utf8)
let hashData = SHA256.hash(data: data)
let hashValue = hashData.compactMap { String(format: "%02x", $0 ) }.joined()
let index = hashValue.index(hashValue.startIndex, offsetBy: length)
return String(hashValue[..<index])
}
}
/// Utilities for working with configuration file paths
struct ConfigPathUtils {
/// Returns the XDG config home directory, respecting the XDG_CONFIG_HOME environment variable if set.
/// Falls back to ~/.config if the environment variable is not set.
static func getXdgConfigHome() -> URL {
if let xdgConfigHome = ProcessInfo.processInfo.environment["XDG_CONFIG_HOME"],
xdgConfigHome.hasPrefix("/") {
return URL(fileURLWithPath: xdgConfigHome)
}
return FileManager.default.homeDirectoryForCurrentUser.appendingPathComponent(".config")
}
/// Generates a config file path for a specific user.
/// - Parameters:
/// - userName: The user name to generate a path for
/// - appDirectory: The application directory name, defaults to "github-copilot/xcode"
/// - fileName: The file name to append to the path
/// - Returns: The complete URL for the config file
static func configFilePath(
userName: String,
baseDirectory: String = BaseAppDirectory,
subDirectory: String? = nil,
fileName: String
) -> URL {
var baseURL: URL = getXdgConfigHome()
.appendingPathComponent(baseDirectory)
.appendingPathComponent(toHash(contents: userName))
if let subDirectory = subDirectory {
baseURL = baseURL.appendingPathComponent(subDirectory)
}
ensureDirectoryExists(at: baseURL)
return baseURL.appendingPathComponent(fileName)
}
/// Ensures a directory exists at the specified URL, creating it if necessary.
/// - Parameter url: The directory URL
private static func ensureDirectoryExists(at url: URL) {
let fileManager = FileManager.default
if !fileManager.fileExists(atPath: url.path) {
do {
try fileManager.createDirectory(at: url, withIntermediateDirectories: true, attributes: nil)
} catch let error as NSError {
if error.domain == NSPOSIXErrorDomain && error.code == EACCES {
Logger.client.error("Permission denied when trying to create directory: \(url.path)")
} else {
Logger.client.info("Failed to create directory: \(error)")
}
}
}
}
/// Generates a hash from a string using SHA256.
/// - Parameters:
/// - contents: The string to hash
/// - length: The length of the hash to return, defaults to 16 characters
/// - Returns: The hashed string
static func toHash(contents: String, _ length: Int = 16) -> String {
let data = Data(contents.utf8)
let hashData = SHA256.hash(data: data)
let hashValue = hashData.compactMap { String(format: "%02x", $0 ) }.joined()
let index = hashValue.index(hashValue.startIndex, offsetBy: length)
return String(hashValue[..<index])
}
}