summaryrefslogtreecommitdiff
path: root/src/lib/config.source.sh
blob: b08aec9ed0248e7bd0942ba3739133a32a685948 (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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
existing_parent_dir() {
    local -r path="$1"; shift
    local existing_parent

    existing_parent=$(dirname "$path")

    while [ ! -e "$existing_parent" ]; do
        existing_parent=$(dirname "$existing_parent")
    done

    printf '%s\n' "$existing_parent"
}

# The generation "working" directory: the parent of DIST_DIR. Several DIST_DIR
# derived paths hang off this single parent -- the staging/backup sibling dirs
# (config.staging, action) and the volatile EXIF cache (metadata-cache) all live
# beside the final dist. Centralised here (task pr0), next to existing_parent_dir
# (the other DIST_DIR-parent resolver), so the plain `dirname "$DIST_DIR"` is
# computed in exactly one place instead of being recomputed at each call site.
# Plain dirname (NOT existing_parent_dir): callers that previously inlined
# `dirname "$DIST_DIR"` get a byte-identical result, including any trailing-slash
# or relative-vs-absolute behaviour dirname already produced. printf (no echo) so
# it stays safe under `set -euo pipefail`.
working_dir() {
    printf '%s\n' "$(dirname "$DIST_DIR")"
}

resolve_config_file() {
    local -r config_file="${1:-}"

    if [ -n "$config_file" ]; then
        printf '%s\n' "$config_file"
    else
        printf '%s\n' ./shuriken.conf
    fi
}

missing_config() {
    local -r config_file="$1"; shift

    printf 'Error: Can not find config file %s\n' "$config_file" >&2
    printf 'Run shuriken --init to create ./shuriken.conf.\n' >&2
    exit 1
}

# Apply the documented defaults for every config field that has one. Driven
# entirely by CONFIG_SPECS (task mr0): each scalar entry with has_default=yes
# gets VAR="${VAR:-$default}" applied, so a field's default value lives in
# exactly one place (the registry) instead of being restated here. This is what
# eliminates the default-drift class of bug (TARBALL_INCLUDE once read 'no' here
# while the registry/default-conf said 'yes', fixed in 7r0): the default and the
# documented value can no longer disagree because they are the same datum.
#
# Notes:
#   - Empty defaults are intentional and applied verbatim (e.g. FAVICON='' means
#     "use the bundled default favicon"; HEIGHT/RANDOM_SEED/ORIGINAL_BASEPATH
#     default to the empty string).
#   - has_default=no scalars (TITLE, THUMBHEIGHT, MAXPREVIEWS, ...) are required
#     and deliberately get no default; validate_common_config rejects them when
#     unset.
#   - The two array fields (TAR_OPTS, SYNC_DESTINATIONS) cannot use the scalar
#     "${VAR:-...}" form, so they keep their `declare -p` guards below. They are
#     marked print_kind=array / has_default=no in the registry so this loop
#     skips them.
apply_config_defaults() {
    local spec
    local -a fields=()
    local name default has_default

    for spec in "${CONFIG_SPECS[@]}"; do
        config_spec_split "$spec" fields
        name="${fields[0]}"
        default="${fields[1]}"
        has_default="${fields[2]}"

        if [ "$has_default" = yes ]; then
            printf -v "$name" '%s' "${!name:-$default}"
        fi
    done

    if ! declare -p TAR_OPTS >/dev/null 2>&1; then
        TAR_OPTS=(-c)
    fi
    if ! declare -p SYNC_DESTINATIONS >/dev/null 2>&1; then
        SYNC_DESTINATIONS=()
    fi
}