CHGenerator/Sources/Generator/Files/FileUpdateChecker.swift

93 lines
2.4 KiB
Swift
Raw Normal View History

2022-09-18 16:48:15 +02:00
import Foundation
import CryptoKit
final class FileUpdateChecker {
2022-12-04 19:15:22 +01:00
private let hashesFileName = "hashes.json"
2022-09-18 16:48:15 +02:00
private let input: URL
/**
The hashes of all accessed files from the previous run
The key is the relative path to the file from the source
*/
private var previousFiles: [String : Data] = [:]
/**
The paths of all files which were accessed, with their new hashes
This list is used to check if a file was modified, and to write all accessed files back to disk
*/
private var accessedFiles: [String : Data] = [:]
2022-12-04 19:15:22 +01:00
var numberOfFilesLoaded: Int {
previousFiles.count
}
var numberOfFilesAccessed: Int {
accessedFiles.count
2022-09-18 16:48:15 +02:00
}
init(input: URL) {
self.input = input
2022-12-04 19:15:22 +01:00
}
enum LoadResult {
case notLoaded
case loaded
case failed(String)
}
func loadPreviousRun(from folder: URL) -> LoadResult {
let url = folder.appendingPathComponent(hashesFileName)
guard url.exists else {
return .notLoaded
2022-09-18 16:48:15 +02:00
}
let data: Data
do {
2022-12-04 19:15:22 +01:00
data = try Data(contentsOf: url)
2022-09-18 16:48:15 +02:00
} catch {
2022-12-04 19:15:22 +01:00
return .failed("Failed to read hashes from last run: \(error)")
2022-09-18 16:48:15 +02:00
}
do {
self.previousFiles = try JSONDecoder().decode(from: data)
} catch {
2022-12-04 19:15:22 +01:00
return .failed("Failed to decode hashes from last run: \(error)")
2022-09-18 16:48:15 +02:00
}
2022-12-04 19:15:22 +01:00
return .loaded
2022-09-18 16:48:15 +02:00
}
func fileHasChanged(at path: String) -> Bool {
guard let oldHash = previousFiles[path] else {
// Image wasn't used last time, so treat as new
return true
}
guard let newHash = accessedFiles[path] else {
// Each image should have been loaded once
// before using this function
fatalError()
}
return oldHash != newHash
}
func didLoad(_ data: Data, at path: String) {
accessedFiles[path] = SHA256.hash(data: data).data
}
2022-12-04 19:15:22 +01:00
func writeDetectedFileChanges(to folder: URL) -> String? {
let url = folder.appendingPathComponent(hashesFileName)
2022-09-18 16:48:15 +02:00
do {
let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted
let data = try encoder.encode(accessedFiles)
2022-12-04 19:15:22 +01:00
try data.write(to: url)
return nil
2022-09-18 16:48:15 +02:00
} catch {
2022-12-04 19:15:22 +01:00
return "Failed to save file hashes: \(error)"
2022-09-18 16:48:15 +02:00
}
}
}
2022-12-04 19:15:22 +01:00
var notFound = 0