123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  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. mkdir -p "$MKIT_LOCAL"
  18. echo "$dstpath" >> "$MKIT_LOCAL/built.lst"
  19. }
  20. _build1_ftype() {
  21. #
  22. # Build a file of type $1; fom stdin to stdout
  23. #
  24. local ftype=$1 # file/builder type
  25. case $ftype in
  26. MKIT_COMMON) _expand_tokens "tokens" ;;
  27. markdown) _expand_includes | _expand_tokens "tokens" ;;
  28. rpmstuff) _expand_tokens "tokens" "rpmstuff:tokens" ;;
  29. debstuff) _expand_tokens "tokens" "debstuff:tokens" ;;
  30. *) die "unknown file type: $ftype" ;;
  31. esac
  32. }
  33. _expand_includes() {
  34. #
  35. # Expand include directives
  36. #
  37. # Expand e.g. `<!-- include4: foo.sh -->` to include code of foo.sh
  38. #
  39. perl -we '
  40. use strict;
  41. my $text;
  42. while (<>) {
  43. chomp;
  44. if (m/<!-- include4: (\S+) -->/) {
  45. open my $fh, $1 or warn "cannot find: $1";
  46. my $text = do { local($/); <$fh> };
  47. close $fh;
  48. $text =~ s/^(.)/ $1/gm;
  49. chomp $text;
  50. print "$text\n";
  51. } else {
  52. print "$_\n";
  53. }
  54. }
  55. '
  56. }
  57. _expand_tokens() {
  58. #
  59. # Read stdin, expanding tokens from sections $@
  60. #
  61. local script # sed script cache
  62. local section # each section to expand tokens from
  63. local varname # each token name
  64. local varvalue # each token value
  65. script=$(mktemp --tmpdir mkit-tmp.XXXXXXXXXX)
  66. {
  67. for section in "$@"; do
  68. debug_var section
  69. ini lskeys "$section" \
  70. | while read -r varname; do
  71. varvalue="$(ini 1value "$section:$varname" | _qfs )"
  72. echo "s|$varname|$varvalue|g;"
  73. debug_var varname varvalue
  74. done
  75. done
  76. echo "s|__MKIT_PROJ_NAME__|$(ini 1value project:name | _qfs)|g;"
  77. echo "s|__MKIT_PROJ_CODENAME__|$(ini 1value project:codename | _qfs)|g;"
  78. echo "s|__MKIT_PROJ_LICENSE__|$(ini 1value project:license | _qfs)|g;"
  79. echo "s|__MKIT_PROJ_PKGNAME__|$(ini 1value project:pkgname | _qfs)|g;"
  80. echo "s|__MKIT_PROJ_TAGLINE__|$(ini 1value project:tagline | _qfs)|g;"
  81. echo "s|__MKIT_PROJ_MAINTAINER__|$(ini 1value project:maintainer | _qfs)|g;"
  82. echo "s|__MKIT_PROJ_VCS_BROWSER__|$(ini 1value project:vcs_browser | _qfs)|g;"
  83. echo "s|__MKIT_PROJ_GIT_LASTHASH__|$(git_lasthash | _qfs)|g;"
  84. echo "s|__MKIT_PROJ_VERSION__|$(semver | _qfs)|g;"
  85. echo "s|__MKIT_SELF_VERSION__|$MKIT_VERSION|g;"
  86. } >> "$script"
  87. sed -f "$script" || die "_expand_tokens failed"
  88. rm "$script"
  89. }
  90. _guess_ftype() {
  91. #
  92. # Guess file type from destination path $1
  93. #
  94. local dstpath=$1 # destination path
  95. case $dstpath in
  96. *.md) echo markdown ;;
  97. *) echo MKIT_COMMON ;;
  98. esac
  99. }
  100. _qfs() {
  101. #
  102. # Quote for our sed scipt's RHS
  103. #
  104. sed '
  105. s:\\:\\\\:g
  106. s:|:\\|:g
  107. '
  108. }
  109. build() {
  110. #
  111. # Add meat to all skeletons
  112. #
  113. local srcpath # each source path
  114. find -type f -name '*.skel' \
  115. | while read -r srcpath; do
  116. _build1 "$srcpath"
  117. done
  118. }
  119. build_manpages() {
  120. #
  121. # Build manpages using ronn
  122. #
  123. local manfile # each manual file listed in '[files:man]'
  124. local mdfile # each source markdown file
  125. if command -v ronn >/dev/null; then
  126. ini lskeys "files:man" \
  127. | while read -r manfile; do
  128. mdfile="$manfile.md"
  129. ronn -r "$mdfile"
  130. mkdir -p "$MKIT_LOCAL"
  131. echo "$manfile" >> "$MKIT_LOCAL/built.lst"
  132. done
  133. else
  134. echo "ronn is not installed"
  135. return 1
  136. fi
  137. }
  138. clean() {
  139. #
  140. # Clean up tree after building
  141. #
  142. test -f "$MKIT_LOCAL/built.lst" && {
  143. <"$MKIT_LOCAL/built.lst" grep -v -e '\.\.' -e ^/ \
  144. | xargs -r rm -rf
  145. rm -f "$MKIT_LOCAL/built.lst"
  146. rmdir --ignore-fail-on-non-empty "$MKIT_LOCAL"
  147. }
  148. true
  149. }
  150. debstuff() {
  151. #
  152. # Build Debian stuff (eamed tarball, debian dir)
  153. #
  154. local version # package version
  155. local debian_skel # 'debian' folder skeleton
  156. local dfsrc # each source file from ^^
  157. local dftgt # each built packaging file
  158. version=$(semver)
  159. # tarball - we should already have by means of 'dist'
  160. #
  161. mv "${MKIT_PROJ_PKGNAME}-$version.tar.gz" \
  162. "${MKIT_PROJ_PKGNAME}_$version.orig.tar.gz" \
  163. || die "could not rename tarball"
  164. echo "${MKIT_PROJ_PKGNAME}_$version.orig.tar.gz" >> "$MKIT_LOCAL/built.lst"
  165. # read content of each mandatory file from debian_skel
  166. #
  167. debian_skel=$(ini 1value dist:debstuff)
  168. test -n "$debian_skel" || die "dist:debstuff not specified"
  169. test -d "$debian_skel" || die "debian directory template found: $debian_skel"
  170. mkdir -p debian/source
  171. find "$debian_skel" -type f \
  172. | while read -r dfsrc; do
  173. dftgt="debian/${dfsrc#$debian_skel}"
  174. mkdir -p "$(dirname "$dftgt")"
  175. _build1 "$dfsrc" "$dftgt" debstuff
  176. done
  177. echo debian >> "$MKIT_LOCAL/built.lst"
  178. }
  179. dist() {
  180. #
  181. # Create distributable tarball
  182. #
  183. #FIXME: lacking Makefile skills, we do this step twice fot
  184. # rpmstuff, hence -f hack for gzip
  185. #
  186. local version # tarball version
  187. local git_lasthash # last git commit hash
  188. local dirname # directory and tarball name
  189. version=$(semver)
  190. dirname=$MKIT_PROJ_PKGNAME-$version
  191. git_lasthash=$(git_lasthash)
  192. mkdir -p "$dirname"
  193. ini values "dist:tarball" | xargs -I DIST_ITEM cp -R DIST_ITEM "$dirname"
  194. update_version "$version" "$dirname/mkit.ini"
  195. mkdir -p "$dirname/.mkit"
  196. echo -n "$git_lasthash" > "$dirname/.mkit/git_lasthash"
  197. tar -cf "$dirname.tar" "$dirname"
  198. gzip -f "$dirname.tar" # see above FIXME
  199. mkdir -p "$MKIT_LOCAL"
  200. echo "$dirname.tar.gz" >> "$MKIT_LOCAL/built.lst"
  201. rm -rf "$dirname"
  202. }
  203. rpmstuff() {
  204. #
  205. # Build specfile
  206. #
  207. local specname=$MKIT_PROJ_PKGNAME.spec # .spec filename
  208. local specsrc # source of specfile
  209. specsrc="$(ini 1value "dist:rpmstuff")"
  210. test -n "$specsrc" || die "dist:rpmstuff not specified"
  211. test -f "$specsrc" || die "specfile template not found: $specsrc"
  212. _build1 "$specsrc" "$specname" rpmstuff
  213. }