CHGenerator/Sources/Generator/run.swift

188 lines
6.6 KiB
Swift
Raw Normal View History

2022-09-09 13:29:31 +02:00
import Foundation
import ArgumentParser
@main
struct CHGenerator: ParsableCommand {
@Argument(help: "The path to the generator configuration file")
var configPath: String
mutating func run() throws {
try generate(configPath: configPath)
}
}
private func loadConfiguration(at configPath: String) -> Configuration? {
print("--- CONFIGURATION ----------------------------------")
2022-12-04 19:15:22 +01:00
print(" ")
print(" Configuration file: \(configPath)")
2022-09-09 13:29:31 +02:00
let configUrl = URL(fileURLWithPath: configPath)
2022-12-10 22:28:39 +01:00
guard configUrl.exists else {
print(" Error: Configuration file not found")
return nil
}
var config: Configuration
do {
let data = try Data(contentsOf: configUrl)
config = try JSONDecoder().decode(from: data)
config.adjustPathsRelative(to: configUrl.deletingLastPathComponent())
} catch {
2022-12-04 19:15:22 +01:00
print(" Configuration error: \(error)")
return nil
}
config.printOverview()
print(" ")
return config
}
2022-12-05 17:25:07 +01:00
private func loadSiteData(in folder: URL, runFolder: URL) throws -> (root: Element, pageMap: PageMap)? {
2022-12-04 19:15:22 +01:00
print("--- SOURCE FILES -----------------------------------")
print(" ")
2022-12-04 23:10:44 +01:00
let log = MetadataInfoLogger(input: folder)
2022-12-04 19:15:22 +01:00
let root = Element(atRoot: folder, log: log)
2022-12-04 23:10:44 +01:00
let file = runFolder.appendingPathComponent("metadata.txt")
defer {
log.writeResults(to: file)
print(" ")
}
2022-12-04 19:15:22 +01:00
guard let root else {
2022-12-04 23:10:44 +01:00
log.printMetadataScanOverview(languages: 0)
print(" Error: No site root loaded, aborting generation")
2022-12-04 19:15:22 +01:00
return nil
}
2023-12-16 22:10:50 +01:00
let pageMap = root.languages.map { language in
(language: language.language,
pages: root.getExternalPageMap(language: language.language, log: log))
}
2022-12-04 23:10:44 +01:00
log.printMetadataScanOverview(languages: root.languages.count)
2022-12-05 17:25:07 +01:00
return (root, pageMap)
2022-12-04 19:15:22 +01:00
}
2022-12-05 17:25:07 +01:00
private func generatePages(from root: Element, configuration: Configuration, fileUpdates: FileUpdateChecker, pageMap: PageMap, runFolder: URL) -> (ImageData, FileData)? {
2022-12-04 19:15:22 +01:00
print("--- GENERATION -------------------------------------")
print(" ")
2022-09-09 13:29:31 +02:00
2022-12-05 17:25:07 +01:00
let pageCount = pageMap.reduce(0) { $0 + $1.pages.count }
2022-12-04 19:15:22 +01:00
let results = GenerationResultsHandler(
2022-09-09 13:29:31 +02:00
in: configuration.contentDirectory,
to: configuration.outputDirectory,
2022-12-04 19:15:22 +01:00
configuration: configuration,
fileUpdates: fileUpdates,
2022-12-05 17:25:07 +01:00
pageMap: pageMap,
2022-12-04 19:15:22 +01:00
pageCount: pageCount)
2022-12-04 23:10:44 +01:00
defer { results.printOverview() }
let siteGenerator: SiteGenerator
do {
siteGenerator = try SiteGenerator(results: results)
} catch {
return nil
}
2022-12-04 19:15:22 +01:00
siteGenerator.generate(site: root)
2022-12-04 23:10:44 +01:00
let url = runFolder.appendingPathComponent("pages.txt")
results.writeResults(to: url)
if let error = fileUpdates.writeDetectedFileChanges(to: runFolder) {
print(" Hashes not saved: \(error)")
}
2022-12-04 19:15:22 +01:00
return (results.images, results.files)
}
private func generateImages(_ images: ImageData, configuration: Configuration, runFolder: URL, fileUpdates: FileUpdateChecker) {
print("--- IMAGES -----------------------------------------")
print(" ")
let reader = ImageReader(in: configuration.contentDirectory, runFolder: runFolder, fileUpdates: fileUpdates)
let generator = ImageGenerator(
input: configuration.contentDirectory,
output: configuration.outputDirectory,
reader: reader, images: images)
generator.generateImages()
print(" ")
2022-12-04 23:10:44 +01:00
let file = runFolder.appendingPathComponent("images.txt")
generator.writeResults(to: file)
2022-12-04 19:15:22 +01:00
}
private func copyFiles(files: FileData, configuration: Configuration, runFolder: URL) {
print("--- FILES ------------------------------------------")
print(" ")
let generator = FileGenerator(
input: configuration.contentDirectory,
output: configuration.outputDirectory,
runFolder: runFolder,
files: files)
generator.generate()
2023-01-08 21:49:01 +01:00
let file = runFolder.appendingPathComponent("files.txt")
generator.writeResults(to: file)
2022-12-04 19:15:22 +01:00
}
2022-12-05 11:51:19 +01:00
private func finish(start: Date, complete: Bool) {
print("--- SUMMARY ----------------------------------------")
2022-12-04 19:15:22 +01:00
print(" ")
let duration = Int(-start.timeIntervalSinceNow.rounded())
2022-12-17 08:26:35 +01:00
if duration < 3600 {
2022-12-04 19:15:22 +01:00
print(String(format: " Duration: %d:%02d", duration / 60, duration % 60))
} else {
print(String(format: " Duration: %d:%02d:%02d", duration / 3600, (duration / 60) % 60, duration % 60))
}
2022-12-05 11:51:19 +01:00
print(" Complete: \(complete ? "Yes" : "No")")
print(" ")
print("----------------------------------------------------")
2022-12-04 19:15:22 +01:00
}
private func generate(configPath: String) throws {
let start = Date()
2022-12-05 11:51:19 +01:00
var complete = false
defer {
// 6. Print summary
finish(start: start, complete: complete)
}
2022-12-04 19:15:22 +01:00
2022-12-05 11:43:30 +01:00
print(" ")
guard checkDependencies() else {
return
}
2022-12-04 19:15:22 +01:00
// 1. Load configuration
guard let configuration = loadConfiguration(at: configPath) else {
return
}
let runFolder = configuration.contentDirectory.appendingPathComponent("run")
2022-09-09 13:29:31 +02:00
// 2. Scan site elements
2022-12-05 17:25:07 +01:00
guard let (siteRoot, pageMap) = try loadSiteData(in: configuration.contentDirectory, runFolder: runFolder) else {
2022-09-09 13:29:31 +02:00
return
}
2022-12-04 19:15:22 +01:00
let fileUpdates = FileUpdateChecker(input: configuration.contentDirectory)
switch fileUpdates.loadPreviousRun(from: runFolder) {
case .notLoaded:
print("Regarding all files as new (no hashes loaded)")
case .loaded:
break
case .failed(let error):
print("Regarding all files as new (\(error))")
}
// 3. Generate pages
2022-12-05 17:25:07 +01:00
guard let (images, files) = generatePages(from: siteRoot, configuration: configuration, fileUpdates: fileUpdates, pageMap: pageMap, runFolder: runFolder) else {
2022-12-04 23:10:44 +01:00
return
2022-12-04 19:15:22 +01:00
}
// 4. Generate images
generateImages(images, configuration: configuration, runFolder: runFolder, fileUpdates: fileUpdates)
// 5. Copy/minify files
copyFiles(files: files, configuration: configuration, runFolder: runFolder)
2022-09-09 13:29:31 +02:00
2022-12-05 11:51:19 +01:00
complete = true
2022-09-09 13:29:31 +02:00
}