aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--docs/superpowers/specs/2026-10-16-git-config-design.md83
1 files changed, 83 insertions, 0 deletions
diff --git a/docs/superpowers/specs/2026-10-16-git-config-design.md b/docs/superpowers/specs/2026-10-16-git-config-design.md
new file mode 100644
index 0000000..e9975fc
--- /dev/null
+++ b/docs/superpowers/specs/2026-10-16-git-config-design.md
@@ -0,0 +1,83 @@
+# Global git config in the drawer
+
+## Goal
+
+Review and edit the user's global git configuration from the drawer: every
+key, not only the three the user page derives. Per-repository, system and
+`[include]`d configs are out of scope.
+
+## Measured
+
+- The global config is `~/.gitconfig`: 59 keys over 20 sections, one of
+ them (`versionsort.prereleasesuffix`) set six times. `~/.config/git/`
+ holds no `config`, so there is one global file.
+- git 2.55: `--fixed-value` (2.30+) makes a value argument a literal rather
+ than a regex, so a write can target one value of a multi-valued key.
+- `git config --global -z --list` separates entries with NUL and key from
+ value with the first newline, so values holding `=` or newlines survive.
+- The editor is `/usr/bin/sublime_text`; there is no `subl` on PATH.
+
+## Approach
+
+All reads and writes go through `git config`. git keeps the file's comments,
+layout and quoting; the shell never parses or writes `~/.gitconfig` itself.
+Rewriting the file from QML was rejected: it loses comments and has to
+reimplement git's quoting.
+
+## Module: `desktop/modules/git/`
+
+- `GitModule.qml`: name `git`, label `Git config`, `tiled: false`, a page,
+ and `up: "user"` (see Drawer below).
+- `gitcfg`: bash helper, the only thing that touches git. Every write puts
+ `--` before the key, so a key or value starting with `-` is an argument,
+ not an option (checked against git 2.55 with `--add`, `--replace-all` and
+ `--unset`).
+ - `list`: `git config --global -z --list`, printed as is.
+ - `set <key> <old> <new>`: `git config --global --fixed-value
+ --replace-all <key> <new> <old>`. Only the value equal to `<old>`
+ changes, even on a multi-valued key.
+ - `add <key> <value>`: `git config --global --add <key> <value>`.
+ - `unset <key> <value>`: `git config --global --fixed-value --unset <key>
+ <value>`. Removes only that value.
+ - git's stderr passes through and its exit status is the helper's.
+- `Git.js` (`.pragma library`): `parse(text)` turns the `-z` output into
+ `[{section, key, value}]` in file order, `section` being everything before
+ the last dot (`color.branch.remote` is section `color.branch`). Tested by
+ `test_git.js` under node, as `User.js` is.
+- `GitPage.qml`:
+ - Top: an "Edit in editor" button running `sublime_text ~/.gitconfig`,
+ detached, so the drawer can close while it stays open.
+ - The keys grouped under their section, one row per value: the key name,
+ then the value as an inline text field. Enter saves through `set`,
+ Escape restores the old value; Escape on an unfocused page still steps
+ back as on every page.
+ - A remove button per row, through `unset`. No confirmation: a removed
+ value is re-added from the Add row.
+ - An Add row at the bottom: `section.key` and value, through `add`.
+ - After every write, and when the page opens, the list is read again from
+ git. A failed write shows git's stderr under the row it came from and
+ the list is reloaded, so the field shows what git really holds.
+
+## User page link
+
+The user page's Git section gains a "More git settings" button that opens
+the git page.
+
+## Drawer
+
+- `Page.qml` gains a `go(name)` signal; the drawer connects it to
+ `show(name)`, so a page can open another module's page.
+- `Module.qml` gains `property string up: ""`: the page `back()` returns to.
+ Empty means the grid, today's behaviour. `back()` sets `page` to
+ `current.up`, and the page's back arrow calls `back()` rather than
+ clearing `page` itself, so the arrow, Escape and the mouse back button
+ agree.
+
+## Checks
+
+- `test-gitcfg.sh` runs `gitcfg` against a throwaway `GIT_CONFIG_GLOBAL` in
+ a temp directory: `list` of a multi-valued key, `set` of one value of
+ three, `unset` of one value of three, `add`, a value containing `=`, and a
+ value starting with `-`.
+- `node desktop/modules/git/test_git.js` for `parse`.
+- The page is checked by the user, by hand.