123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. #!/bin/bash
  2. # MKit - simple install helper
  3. # See LICENSE file for copyright and license details.
  4. __ini_cat() {
  5. #
  6. # A no-op for text stream
  7. #
  8. local line # each line
  9. while read -r line; do
  10. printf -- "%s\n" "$line"
  11. done
  12. }
  13. __ini_expand() {
  14. #
  15. # Expand reference value (prefix only)
  16. #
  17. local line # each input line
  18. local suffix # tail of the line
  19. local ref # reference
  20. local value # value if reference
  21. while read -r line; do # [foo:bar]/path
  22. suffix="${line#\[*\]}" # /path
  23. ref="${line%$suffix}" # [foo:bar]
  24. ref="${ref%\]}" # [foo:bar
  25. ref="${ref#\[}" # foo:bar
  26. value="$(ini 1value "$ref")" # foo_bar_value
  27. printf -- "%s\n" "$value$suffix" # foo_bar_value/path
  28. done
  29. }
  30. __ini_grepcmt() {
  31. #
  32. # Remove comments from INI file on stdin
  33. #
  34. grep -v '^[[:space:]]*#'
  35. }
  36. __ini_grepkey() {
  37. #
  38. # Read key from a section
  39. #
  40. local wnt=$1 # wanted key
  41. grep '.' \
  42. | sed -e 's/ *= */=/; s/ +$//; s/^//;' \
  43. | grep -e "^$wnt=" \
  44. | cut -d= -f2- \
  45. | __ini_maybe_expand
  46. }
  47. __ini_greppath() {
  48. #
  49. # Read key from the right section
  50. #
  51. # E.g. `files:share:my/lib.sh` should read
  52. #
  53. # [files:share]
  54. # my/lib.sh = proj/my/lib.sh
  55. #
  56. local wnt=$1 # wanted path
  57. local wntkey=${wnt##*:} # ^^ key part
  58. local wntsec=${wnt%:$wntkey} # ^^ section part
  59. local override # ENV override (only ENV section)
  60. if test "$wntsec" = 'ENV'; then
  61. override=${!wntkey}
  62. test -n "$override" \
  63. && echo "$override" \
  64. && return
  65. fi
  66. __ini_grepsec "$wntsec" | __ini_grepkey "$wntkey"
  67. }
  68. __ini_grepsec() {
  69. #
  70. # Read one INI section
  71. #
  72. local wnt=$1 # wanted section name
  73. local ok=false # are we in the section?
  74. local line # each input line
  75. grep '.' \
  76. | grep -v '\s*#' \
  77. | while read -r line; do
  78. case "$line" in
  79. \[$wnt\]) ok=true; continue ;;
  80. \[*\]) ok=false; continue ;;
  81. esac
  82. $ok || continue
  83. printf -- "%s\n" "$line"
  84. done \
  85. | sed -e 's/ *= */=/; s/ +$//; s/^//;'
  86. }
  87. __ini_lskeys() {
  88. #
  89. # List keys from a section
  90. #
  91. local sct=$1 # section of interest
  92. __ini_grepsec "$sct" | cut -d= -f1 | awk '!x[$0]++'
  93. }
  94. __ini_lssect() {
  95. #
  96. # List all section names
  97. #
  98. local arg=$1 # unused argument
  99. grep -x '\[.*\]' | sed 's/^.//; s/.$//'
  100. }
  101. __ini_maybe_expand() {
  102. #
  103. # Decide whether or not to expand
  104. #
  105. if test "$MKIT_INI_EXPAND" -gt 0; then
  106. MKIT_INI_EXPAND=$(( --MKIT_INI_EXPAND )) __ini_expand
  107. else
  108. __ini_cat
  109. fi
  110. }
  111. __ini_body() {
  112. #
  113. # Produce mkit.ini body including INCLUDE
  114. #
  115. # Note: recursive includes are not supported.
  116. #
  117. local inc # file to include
  118. local incre='\[INCLUDE:.*\]' # include directive regex
  119. local iline # include directive line
  120. if iline=$(grep -m1 -x "$incre" "$MKIT_INI"); then
  121. inc=${iline#*:}; inc=${inc%]}
  122. grep -vx "$incre" "$inc"
  123. grep -vx "$incre" "$MKIT_INI"
  124. else
  125. cat "$MKIT_INI"
  126. fi | __ini_grepcmt
  127. }
  128. ini() {
  129. #
  130. # do ini operation
  131. #
  132. local op=$1 # operator
  133. local arg=$2 # argument
  134. local fn # internal function implementing $op
  135. local limit=__ini_cat # limiting internal function
  136. case $op in
  137. lskeys) fn=__ini_lskeys ;;
  138. lssect) fn=__ini_lssect ;;
  139. sec) fn=__ini_grepsec ;;
  140. values) fn=__ini_greppath ;;
  141. 1value) fn=__ini_greppath; limit="tail -1" ;;
  142. *) die "incorrect use of \`ini()\`"
  143. esac
  144. __ini_body | $fn "$arg" | $limit
  145. }
  146. update_version() {
  147. #
  148. # Change project:version in mkit.ini at path $2 to value $1
  149. #
  150. local version=$1 # new version
  151. local inifile=$2 # mkit.ini path
  152. local tmp # mkit.ini cache
  153. tmp=$(mktemp -t mkit.update_version.XXXXXXXX)
  154. <"$inifile" perl -e '
  155. my $hit = 0;
  156. my $done = 0;
  157. foreach (<STDIN>) {
  158. if ($done) { print; next; }
  159. elsif (m/\[project\]/) { $hit++; print; next; }
  160. elsif (m/\[/) { $hit = 0; print; next; }
  161. elsif ($hit) { s/\bversion\b( *)=( *).*/version$1=$2$ARGV[0]/ and $done++; print; }
  162. else { print; next; }
  163. }
  164. ' "$version" >"$tmp" || die "failed to update version in mkit.ini"
  165. mv "$tmp" "$inifile"
  166. }