#!/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 while read -r line; do # [foo:bar]/path __ini_expandln "$line" done } __ini_expandln() { # # Fully expand references in line $1 # local line_orig=$1 # original line local line_todo=$line_orig # current state local line_done # next state local Depth=0 # current depth local MaxDepth=10 # maximum depth while true; do ((Depth++)) debug_var line_todo test "$Depth" -le "$MaxDepth" || { warn "expansion error: reached maximum depth: $Depth > $MaxDepth" warn " original line: $line_orig" warn " expanded line: $line_todo" return 3 } line_done=$(__ini_expandln_once "$line_todo") debug_var line_done test "$line_done" == "$line_todo" && break line_todo=$line_done done echo "$line_done" } __ini_expandln_once() { # # Run through line $1 once and replace all references # local line=$1 # line to expand local ref # full reference (incl. brackets) local ipath # just ini path from ^^ (stripped brackets) local value # value of reference local refs=() # all references found in line mapfile -t refs <<<"$(grep -Eo '[[][^]]+[]]' <<< "$line_todo")" debug_var refs for ref in "${refs[@]}"; do test -n "$ref" || continue ipath=${ref#[}; ipath=${ipath%]} value=$(ini 1value "$ipath") debug_var line ref ipath value line=$(sed "s|\\[$ipath\\]|$value|" <<<"$line") done echo "$line" } __ini_grepcmt() { # # Remove comments from INI file on stdin # grep -v '^[[:space:]]*#' } __ini_grepkey() { # # Read key from a section # local wnt=$1 # wanted key grep '.' \ | 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 '.' \ | 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 # 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_body() { # # Produce mkit.ini body including INCLUDE # # Note: recursive includes are not supported. # local inc # file to include local incre='\[INCLUDE:.*\]' # include directive regex local iline # include directive line if iline=$(grep -m1 -xe "$incre" "$MKIT_INI"); then inc=${iline#*:}; inc=${inc%]} grep -vxe "$incre" "$inc" grep -vxe "$incre" "$MKIT_INI" else cat "$MKIT_INI" fi | __ini_grepcmt } 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 __ini_body | $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 () { 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" }