Skip to content

Instantly share code, notes, and snippets.

@asenchenkov
Last active April 28, 2022 12:19
Show Gist options
  • Save asenchenkov/0a861bf7f1a0349bad1f3c898db1a5b7 to your computer and use it in GitHub Desktop.
Save asenchenkov/0a861bf7f1a0349bad1f3c898db1a5b7 to your computer and use it in GitHub Desktop.
Скрипт запускается в Pre-actions Xcode и принимает решение о скачивании кэша или же сразу переходит к фазе сборки
#!/usr/bin/xcrun --sdk macosx swift
import Foundation
@discardableResult
func shell(_ command: String) -> String {
let task = Process()
let pipe = Pipe()
task.standardOutput = pipe
task.standardError = pipe
task.arguments = ["-c", command]
task.launchPath = "/bin/zsh"
task.launch()
let data = pipe.fileHandleForReading.readDataToEndOfFile()
let output = String(data: data, encoding: .utf8)!
return output
}
enum CarthageCache {
enum Files {
static let local = "./.carthage-cache-config.json"
}
struct Local: Codable {
let cachePrefix: String
let cartfileResolvedMD5: String
let cartfileMD5: String
}
struct Configuration {
let local: Local
}
private static func load<T: Decodable>(fromFile path: String) -> T? {
do {
let stringData = try String(contentsOfFile: path)
if let data = stringData.data(using: .utf8), let result = try? JSONDecoder().decode(T.self, from: data) {
print("Saved carthage cache configuration at \(path): \(result)")
return result
} else {
return nil
}
} catch {
print("Error get carthage cache configuration at \(path): \(error)")
}
return nil
}
static func loadConfiguration() -> Configuration? {
guard
let local: Local = load(fromFile: Files.local)
else { return nil }
return Configuration(local: local)
}
}
class RomeCacheDownloadVerify {
private let fileManager = FileManager.default
private lazy var carthageCacheConfiguration: CarthageCache.Configuration? = CarthageCache.loadConfiguration()
/// Имеем ли папку с Carthage (просто папку, даже пустую)
private var hasCarthageFolder: Bool {
var isDirectory: ObjCBool = true
return fileManager.fileExists(atPath: "./Carthage", isDirectory: &isDirectory) && isDirectory.boolValue
}
/// Текущий префикс для кэша (состоит их swift --version)
private var currentCachePrefix: String {
let currentCachePrefix = shell("./carthage_cache_prefix.sh")
.trimmingCharacters(in: .whitespacesAndNewlines)
print("cachePrefix: \(currentCachePrefix)")
return currentCachePrefix
}
/// Валидация xcframework файлов
private var verifyCarthageLibs: Bool {
let validatorResult = shell("./carthage-cache-validator.swift")
print("validatorResult: \(validatorResult)")
return validatorResult.contains("true")
}
/// Храним кэш Cartfile.resolved чтобы чекать в нем изменения
private var currentCartfileResolvedMD5: String {
let configUrl = shell("md5sum Cartfile.resolved")
return configUrl.components(separatedBy: " ").first ?? ""
}
/// Храним кэш Cartfile чтобы чекать в нем изменения
private var currentCartfileMD5: String {
let configUrl = shell("md5sum Cartfile")
return configUrl.components(separatedBy: " ").first ?? ""
}
/// Менялся ли Cartfile.resolved
private var isChangedCartfileResolved: Bool {
currentCartfileResolvedMD5 != carthageCacheConfiguration?.local.cartfileResolvedMD5
}
/// Менялся ли Cartfile
private var isChangedCartfile: Bool {
currentCartfileMD5 != carthageCacheConfiguration?.local.cartfileMD5
}
/// Совпадает ли сохраненный префикс из конфига с текущим
private var isValidCachePrefix: Bool {
currentCachePrefix == carthageCacheConfiguration?.local.cachePrefix
}
/// Проверяем на ошибки
private func verify() -> String {
var errorString = ""
if currentCartfileResolvedMD5.isEmpty {
errorString.append("\nError: No current Cartfile.resolved MD5")
}
if currentCartfileMD5.isEmpty {
errorString.append("\nError: No current Cartfile MD5")
}
if !currentCachePrefix.contains("swift") {
errorString.append("\nError: generate prefix")
}
return errorString
}
/// Все проверки в одном месте запускаем
public func verifyDownloadCache() -> Bool {
let errorString = verify()
guard errorString.isEmpty else {
print(errorString)
exit(1)
}
return hasCarthageFolder &&
isValidCachePrefix &&
!isChangedCartfileResolved &&
!isChangedCartfile &&
verifyCarthageLibs
}
}
// Run script
let info = ProcessInfo.processInfo
print("Process info")
print("Process identifier:", info.processIdentifier)
print("System uptime:", info.systemUptime)
print("Globally unique process id string:", info.globallyUniqueString)
print("Process name:", info.processName)
print("\nSoftware info")
print("Host name:", info.hostName)
print("OS major version:", info.operatingSystemVersion.majorVersion)
print("OS version string", info.operatingSystemVersionString)
print("\nHardware info")
print("Active processor count:", info.activeProcessorCount)
print("Physical memory (bytes)", info.physicalMemory)
/// same as CommandLine.arguments
print("\nArguments")
print(ProcessInfo.processInfo.arguments)
let cacheVerify = RomeCacheDownloadVerify()
if cacheVerify.verifyDownloadCache() {
print("Carthage cache is valid")
exit(0)
} else {
print("Need update carthage cache")
exit(1)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment