CHGenerator/Sources/Generator/Files/FileUpdateChecker.swift
2022-12-04 19:15:22 +01:00

93 lines
2.4 KiB
Swift

import Foundation
import CryptoKit
final class FileUpdateChecker {
private let hashesFileName = "hashes.json"
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] = [:]
var numberOfFilesLoaded: Int {
previousFiles.count
}
var numberOfFilesAccessed: Int {
accessedFiles.count
}
init(input: URL) {
self.input = input
}
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
}
let data: Data
do {
data = try Data(contentsOf: url)
} catch {
return .failed("Failed to read hashes from last run: \(error)")
}
do {
self.previousFiles = try JSONDecoder().decode(from: data)
} catch {
return .failed("Failed to decode hashes from last run: \(error)")
}
return .loaded
}
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
}
func writeDetectedFileChanges(to folder: URL) -> String? {
let url = folder.appendingPathComponent(hashesFileName)
do {
let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted
let data = try encoder.encode(accessedFiles)
try data.write(to: url)
return nil
} catch {
return "Failed to save file hashes: \(error)"
}
}
}
var notFound = 0