diff options
| -rw-r--r-- | org/in_abstraction_artefacts.org | 7 | ||||
| -rw-r--r-- | org/out_ocda_sqlite_db.org | 82 | ||||
| -rw-r--r-- | src/sisudoc/ocda/abstraction/db_in.d | 5 | ||||
| -rw-r--r-- | src/sisudoc/outputs/io_out/sqlite_ocda_db.d | 82 |
4 files changed, 173 insertions, 3 deletions
diff --git a/org/in_abstraction_artefacts.org b/org/in_abstraction_artefacts.org index 6c6fca5..f0ee34c 100644 --- a/org/in_abstraction_artefacts.org +++ b/org/in_abstraction_artefacts.org @@ -1,4 +1,4 @@ --*- mode: org -*- +src/sisudoc/ocda/abstraction/db_in.d-*- mode: org -*- #+TITLE: sisudoc spine (doc_reform) markup source raw #+DESCRIPTION: documents - structuring, publishing in multiple formats & search #+FILETAGS: :spine:sourcefile:read: @@ -738,7 +738,10 @@ template spineAbstractionDbRead() { string _kk = _k["doc_has.".length .. $]; doc.doc_has[_kk] = _v; doc.doc_has_order ~= _kk; - } else if (_k.startsWith("schema.")) { + } else if (_k.startsWith("schema.") || _k.startsWith("build.")) { + /+ ↓ what the file is and what wrote it. Neither is part of the + document, and only the format version is wanted here. + +/ if (_k == "schema.version") { doc.format = "% SiSU Document Abstraction v" ~ _v; } diff --git a/org/out_ocda_sqlite_db.org b/org/out_ocda_sqlite_db.org index b75ea83..08a4305 100644 --- a/org/out_ocda_sqlite_db.org +++ b/org/out_ocda_sqlite_db.org @@ -222,6 +222,22 @@ template spineAbstractionDb() { -- output writers must have in order to produce a document. bytes are -- stored exactly as read, so sha256 matches the digest the abstraction -- was built with + -- + -- image what the output writers need to produce a document. + -- named by its bare filename, as the abstraction refers + -- to it, and shared by every language. + -- source the markup: the document file and the files it inserts, + -- one set per language. named by its path within the pod, + -- media/text/<lang>/<file>, because the bare names repeat + -- across languages and because that is where a pod + -- materialised from this database has to put them. + -- conf conf/document_make, the document's own configuration. + -- manifest pod.manifest, as the author wrote it. + -- + -- source, conf and manifest are what make this a document source and + -- not only a serialised abstraction: with them a pod can be written + -- back out of the file and rebuilt from the markup, rather than only + -- rendered from the objects. CREATE TABLE IF NOT EXISTS files ( id INTEGER PRIMARY KEY, role TEXT NOT NULL, @@ -361,6 +377,12 @@ template spineAbstractionDb() { +/ insertFileMeta("schema.name", "sisu-abstraction-db"); insertFileMeta("schema.version", ssp_format_version); + /+ ↓ which spine wrote the file. Not a property of the document and not + in the .ssp: it says what to blame when a database made months ago + reads oddly, and it is the one thing a file cannot be asked for + after the fact. + +/ + insertFileMeta("build.spine_version", doc_matters.generator_program.ver); insertMeta("source.filename", ssp_doc.source); insertBlock("source.", ssp_doc.source_info_order, ssp_doc.source_info); /+ ↓ the digest of the .ssp this database was built from. a file cannot @@ -709,6 +731,66 @@ template spineAbstractionDb() { file_stmt.execute(); file_stmt.reset(); } + /+ ↓ the markup, the configuration and the manifest. + Carried for the same reason the images are, and for one more: a + database that holds the markup is a document source, and a pod can + be written back out of it. The abstraction alone can be rendered + but not re-parsed, and a reader who wants to correct a sentence + needs the sentence as the author wrote it. + . + Stored as read, with the digest over those bytes, which is the + digest the abstraction was built with: source.digest in the header + is the sha256 over one line per markup file, and each line is + checkable against the row written here. + +/ + void _carry(string _role, string _name, string _path) { + import std.typecons : Nullable; + if (_path.length == 0 || _name.length == 0) { return; } + ubyte[] _bytes; + try { + if (_path.exists && _path.isFile) { _bytes = cast(ubyte[]) _path.read; } + } catch (Exception ex) { + _bytes = []; + } + if (_bytes.length == 0) { + if (doc_matters.opt.action.vox_gt_1) { + writeln(" ", _role, " not carried into abstraction db: ", _path); + } + return; + } + file_stmt.bind(":role", _role); + file_stmt.bind(":name", _name); + file_stmt.bind(":bytes", cast(long) _bytes.length); + file_stmt.bind(":sha256", sha256Of(_bytes).toHexString.to!string); + file_stmt.bind(":width", Nullable!int()); + file_stmt.bind(":height", Nullable!int()); + file_stmt.bind(":data", _bytes); + file_stmt.execute(); + file_stmt.reset(); + } + { + import std.path : baseName; + /+ ↓ the markup of this language. The writer runs once per language, + so the set of source rows fills up as the languages go by, and + UNIQUE(role, name) over the pod relative path is what keeps a + second run from writing them twice. + +/ + string _text_dir = "media/text/" ~ doc_matters.src.lng ~ "/"; + _carry("source", _text_dir ~ doc_matters.src.filename, + doc_matters.src.file_with_absolute_path.to!string); + foreach (_insert; doc_matters.srcs.file_insert_list) { + _carry("source", _text_dir ~ _insert.baseName, _insert); + } + /+ ↓ the configuration and the manifest, one of each for the whole + document however many languages it has + +/ + _carry("conf", "conf/document_make", + doc_matters.src.conf_dir_path.to!string ~ "/document_make"); + if (doc_matters.src.is_pod) { + _carry("manifest", "pod.manifest", + doc_matters.pod.manifest_file_with_path); + } + } file_stmt.finalize(); } diff --git a/src/sisudoc/ocda/abstraction/db_in.d b/src/sisudoc/ocda/abstraction/db_in.d index 7f1b2c3..53ac95d 100644 --- a/src/sisudoc/ocda/abstraction/db_in.d +++ b/src/sisudoc/ocda/abstraction/db_in.d @@ -204,7 +204,10 @@ template spineAbstractionDbRead() { string _kk = _k["doc_has.".length .. $]; doc.doc_has[_kk] = _v; doc.doc_has_order ~= _kk; - } else if (_k.startsWith("schema.")) { + } else if (_k.startsWith("schema.") || _k.startsWith("build.")) { + /+ ↓ what the file is and what wrote it. Neither is part of the + document, and only the format version is wanted here. + +/ if (_k == "schema.version") { doc.format = "% SiSU Document Abstraction v" ~ _v; } diff --git a/src/sisudoc/outputs/io_out/sqlite_ocda_db.d b/src/sisudoc/outputs/io_out/sqlite_ocda_db.d index aa91e89..d30295a 100644 --- a/src/sisudoc/outputs/io_out/sqlite_ocda_db.d +++ b/src/sisudoc/outputs/io_out/sqlite_ocda_db.d @@ -240,6 +240,22 @@ template spineAbstractionDb() { -- output writers must have in order to produce a document. bytes are -- stored exactly as read, so sha256 matches the digest the abstraction -- was built with + -- + -- image what the output writers need to produce a document. + -- named by its bare filename, as the abstraction refers + -- to it, and shared by every language. + -- source the markup: the document file and the files it inserts, + -- one set per language. named by its path within the pod, + -- media/text/<lang>/<file>, because the bare names repeat + -- across languages and because that is where a pod + -- materialised from this database has to put them. + -- conf conf/document_make, the document's own configuration. + -- manifest pod.manifest, as the author wrote it. + -- + -- source, conf and manifest are what make this a document source and + -- not only a serialised abstraction: with them a pod can be written + -- back out of the file and rebuilt from the markup, rather than only + -- rendered from the objects. CREATE TABLE IF NOT EXISTS files ( id INTEGER PRIMARY KEY, role TEXT NOT NULL, @@ -379,6 +395,12 @@ template spineAbstractionDb() { +/ insertFileMeta("schema.name", "sisu-abstraction-db"); insertFileMeta("schema.version", ssp_format_version); + /+ ↓ which spine wrote the file. Not a property of the document and not + in the .ssp: it says what to blame when a database made months ago + reads oddly, and it is the one thing a file cannot be asked for + after the fact. + +/ + insertFileMeta("build.spine_version", doc_matters.generator_program.ver); insertMeta("source.filename", ssp_doc.source); insertBlock("source.", ssp_doc.source_info_order, ssp_doc.source_info); /+ ↓ the digest of the .ssp this database was built from. a file cannot @@ -727,6 +749,66 @@ template spineAbstractionDb() { file_stmt.execute(); file_stmt.reset(); } + /+ ↓ the markup, the configuration and the manifest. + Carried for the same reason the images are, and for one more: a + database that holds the markup is a document source, and a pod can + be written back out of it. The abstraction alone can be rendered + but not re-parsed, and a reader who wants to correct a sentence + needs the sentence as the author wrote it. + . + Stored as read, with the digest over those bytes, which is the + digest the abstraction was built with: source.digest in the header + is the sha256 over one line per markup file, and each line is + checkable against the row written here. + +/ + void _carry(string _role, string _name, string _path) { + import std.typecons : Nullable; + if (_path.length == 0 || _name.length == 0) { return; } + ubyte[] _bytes; + try { + if (_path.exists && _path.isFile) { _bytes = cast(ubyte[]) _path.read; } + } catch (Exception ex) { + _bytes = []; + } + if (_bytes.length == 0) { + if (doc_matters.opt.action.vox_gt_1) { + writeln(" ", _role, " not carried into abstraction db: ", _path); + } + return; + } + file_stmt.bind(":role", _role); + file_stmt.bind(":name", _name); + file_stmt.bind(":bytes", cast(long) _bytes.length); + file_stmt.bind(":sha256", sha256Of(_bytes).toHexString.to!string); + file_stmt.bind(":width", Nullable!int()); + file_stmt.bind(":height", Nullable!int()); + file_stmt.bind(":data", _bytes); + file_stmt.execute(); + file_stmt.reset(); + } + { + import std.path : baseName; + /+ ↓ the markup of this language. The writer runs once per language, + so the set of source rows fills up as the languages go by, and + UNIQUE(role, name) over the pod relative path is what keeps a + second run from writing them twice. + +/ + string _text_dir = "media/text/" ~ doc_matters.src.lng ~ "/"; + _carry("source", _text_dir ~ doc_matters.src.filename, + doc_matters.src.file_with_absolute_path.to!string); + foreach (_insert; doc_matters.srcs.file_insert_list) { + _carry("source", _text_dir ~ _insert.baseName, _insert); + } + /+ ↓ the configuration and the manifest, one of each for the whole + document however many languages it has + +/ + _carry("conf", "conf/document_make", + doc_matters.src.conf_dir_path.to!string ~ "/document_make"); + if (doc_matters.src.is_pod) { + _carry("manifest", "pod.manifest", + doc_matters.pod.manifest_file_with_path); + } + } file_stmt.finalize(); } |
