| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154 | #!/bin/bash
# MKit - simple install helper
# See LICENSE file for copyright and license details.
__ini_cat() {
    #
    # A no-op for text stream
    #
    local line      # each line
    while read -r line; do
        printf -- "%s\n" "$line"
    done
}
__ini_expand() {
    #
    # Expand reference value (prefix only)
    #
    local line      # each input line
    local suffix    # tail of the line
    local ref       # reference
    local value     # value if reference
    while read -r line; do                  # [foo:bar]/path
        suffix="${line#\[*\]}"              # /path
        ref="${line%$suffix}"               # [foo:bar]
        ref="${ref%\]}"                     # [foo:bar
        ref="${ref#\[}"                     # foo:bar
        value="$(ini 1value "$ref")"        # foo_bar_value
        printf -- "%s\n" "$value$suffix"    # foo_bar_value/path
    done
}
__ini_grepkey() {
    #
    # Read key from a section
    #
    local wnt=$1    # wanted key
    grep '.' \
      | grep -v '\s*#' \
      | sed -e 's/ *= */=/; s/ +$//; s/^//;' \
      | grep -e "^$wnt=" \
      | cut -d= -f2- \
      | __ini_maybe_expand
}
__ini_greppath() {
    #
    # Read key from the right section
    #
    # E.g. `files:share:my/lib.sh` should read
    #
    #     [files:share]
    #         my/lib.sh   = proj/my/lib.sh
    #
    local wnt=$1                    # wanted path
    local wntkey=${wnt##*:}         # ^^ key part
    local wntsec=${wnt%:$wntkey}    # ^^ section part
    local override                  # ENV override (only ENV section)
    if test "$wntsec" = 'ENV'; then
        override=${!wntkey}
        test -n "$override" \
         && echo "$override" \
         && return
    fi
    __ini_grepsec "$wntsec" | __ini_grepkey "$wntkey"
}
__ini_grepsec() {
    #
    # Read one INI section
    #
    local wnt=$1        # wanted section name
    local ok=false      # are we in the section?
    local line          # each input line
    grep '.' \
      | grep -v '\s*#' \
      | while read -r line; do
            case "$line" in
                \[$wnt\]) ok=true;  continue ;;
                \[*\])    ok=false; continue ;;
            esac
            $ok || continue
            printf -- "%s\n" "$line"
        done \
      | sed -e 's/ *= */=/; s/ +$//; s/^//;'
}
__ini_lskeys() {
    #
    # List keys from a section
    #
    local sct=$1    # section of interest
    __ini_grepsec "$sct" | cut -d= -f1 | awk '!x[$0]++'
}
__ini_lssect() {
    #
    # List all section names
    #
    local arg=$1    # unused argument
    grep -x '\[.*\]' | sed 's/^.//; s/.$//'
}
__ini_maybe_expand() {
    #
    # Decide whether or not to expand
    #
    if test "$MKIT_INI_EXPAND" -gt 0; then
        MKIT_INI_EXPAND=$(( --MKIT_INI_EXPAND )) __ini_expand
    else
        __ini_cat
    fi
}
ini() {
    #
    # do ini operation
    #
    local op=$1             # operator
    local arg=$2            # argument
    local fn                # internal function implementing $op
    local limit=__ini_cat    # limiting internal function
    case $op in
        lskeys) fn=__ini_lskeys   ;;
        lssect) fn=__ini_lssect   ;;
        sec)    fn=__ini_grepsec  ;;
        values) fn=__ini_greppath ;;
        1value) fn=__ini_greppath; limit="tail -1" ;;
        *)      die "incorrect use of \`ini()\`"
    esac
    <"$MKIT_INI" $fn "$arg" | $limit
}
update_version() {
    #
    # Change project:version in mkit.ini at path $2 to value $1
    #
    local version=$1    # new version
    local inifile=$2    # mkit.ini path
    local tmp           # mkit.ini cache
    tmp=$(mktemp -t mkit.update_version.XXXXXXXX)
    <"$inifile" perl -e '
        my $hit = 0;
        my $done = 0;
        foreach (<STDIN>) {
            if      ($done) { print; next; }
            elsif   (m/\[project\]/) { $hit++; print; next; }
            elsif   (m/\[/) { $hit = 0; print; next; }
            elsif   ($hit) { s/\bversion\b( *)=( *).*/version$1=$2$ARGV[0]/ and $done++; print; }
            else { print; next; }
        }
    ' "$version" >"$tmp" || die "failed to update version in mkit.ini"
    mv "$tmp" "$inifile"
}
 |