gds¶
Package gds is the GDS process of docs/gds (GDS 0001) as a library: it loads the
discussion records of a directory into a Catalog, plans changes to them (a new draft,
a promotion, a state or label change, the regenerated index) as a Plan, applies a plan
as one recoverable transaction under a lock. RST publication uses the project engine;
Typst typesets PDF.
Failure is a Problem that carries the exit status, never a panic. It allocates with
context.allocator and frees nothing, so a caller runs it in an arena, as guidedog gds
does, and frees the arena when done.
Types
- gds.Options :: struct¶
-
- dir: string¶
- command: string¶
- identifier: string¶
- slug: string¶
- labels: string¶
- state: string¶
- label: string¶
- to: string¶
- reason: string¶
- evidence: string¶
- discussion: string¶
- record: string¶
- target: string¶
- number: int¶
- dry_run: bool¶
- check_only: bool¶
- historical: bool¶
- render: bool¶
- rollback: bool¶
- gds.Problem :: struct¶
-
- code: string¶
- title: string¶
- path: string¶
- message: string¶
- hint: string¶
- exit: int¶
- gds.Record :: struct¶
-
- number: string¶
- slug: string¶
- title: string¶
- state: string¶
- kind: string¶
- created: string¶
- updated: string¶
- discussion: string¶
- labels: []string¶
- path: string¶
- text: string¶
- historical: bool¶
Procedures
- gds.apply :: proc(dir: string, plan: Plan) -> Problem¶
-
apply writes a plan’s changes as one transaction under dir: each file must still have the contents the plan was made from, a journal records the originals first, and every file is replaced atomically, so an interrupted apply can be rolled back by recover. Hold lock while planning and applying.
- gds.build :: proc(o: Options, c: Catalog, engine: string) -> (string, Problem)¶
-
build publishes o.target 「pdf」, 「html」, or 「both」 (the default). An RST catalog uses the project engine: HTML is a complete site and o.record selects separate PDF books. A legacy Typst catalog compiles records directly into docs/build. It returns the output paths, comma-separated. Typst is needed only for RST PDF or legacy publication; engine names its program, unless the compiler is embedded. Publication is staged so a compiler failure cannot replace a previously good output.
- gds.check_index :: proc(dir: string, c: Catalog) -> Problem¶
-
check_index is a Problem when the registry or bundle of dir differs from what index_plan would write.
- gds.check_sources :: proc(c: Catalog) -> Problem¶
-
check_sources checks that every record other than a historical one has the sections the discussion template requires; the first missing one is a Problem.
- gds.edit_plan :: proc(o: Options, c: Catalog) -> (plan: Plan, p: Problem)¶
-
edit_plan plans the change o.command asks of the record o.identifier names: promote (a draft takes the next number), state (a move the process allows, with its reason and evidence), or label; with the index refreshed. It changes nothing; apply writes the plan. A historical record, or a move the process forbids, is a Problem.
- gds.index_plan :: proc(dir: string, c: Catalog) -> (plan: Plan, p: Problem)¶
-
index_plan plans the regenerated registry.typ and bundle.typ of dir for the catalog; the plan has no changes when they are current.
- gds.load :: proc(dir: string) -> (catalog: Catalog, p: Problem)¶
-
load reads the discussion directory dir (records/*.rst or legacy *.typ), and the numbers it reserves, into a catalog allocated in the context arena. It fails with a Problem, and changes nothing, when an update awaits recovery, a record is unreadable, too large, or malformed, or two records claim one number or slug.
- gds.lock :: proc(dir: string) -> (^os.File, Problem)¶
-
lock takes the lock of the discussion directory dir and returns its file, which the caller holds while it plans and applies, and closes to release; another command holding it is a Problem. A kernel lock is released even if the process crashes. The lock file is kept: unlinking it would allow two processes to lock different inodes at the same path.
- gds.new_plan :: proc(o: Options, c: Catalog) -> (plan: Plan, p: Problem)¶
-
new_plan plans a new draft record for o.identifier: its file, from the template, and the refreshed index. It changes nothing; apply writes the plan. A bad or taken slug, or no author (–author, or git’s user.name), is a Problem.
- gds.next_number :: proc(o: Options, c: Catalog) -> (int, Problem)¶
-
next_number is the number a promoted draft takes: o.number when it is free, else one past the highest that a record, the registry’s reservation, or a gds/ branch of the repository in o.dir holds. A number already reserved, or above 9999, is a Problem.
- gds.now :: proc() -> datetime.DateTime¶
-
now is the moment a build is stamped with. As in Sphinx and other reproducible builds, SOURCE_DATE_EPOCH (seconds since 1970, in UTC) sets it; otherwise it is the local time, in the local time zone, which stays loaded for the life of the process.
- gds.parse_record :: proc(path, source: string) -> (r: Record, p: Problem)¶
-
parse_record reads RST metadata or legacy #let gds-… lines from source; the record borrows path and source. A missing, repeated, unknown, or invalid field, a bad slug, or dates out of order is a Problem.
- gds.problem :: proc(code, title, path, message, hint: string, exit := 1) -> Problem¶
-
problem makes a Problem: its code (「gds.slug」), title, the path it concerns, what went wrong, a hint, and the exit status the command returns for it.
- gds.recover :: proc(dir: string, dry_run: bool) -> Problem¶
-
recover finishes an interrupted apply: it restores every file the journal names to its original contents and removes the journal; dry_run only checks that it can. No journal is no work.
- gds.replace_field :: proc(source, key, literal: string) -> string¶
-
replace_field returns source with the value of the metadata field key replaced by the Typst literal (quoted, as 「\」accepted\」」), allocated in the context arena.
- gds.resolve :: proc(c: Catalog, id: string) -> (Record, Problem)¶
-
resolve finds the one record an identifier names: its number (7 or 「0007」), slug, title, or file name. The record borrows the catalog; no match, or more than one, is a Problem that lists the candidates.
- gds.today :: proc() -> string¶
-
today is now’s date, as YYYY-MM-DD.
Constants
- gds.LABELS¶
- gds.STATES :: []string{"prediscussion", "discussion", "accepted", "published", "committed", "abandoned"}¶