# 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 `: `git config --global --fixed-value --replace-all `. Only the value equal to `` changes, even on a multi-valued key. - `add `: `git config --global --add `. - `unset `: `git config --global --fixed-value --unset `. Removes only that value. - A write prints nothing on success; on failure, git's message on stdout (for the page) and exit 1. `set` and `unset` first check the old value is still there: `--replace-all` with no match appends and exits 0. - `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.