Poor man's XPath library https://pagure.io/shellfu-bash-pxpath

build.sh 7.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. #!/bin/bash
  2. # MKit - simple install helper
  3. # See LICENSE file for copyright and license details.
  4. mkit_import ini
  5. mkit_import facts
  6. __build1() {
  7. #
  8. # Process one skeleton $1 of type $3 (or guessed) to path $2
  9. #
  10. local srcpath=$1 # skeleton path
  11. local dstpath=$2 # destination meaty animal path
  12. local ftype=$3 # file/builder type
  13. test -n "$dstpath" || dstpath=${srcpath%.skel}
  14. test -n "$ftype" || ftype=$(__guess_ftype "$dstpath")
  15. debug_var srcpath dstpath ftype
  16. <"$srcpath" __build1_ftype "$ftype" >"$dstpath"
  17. __rec_built "$dstpath"
  18. }
  19. __build1_ftype() {
  20. #
  21. # Build a file of type $1; fom stdin to stdout
  22. #
  23. local ftype=$1 # file/builder type
  24. case $ftype in
  25. MKIT_COMMON) __expand_tokens "tokens" ;;
  26. rpmstuff) __expand_tokens "tokens" "rpmstuff:tokens" ;;
  27. debstuff) __expand_tokens "tokens" "debstuff:tokens" ;;
  28. *) die "unknown file type: $ftype" ;;
  29. esac
  30. }
  31. __expand_tokens() {
  32. #
  33. # Read stdin, expanding tokens from sections $@
  34. #
  35. local script # sed script cache
  36. local section # each section to expand tokens from
  37. local varname # each token name
  38. local varvalue # each token value
  39. script=$(mktemp --tmpdir mkit-tmp.XXXXXXXXXX)
  40. {
  41. for section in "$@"; do
  42. debug_var section
  43. ini lskeys "$section" \
  44. | while read -r varname; do
  45. varvalue="$(ini 1value "$section:$varname" | __qfs )"
  46. echo "s|$varname|$varvalue|g;"
  47. debug_var varname varvalue
  48. done
  49. done
  50. echo "s|__MKIT_PROJ_NAME__|$(ini 1value project:name | __qfs)|g;"
  51. echo "s|__MKIT_PROJ_CODENAME__|$(ini 1value project:codename | __qfs)|g;"
  52. echo "s|__MKIT_PROJ_LICENSE__|$(ini 1value project:license | __qfs)|g;"
  53. echo "s|__MKIT_PROJ_PKGNAME__|$(ini 1value project:pkgname | __qfs)|g;"
  54. echo "s|__MKIT_PROJ_TAGLINE__|$(ini 1value project:tagline | __qfs)|g;"
  55. echo "s|__MKIT_PROJ_MAINTAINER__|$(ini 1value project:maintainer | __qfs)|g;"
  56. echo "s|__MKIT_PROJ_VCS_BROWSER__|$(ini 1value project:vcs_browser | __qfs)|g;"
  57. echo "s|__MKIT_PROJ_GIT_LASTHASH__|$(__cached git_lasthash | __qfs)|g;"
  58. echo "s|__MKIT_PROJ_VERSION__|$(__cached semver | __qfs)|g;"
  59. echo "s|__MKIT_SELF_VERSION__|$MKIT_VERSION|g;"
  60. } >> "$script"
  61. sed -f "$script" || die "__expand_tokens failed"
  62. rm "$script"
  63. }
  64. __guess_ftype() {
  65. #
  66. # Guess file type from destination path $1
  67. #
  68. local dstpath=$1 # destination path
  69. case $dstpath in
  70. *) echo MKIT_COMMON ;;
  71. esac
  72. }
  73. __qfs() {
  74. #
  75. # Quote for our sed scipt's RHS
  76. #
  77. sed '
  78. s:\\:\\\\:g
  79. s:|:\\|:g
  80. '
  81. }
  82. __cached() {
  83. #
  84. # Cached value $1 of function $1()
  85. #
  86. # In order to support git-less builds, some values might be cached
  87. # in $MKIT_LOCAL. This function gets file $1 from that cache (cache
  88. # hit) or re-creates it (cache miss), but prints its body in either
  89. # case.
  90. #
  91. # The command to re-create file is the same as the key (ie. no
  92. # arguments).
  93. #
  94. local name=$1
  95. __local_get "$name" && return 0
  96. "$name" | __local_putb "$name"
  97. __local_get "$name"
  98. }
  99. __local_putb() {
  100. #
  101. # Make file $1 in $MKIT_LOCAL from stdin and mark as built
  102. #
  103. local fpath=$1
  104. __local_put "$fpath" && __rec_built "$MKIT_LOCAL/$fpath"
  105. }
  106. __local_put() {
  107. #
  108. # Make file $1 in $MKIT_LOCAL from stdin
  109. #
  110. local fpath="$MKIT_LOCAL/$1"
  111. { mkdir -p "${fpath%/*}" && cat >"$fpath"; } \
  112. || die "cannot write to local cache: $fpath"
  113. }
  114. __local_get() {
  115. #
  116. # Read file $1 in $MKIT_LOCAL
  117. #
  118. local fpath="$MKIT_LOCAL/$1"
  119. cat "$fpath" 2>/dev/null
  120. }
  121. __rec_built() {
  122. #
  123. # Record file $1 for deletion on `clean`
  124. #
  125. local file=$1
  126. mkdir -p "$MKIT_LOCAL"
  127. echo "$file" >> "$MKIT_LOCAL/built.lst"
  128. }
  129. _mkit_data() {
  130. #
  131. # Build sampler showing all token values
  132. #
  133. local token
  134. local section
  135. local sections
  136. sections=()
  137. ini lskeys tokens | grep -q . && sections=(tokens)
  138. sections+=( $(ini lssect | grep ':tokens$') )
  139. {
  140. echo "(builtin):"
  141. echo " x_MKIT_PROJ_NAME__ => '__MKIT_PROJ_NAME__'"
  142. echo " x_MKIT_PROJ_CODENAME__ => '__MKIT_PROJ_CODENAME__'"
  143. echo " x_MKIT_PROJ_LICENSE__ => '__MKIT_PROJ_LICENSE__'"
  144. echo " x_MKIT_PROJ_PKGNAME__ => '__MKIT_PROJ_PKGNAME__'"
  145. echo " x_MKIT_PROJ_TAGLINE__ => '__MKIT_PROJ_TAGLINE__'"
  146. echo " x_MKIT_PROJ_MAINTAINER__ => '__MKIT_PROJ_MAINTAINER__'"
  147. echo " x_MKIT_PROJ_VCS_BROWSER__ => '__MKIT_PROJ_VCS_BROWSER__'"
  148. echo " x_MKIT_PROJ_GIT_LASTHASH__ => '__MKIT_PROJ_GIT_LASTHASH__'"
  149. echo " x_MKIT_PROJ_VERSION__ => '__MKIT_PROJ_VERSION__'"
  150. echo " x_MKIT_SELF_VERSION__ => '__MKIT_SELF_VERSION__'"
  151. for section in "${sections[@]}"; do
  152. echo "$section:"
  153. for token in $(ini lskeys "$section"); do
  154. echo " x${token:1} => '$token'"
  155. done
  156. done
  157. } \
  158. | __expand_tokens "MKIT_BUILTIN" "${sections[@]}" \
  159. | sed '/^ x/ s|x|_|'
  160. }
  161. build() {
  162. #
  163. # Add meat to all skeletons
  164. #
  165. local srcpath # each source path
  166. find . -type f -name '*.skel' \
  167. | while read -r srcpath; do
  168. __build1 "$srcpath"
  169. done
  170. }
  171. clean() {
  172. #
  173. # Clean up tree after building
  174. #
  175. test -f "$MKIT_LOCAL/built.lst" && {
  176. <"$MKIT_LOCAL/built.lst" grep -v -e '\.\.' -e ^/ \
  177. | xargs -r rm -rf
  178. rm -f "$MKIT_LOCAL/built.lst"
  179. rmdir --ignore-fail-on-non-empty "$MKIT_LOCAL"
  180. }
  181. true
  182. }
  183. debstuff() {
  184. #
  185. # Build Debian stuff (eamed tarball, debian dir)
  186. #
  187. local version # package version
  188. local debian_skel # 'debian' folder skeleton
  189. local dfsrc # each source file from ^^
  190. local dftgt # each built packaging file
  191. version=$(__cached semver)
  192. # tarball - we should already have by means of 'dist'
  193. #
  194. mv "${MKIT_PROJ_PKGNAME}-$version.tar.gz" \
  195. "${MKIT_PROJ_PKGNAME}_$version.orig.tar.gz" \
  196. || die "could not rename tarball"
  197. __rec_built "${MKIT_PROJ_PKGNAME}_$version.orig.tar.gz"
  198. # read content of each mandatory file from debian_skel
  199. #
  200. debian_skel=$(ini 1value dist:debstuff)
  201. test -n "$debian_skel" || die "dist:debstuff not specified"
  202. test -d "$debian_skel" || die "debian directory template found: $debian_skel"
  203. mkdir -p debian/source
  204. find "$debian_skel" -type f \
  205. | while read -r dfsrc; do
  206. dftgt="debian/${dfsrc#$debian_skel}"
  207. mkdir -p "$(dirname "$dftgt")"
  208. __build1 "$dfsrc" "$dftgt" debstuff
  209. done
  210. __rec_built debian
  211. }
  212. dist() {
  213. #
  214. # Create distributable tarball
  215. #
  216. #FIXME: lacking Makefile skills, we do this step twice for
  217. # rpmstuff, hence -f hack for gzip
  218. #
  219. local version # tarball version
  220. local git_lasthash # last git commit hash
  221. local dirname # directory and tarball name
  222. version=$(semver)
  223. dirname=$MKIT_PROJ_PKGNAME-$version
  224. git_lasthash=$(git_lasthash)
  225. mkdir -p "$dirname"
  226. ini values "dist:tarball" | xargs -I DIST_ITEM cp -R DIST_ITEM "$dirname"
  227. mkdir -p "$dirname/.mkit"
  228. echo -n "$version" > "$dirname/.mkit/semver"
  229. echo -n "$git_lasthash" > "$dirname/.mkit/git_lasthash"
  230. tar -cf "$dirname.tar" "$dirname"
  231. gzip -f "$dirname.tar" # see above FIXME
  232. __rec_built "$dirname.tar.gz"
  233. rm -rf "$dirname"
  234. }
  235. rpmstuff() {
  236. #
  237. # Build specfile
  238. #
  239. local specname=$MKIT_PROJ_PKGNAME.spec # .spec filename
  240. local specsrc # source of specfile
  241. specsrc="$(ini 1value "dist:rpmstuff")"
  242. test -n "$specsrc" || die "dist:rpmstuff not specified"
  243. test -f "$specsrc" || die "specfile template not found: $specsrc"
  244. __build1 "$specsrc" "$specname" rpmstuff
  245. }