aboutsummaryrefslogtreecommitdiffstats
path: root/desktop/modules/git/gitcfg
blob: a5641f76e5b39227206d848dfd29f756d7a4ee67 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#!/bin/bash
#
# Copyright (C) 2026 Danilo M. <danix@danix.xyz>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# The global git config, for the drawer's git page.
#
#   gitcfg list                    git config --global -z --list, or error=<why>
#   gitcfg set <key> <old> <new>   replace the one value equal to <old>
#   gitcfg add <key> <value>       add a value
#   gitcfg unset <key> <value>     remove the one value equal to <value>
#
# Every write goes through git config, so the file keeps its comments, layout
# and quoting. --fixed-value makes a value a literal rather than a regex, so a
# write touches one value of a multi-valued key, and the `--` before the key
# keeps a leading dash an argument rather than an option.
#
# A write prints nothing on success. On failure it prints the reason on
# stdout, for the page, and exits 1.

set -u

usage() {
    printf 'usage: %s list | set <key> <old> <new> | add <key> <value> | unset <key> <value>\n' \
           "${0##*/}" >&2
    exit 2
}

g() {
    local err
    err="$(git config --global "$@" 2>&1)" || { printf '%s\n' "${err:-git config failed}"; exit 1; }
}

# Exactly one value equal to <value>, or refuse. --replace-all with no match
# appends <new> and succeeds, and --unset of a missing value fails silently:
# the file may have changed in the editor since the page read it. With two
# equal values --replace-all merges both rows into one and --unset fails, so a
# duplicate is left to the editor.
has() {
    local n
    n="$(git config --global -z --fixed-value --get-all -- "$1" "$2" | tr -cd '\0' | wc -c)"
    case "$n" in
        1) ;;
        0) printf '%s no longer holds that value\n' "$1"; exit 1 ;;
        *) printf '%s holds that value twice or more; use the editor\n' "$1"; exit 1 ;;
    esac
}

case "${1:-}" in
    # A file git cannot parse prints nothing on stdout, which would read as
    # an empty config, so its error comes out as one error= line instead.
    list)  [[ $# -eq 1 ]] || usage
           err="$(git config --global --list 2>&1 >/dev/null)" \
               || { printf 'error=%s\n' "${err:-git config failed}"; exit 1; }
           exec git config --global -z --list ;;
    set)   [[ $# -eq 4 ]] || usage; has "$2" "$3"; g --fixed-value --replace-all -- "$2" "$4" "$3" ;;
    add)   [[ $# -eq 3 ]] || usage; g --add -- "$2" "$3" ;;
    unset) [[ $# -eq 3 ]] || usage; has "$2" "$3"; g --fixed-value --unset -- "$2" "$3" ;;
    *)     usage ;;
esac