Export and import the session tree #2

Open
opened 2026-08-19 14:28:03 +00:00 by dusan · 0 comments
Owner

Context

Terminalko keeps everything in GSettings — there is no configuration file,
and the window is the only writer. The session tree lives at:

/me/dusansimic/terminalko/             folders=[…] scratch-sessions=[…] sessions=[…]
/me/dusansimic/terminalko/folders/ID/  name colour sessions=[…]
/me/dusansimic/terminalko/sessions/ID/ name colour type command cwd env …

Folders and sessions are relocatable schema instances keyed by UUID. See
docs/spec/session-model.md for why membership and order live only in the folder
list keys, and crates/terminalko-config/src/session.rs for the model
(Store, Folder, Session, Layout, TidyReport).

Schemas: data/me.dusansimic.terminalko.{,folder.,session.}gschema.xml.

Problem

dconf is not git-friendly and not portable between machines. A user who has built
up a set of sessions has no way to back them up, move them to another machine, or
keep them under version control. docs/spec/session-model.md already promises
this ("ship two explicit GUI actions: Export sessions… and Import
sessions…
") and it does not exist.

Goal

Export the session tree to a single human-readable file, and import it back.

Suggested approach

Format. A GLib keyfile is the natural choice: dconf dump already produces
one, glib::KeyFile reads and writes it, and it is diffable. Something like:

[folders/9f1374fd-…]
name='Work'
colour='cyan'
sessions=['a1b2…', 'c3d4…']

[sessions/a1b2…]
name='API server'
type='ssh'
ssh-host='example.com'

Keeping it dconf dump-compatible is worth it — dconf load /me/dusansimic/terminalko/ < file then works as a fallback path, and users can
inspect an export with tools they already have.

Where. Add to terminalko-config (so terminalkoctl could use it later),
e.g. Store::export_to_keyfile() -> glib::KeyFile and
Store::import_from_keyfile(&KeyFile, ImportMode).

Import needs a decision, not a default. Offer Replace (clear the tree
first) and Merge (keep what is there, giving imported folders and sessions
fresh UUIDs so an import cannot collide with or overwrite existing work).
The dialog must say which is which.

Validation. Imported data comes from a file a user may have edited:

  • ignore keys that are not in the schema rather than failing;
  • an unknown type, restart, container-runtime or escalation value must
    fall back the way the model already does;
  • after importing, run Store::tidy() so a truncated file cannot leave dangling
    references — it adopts orphans and drops references to sessions that do not
    exist, and reports what it repaired.

UI. Two entries in the primary menu (ui/window.blp) and two window
actions, using gtk::FileDialog. Report the outcome as a toast or a message
including the counts, and what tidy() had to repair.

Acceptance criteria

  • Export produces a file that re-imports to an identical tree (same names,
    colours, types, order, folder membership) on a fresh configuration.
  • Import in Merge mode never modifies or deletes an existing session, and
    assigns new UUIDs to what it adds.
  • Import in Replace mode leaves exactly what was in the file.
  • A truncated or hand-mangled file imports what it can and reports the rest; it
    never leaves the tree in a state that tidy() still wants to repair.
  • Round-trip tests in terminalko-config running headless with
    GSETTINGS_BACKEND=memory — see the existing with_store helper in
    session.rs tests, which takes the process-wide lock and starts from an empty
    tree.
  • ./build-aux/ci.sh passes; ./build-aux/smoke.sh still passes.
  • docs/spec/session-model.md updated to describe the format and the two import
    modes.

Notes

  • Do not make the agent or terminalkoctl write configuration: the window is
    the only writer, and that rule is what keeps the model consistent.
  • The project is BSD-2-Clause; see CONTRIBUTING.md before looking at any
    GPL-licensed terminal for reference.
## Context Terminalko keeps everything in **GSettings** — there is no configuration file, and the window is the only writer. The session tree lives at: ```text /me/dusansimic/terminalko/ folders=[…] scratch-sessions=[…] sessions=[…] /me/dusansimic/terminalko/folders/ID/ name colour sessions=[…] /me/dusansimic/terminalko/sessions/ID/ name colour type command cwd env … ``` Folders and sessions are **relocatable schema instances** keyed by UUID. See `docs/spec/session-model.md` for why membership and order live only in the folder list keys, and `crates/terminalko-config/src/session.rs` for the model (`Store`, `Folder`, `Session`, `Layout`, `TidyReport`). Schemas: `data/me.dusansimic.terminalko.{,folder.,session.}gschema.xml`. ## Problem dconf is not git-friendly and not portable between machines. A user who has built up a set of sessions has no way to back them up, move them to another machine, or keep them under version control. `docs/spec/session-model.md` already promises this ("ship two explicit GUI actions: *Export sessions…* and *Import sessions…*") and it does not exist. ## Goal Export the session tree to a single human-readable file, and import it back. ## Suggested approach **Format.** A GLib keyfile is the natural choice: `dconf dump` already produces one, `glib::KeyFile` reads and writes it, and it is diffable. Something like: ```ini [folders/9f1374fd-…] name='Work' colour='cyan' sessions=['a1b2…', 'c3d4…'] [sessions/a1b2…] name='API server' type='ssh' ssh-host='example.com' ``` Keeping it `dconf dump`-compatible is worth it — `dconf load /me/dusansimic/terminalko/ < file` then works as a fallback path, and users can inspect an export with tools they already have. **Where.** Add to `terminalko-config` (so `terminalkoctl` could use it later), e.g. `Store::export_to_keyfile() -> glib::KeyFile` and `Store::import_from_keyfile(&KeyFile, ImportMode)`. **Import needs a decision, not a default.** Offer *Replace* (clear the tree first) and *Merge* (keep what is there, giving imported folders and sessions **fresh UUIDs** so an import cannot collide with or overwrite existing work). The dialog must say which is which. **Validation.** Imported data comes from a file a user may have edited: - ignore keys that are not in the schema rather than failing; - an unknown `type`, `restart`, `container-runtime` or `escalation` value must fall back the way the model already does; - after importing, run `Store::tidy()` so a truncated file cannot leave dangling references — it adopts orphans and drops references to sessions that do not exist, and reports what it repaired. **UI.** Two entries in the primary menu (`ui/window.blp`) and two window actions, using `gtk::FileDialog`. Report the outcome as a toast or a message including the counts, and what `tidy()` had to repair. ## Acceptance criteria - Export produces a file that re-imports to an identical tree (same names, colours, types, order, folder membership) on a fresh configuration. - Import in *Merge* mode never modifies or deletes an existing session, and assigns new UUIDs to what it adds. - Import in *Replace* mode leaves exactly what was in the file. - A truncated or hand-mangled file imports what it can and reports the rest; it never leaves the tree in a state that `tidy()` still wants to repair. - Round-trip tests in `terminalko-config` running headless with `GSETTINGS_BACKEND=memory` — see the existing `with_store` helper in `session.rs` tests, which takes the process-wide lock and starts from an empty tree. - `./build-aux/ci.sh` passes; `./build-aux/smoke.sh` still passes. - `docs/spec/session-model.md` updated to describe the format and the two import modes. ## Notes - Do **not** make the agent or `terminalkoctl` write configuration: the window is the only writer, and that rule is what keeps the model consistent. - The project is BSD-2-Clause; see `CONTRIBUTING.md` before looking at any GPL-licensed terminal for reference.
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
dusan/terminalko#2
No description provided.