diff options
| author | Ralph Amissah <ralph.amissah@gmail.com> | 2026-09-21 15:52:16 -0400 |
|---|---|---|
| committer | Ralph Amissah <ralph.amissah@gmail.com> | 2026-09-22 17:24:13 -0400 |
| commit | 0fb266da0aa1925700f2685057fcd3b0711e4733 (patch) | |
| tree | b7ca3539aa275b4a87b6062504e2ba057082a706 /src | |
| parent | cleanup: misc. (previously deferred) (diff) | |
read: db names outputs from manifest carried
ensure that db uses the names it carries in manifest which produce
deterministic output (and fix divergence in db rendering of output
names, (which previously also looked for variable input from the
environment))
Output built from a database with --config naming the site configuration
is now byte identical to output built from the pod, on the render route
as it already was on the materialise route.
(assisted by Claude-Code)
Diffstat (limited to 'src')
| -rw-r--r-- | src/sisudoc/ocda/abstraction/doc_from_artefact.d | 44 |
1 files changed, 39 insertions, 5 deletions
diff --git a/src/sisudoc/ocda/abstraction/doc_from_artefact.d b/src/sisudoc/ocda/abstraction/doc_from_artefact.d index fa620f8..b3d208c 100644 --- a/src/sisudoc/ocda/abstraction/doc_from_artefact.d +++ b/src/sisudoc/ocda/abstraction/doc_from_artefact.d @@ -247,9 +247,12 @@ template spineDocFromArtefact() { import std.digest.sha : sha256Of; import std.file : mkdirRecurse, write, tempDir; import sisudoc.ocda.abstraction.db_in : spineAbstractionDbRead; + import sisudoc.ocda.abstraction.pod_from_db : spinePodFromDb; mixin spineAbstractionDbRead _dbr; + mixin spinePodFromDb _pfd; auto _files = _dbr.dbReadFiles(_artefact, "image"); - if (_files.length == 0) { return ""; } + auto _manifest = _dbr.dbReadFiles(_artefact, "manifest"); + if (_files.length == 0 && _manifest.length == 0) { return ""; } /+ ↓ every name checked before anything is created or written. the name comes out of the database and a database can be downloaded, so it is attacker-controlled: it can climb with "..", @@ -268,8 +271,25 @@ template spineDocFromArtefact() { return ""; } } - string _root = (tempDir.chainPath("spine-ocda-" + /+ ↓ the directory this makes is a pod, named for the document, and not + a bare place to put images. + . + Because a document's output files are named from its pod: no pod, + and doc_uid_out takes its other branch and prefixes an underscore, + so the same database rendered here wrote _live-manual.en.txt where + the pod it came from writes live-manual.en.txt. It mixed environment: + a database sitting beside a pod tree borrowed that pod's name and got + it right, and the same database moved elsewhere did not. + . + A database carries its own pod.manifest, so it can say what it is + called without being told. Written here beside the images, which + makes this a pod as far as PathMatters is concerned, and the naming + is then the document's own wherever the file happens to be. + +/ + string _tmp = (tempDir.chainPath("spine-ocda-" ~ _artefact.baseName ~ "-" ~ thisProcessID.to!string).array).to!string; + string _root = (_tmp.chainPath(_pfd.podNameFromDbPath(_artefact)) + .array).to!string; string _img_dir = (_root.chainPath("media").chainPath("image").array).to!string; try { _img_dir.mkdirRecurse; @@ -278,6 +298,16 @@ template spineDocFromArtefact() { ": ", ex.msg); return ""; } + foreach (_m; _manifest) { + if (validateCarriedPath(_m.name).length > 0) { continue; } + string _m_path = (_root.chainPath(_m.name).array).to!string; + if (!(carriedPathIsWithin(_root, _m_path))) { continue; } + try { + _m_path.write(_m.data); + } catch (Exception ex) { + stderr.writeln("WARNING: could not write ", _m.name, ": ", ex.msg); + } + } foreach (_f; _files) { string _got = _f.data.sha256Of.toHexString.to!string; if (_f.sha256.length > 0 && _got != _f.sha256) { @@ -380,9 +410,13 @@ template spineDocFromArtefact() { } else { string _extracted = _imagesExtract(_artefact, _opt_action); if (_extracted.length > 0) { - /+ ↓ the source path has to move with it: image_dir_path is - reached from the document's own file, not from the pod +/ - _images_tmp = _extracted; + /+ ↓ the source path has to move with it: image_dir_path is reached + from the document's own file, not from the pod. What is removed + afterwards is the pod's *parent*, the directory this run made: + the pod inside it is named for the document, and removing only + that would leave the parent. + +/ + _images_tmp = _extracted.dirName; _pths.pod_dir = _extracted; _pths.src_file_with_path = (_extracted .chainPath("media").chainPath("text") |
