Improve storage, paths

This commit is contained in:
Christoph Hagen
2024-12-16 21:01:38 +01:00
parent b22b76fd32
commit 849585acc7
19 changed files with 393 additions and 268 deletions

View File

@ -20,41 +20,12 @@ extension Content {
return generateInternal(page, in: language)
}
private func startGenerating() -> Bool {
guard !isGeneratingWebsite else {
return false
}
// TODO: Fix bug where multiple generating operations can be started
// due to dispatch of locking property on main queue
DispatchQueue.main.async {
self.isGeneratingWebsite = true
}
return true
}
private func endGenerating() {
DispatchQueue.main.async {
self.isGeneratingWebsite = false
}
}
private func generateInternal(_ page: Page, in language: ContentLanguage) -> Bool {
let generator = LocalizedWebsiteGenerator(
content: self,
language: language)
if !generator.generate(page: page) {
print("Generation failed")
return false
}
return true
}
// MARK: Paths to items
private func makeCleanAbsolutePath(_ path: String) -> String {
("/" + path).replacingOccurrences(of: "//", with: "/")
}
// MARK: Paths to items
func absoluteUrlPrefixForTag(_ tag: Tag, language: ContentLanguage) -> String {
makeCleanAbsolutePath(settings.paths.tagsOutputFolderPath + "/" + tag.localized(in: language).urlComponent)
}
@ -101,4 +72,86 @@ extension Content {
}
return result
}
// MARK: Generation
private func startGenerating() -> Bool {
guard !isGeneratingWebsite else {
return false
}
// TODO: Fix bug where multiple generating operations can be started
// due to dispatch of locking property on main queue
DispatchQueue.main.async {
self.isGeneratingWebsite = true
}
return true
}
private func endGenerating() {
DispatchQueue.main.async {
self.isGeneratingWebsite = false
}
}
private func generateInternal(_ page: Page, in language: ContentLanguage) -> Bool {
let pagesFolder = settings.paths.pagesOutputFolderPath
guard storage.create(folder: pagesFolder, in: .outputPath) else {
print("Failed to generate output folder")
return false
}
let imageGenerator = ImageGenerator(
storage: storage,
settings: settings)
let pageGenerator = PageGenerator(
content: self,
imageGenerator: imageGenerator)
let content: String
let results: PageGenerationResults
do {
(content, results) = try pageGenerator.generate(page: page, language: language)
} catch {
print("Failed to generate page \(page.id) in language \(language): \(error)")
return false
}
guard !content.trimmed.isEmpty else {
#warning("Generate page with placeholder content")
return true
}
let path = page.absoluteUrl(in: language) + ".html"
do {
try storage.write(content: content, to: path)
} catch {
print("Failed to save page \(page.id): \(error)")
return false
}
guard imageGenerator.runJobs(callback: { _ in }) else {
return false
}
guard copy(requiredFiles: results.files) else {
return false
}
return true
return true
}
private func copy(requiredFiles: Set<FileResource>) -> Bool {
//print("Copying \(requiredVideoFiles.count) files...")
for file in requiredFiles {
guard !file.isExternallyStored else {
continue
}
do {
try storage.copy(file: file.id, to: file.absoluteUrl)
} catch {
print("Failed to copy file \(file.id): \(error)")
return false
}
}
return true
}
}

View File

@ -41,7 +41,10 @@ extension Content {
}
func loadFromDisk() throws {
let storage = Storage(baseFolder: URL(filePath: contentPath))
guard storageIsInitialized else {
print("Storage not initialized, not loading content")
return
}
let settings = try storage.loadSettings()
let imageDescriptions = try storage.loadFileDescriptions().reduce(into: [:]) { descriptions, description in

View File

@ -3,6 +3,10 @@ import Foundation
extension Content {
func saveToDisk() throws {
guard storageIsInitialized else {
print("Storage not initialized, not saving content")
return
}
//print("Starting save")
for page in pages {
try storage.save(pageMetadata: page.pageFile, for: page.id)

View File

@ -4,6 +4,11 @@ import Combine
final class Content: ObservableObject {
let storage = Storage()
@Published
var storageIsInitialized = false
@Published
var settings: Settings
@ -28,48 +33,23 @@ final class Content: ObservableObject {
@Published
var isGeneratingWebsite = false
@AppStorage("contentPath")
private var storedContentPath: String = ""
@Published
var contentPath: String = "" {
didSet {
storedContentPath = contentPath
}
}
let storage: Storage
private var cancellables = Set<AnyCancellable>()
init(settings: Settings,
posts: [Post],
pages: [Page],
tags: [Tag],
files: [FileResource],
tagOverview: TagOverviewPage?,
storedContentPath: String) {
tagOverview: TagOverviewPage?) {
self.settings = settings
self.posts = posts
self.pages = pages
self.tags = tags
self.files = files
self.tagOverview = tagOverview
self.storedContentPath = storedContentPath
self.contentPath = storedContentPath
self.storage = Storage(baseFolder: URL(filePath: storedContentPath))
do {
try storage.createFolderStructure()
} catch {
print(error)
return
}
observeContentPath()
initialize()
}
init() {
self.storage = Storage(baseFolder: URL(filePath: ""))
self.settings = .mock
self.posts = []
self.pages = []
@ -77,29 +57,24 @@ final class Content: ObservableObject {
self.files = []
self.tagOverview = nil
contentPath = storedContentPath
do {
try storage.createFolderStructure()
} catch {
print(error)
initialize()
}
private func initialize() {
guard storage.check(contentPath: settings.paths.contentDirectoryPath) == .nominal else {
storageIsInitialized = false
return
}
try? storage.update(baseFolder: URL(filePath: contentPath))
observeContentPath()
}
storage.check(outputPath: settings.paths.outputDirectoryPath)
private func observeContentPath() {
$contentPath.sink { newValue in
let url = URL(filePath: newValue)
do {
try self.storage.update(baseFolder: url)
try self.loadFromDisk()
} catch {
print("Failed to switch content path: \(error)")
}
do {
try storage.createFolderStructure()
storageIsInitialized = true
} catch {
print("Failed to initialize storage: \(error)")
storageIsInitialized = false
}
.store(in: &cancellables)
}
var images: [FileResource] {

View File

@ -2,6 +2,9 @@ import Foundation
final class PathSettings: ObservableObject {
@Published
var contentDirectoryPath: String
@Published
var outputDirectoryPath: String
@ -24,6 +27,7 @@ final class PathSettings: ObservableObject {
var tagsOutputFolderPath: String
init(file: PathSettingsFile) {
self.contentDirectoryPath = file.contentDirectoryPath
self.assetsOutputFolderPath = file.assetsOutputFolderPath
self.outputDirectoryPath = file.outputDirectoryPath
self.pagesOutputFolderPath = file.pagesOutputFolderPath
@ -34,7 +38,8 @@ final class PathSettings: ObservableObject {
}
var file: PathSettingsFile {
.init(outputDirectoryPath: outputDirectoryPath,
.init(contentDirectoryPath: contentDirectoryPath,
outputDirectoryPath: outputDirectoryPath,
assetsOutputFolderPath: assetsOutputFolderPath,
pagesOutputFolderPath: pagesOutputFolderPath,
imagesOutputFolderPath: imagesOutputFolderPath,