just a dummy repo for a dummy package

build.sh 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437
  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=MKIT_COMMON
  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_macros "build:macros" ;;
  26. rpmstuff) __expand_macros "rpmstuff:macros" ;;
  27. debstuff) __expand_macros "debstuff:macros" ;;
  28. pystuff) __expand_macros "pystuff:macros" ;;
  29. *) die "unknown file type: $ftype" ;;
  30. esac
  31. }
  32. __macrol() {
  33. #
  34. # List known macros
  35. #
  36. find "${MacroDirs[@]}" -mindepth 1 -depth -printf '%P\n' \
  37. | sed 's/[.]/:/g'
  38. }
  39. __macror() {
  40. #
  41. # Read macro $1
  42. #
  43. local key=$1
  44. find "${MacroDirs[@]}" -mindepth 1 -depth -name "$key" \
  45. | head -1 \
  46. | xargs -r cat
  47. }
  48. __macrow() {
  49. #
  50. # Write stdin as macro $1
  51. #
  52. local fqkey=$1
  53. local file="$MKIT_LOCAL/data/${fqkey//:/.}"
  54. mkdir -p "${file%/*}"
  55. cat >"$file"
  56. }
  57. __expand_line() {
  58. #
  59. # Expand macro from config in single line $1
  60. #
  61. # If macro value has multiple lines, repeat original line with
  62. # different substitution.
  63. #
  64. # E.g. if macro value is "foo\nbar" and macro name is __FOO__,
  65. # line `see: "__FOO__"` will expand to two lines: `see: "foo"`
  66. # and `see: "bar"`.
  67. #
  68. local line=$1 # line to process
  69. local mname # macro name
  70. local mvline # line of macro value
  71. local xline # expanded line
  72. xline=$line
  73. for mname in $(__macrol); do
  74. if ! test "${line//$mname}" == "$line"; then
  75. xline=$(
  76. while IFS= read -r mvline; do
  77. echo "${line//$mname/$mvline}"
  78. done <<<"$(__macror "$mname")"
  79. )
  80. fi
  81. line=$xline
  82. done
  83. echo "$xline"
  84. return 1
  85. }
  86. __expand_macros() {
  87. #
  88. # Read stdin, expanding macros from extra sections $@
  89. #
  90. local MacroDirs=() # directories to lookup macros in
  91. local mdir # every ^^
  92. local line # each line on stdin
  93. local bltndata="$MKIT_LOCAL/data/MKIT_BUILTIN"
  94. local usrdata="$MKIT_LOCAL/data/macros"
  95. test -d "$bltndata" && MacroDirs+=("$bltndata")
  96. test -d "$usrdata" && MacroDirs+=("$usrdata")
  97. for extra in "$@"; do
  98. mdir="$MKIT_LOCAL/data/${extra//:/.}"
  99. test -d "$mdir" || continue
  100. MacroDirs+=("$mdir")
  101. done
  102. while IFS= read -r line; do
  103. __expand_line "$line"
  104. done
  105. }
  106. __qfs() {
  107. #
  108. # Quote for our sed scipt's RHS
  109. #
  110. sed '
  111. s:\\:\\\\:g
  112. s:|:\\|:g
  113. '
  114. }
  115. __cached() {
  116. #
  117. # Cached value $1 of function $1()
  118. #
  119. # In order to support git-less builds, some values might be cached
  120. # in $MKIT_LOCAL. This function gets file $1 from that cache (cache
  121. # hit) or re-creates it (cache miss), but prints its body in either
  122. # case.
  123. #
  124. # The command to re-create file is the same as the key (ie. no
  125. # arguments).
  126. #
  127. local name=$1
  128. __local_get "$name" && return 0
  129. "$name" | __local_putb "$name"
  130. __local_get "$name"
  131. }
  132. __local_putb() {
  133. #
  134. # Make file $1 in $MKIT_LOCAL from stdin and mark as built
  135. #
  136. local fpath=$1
  137. __local_put "$fpath" && __rec_built "$MKIT_LOCAL/$fpath"
  138. }
  139. __local_put() {
  140. #
  141. # Make file $1 in $MKIT_LOCAL from stdin
  142. #
  143. local fpath="$MKIT_LOCAL/$1"
  144. { mkdir -p "${fpath%/*}" && cat >"$fpath"; } \
  145. || die "cannot write to local cache: $fpath"
  146. }
  147. __local_get() {
  148. #
  149. # Read file $1 in $MKIT_LOCAL
  150. #
  151. local fpath="$MKIT_LOCAL/$1"
  152. cat "$fpath" 2>/dev/null
  153. }
  154. __rec_built() {
  155. #
  156. # Record file $1 for deletion on `clean`
  157. #
  158. local file=$1
  159. mkdir -p "$MKIT_LOCAL"
  160. echo "1:$file" >> "$MKIT_LOCAL/built.lst"
  161. }
  162. __rec_builtr() {
  163. #
  164. # Record dir $1 for recursive deletion on `clean`
  165. #
  166. local path=$1
  167. mkdir -p "$MKIT_LOCAL"
  168. echo "r:$path" >> "$MKIT_LOCAL/built.lst"
  169. }
  170. _mkit_builddata() {
  171. #
  172. # Build config data
  173. #
  174. local macro
  175. local section
  176. test -d "$MKIT_LOCAL/data/build.macros" && {
  177. warn "mkit: using cached _mkit_builddata: $(date -Isec -r "$MKIT_LOCAL/data/build.macros")"
  178. warn "mkit: (hint: run 'make clean' to regenerate it)"
  179. return 0
  180. }
  181. __rec_builtr "$MKIT_LOCAL/data"
  182. for macro in $(ini lskeys "build:macros"); do
  183. ini values "build:macros:$macro" | __macrow "build:macros/$macro"
  184. done
  185. }
  186. _mkit_inidata() {
  187. #
  188. # Build INI data
  189. #
  190. test -d "$MKIT_LOCAL/data/ini" && {
  191. warn "mkit: using cached _mkit_inidata: $(date -Isec -r "$MKIT_LOCAL/data/ini")"
  192. warn "mkit: (hint: run 'make clean' to regenerate it)"
  193. return 0
  194. }
  195. __rec_builtr "$MKIT_LOCAL/data"
  196. local sect
  197. local key
  198. ini lssect \
  199. | while read -r sect; do
  200. mkdir -p "$MKIT_LOCAL/data/ini/$sect"
  201. ini lskeys "$sect" \
  202. | while read -r key; do
  203. ini values "$sect:$key" >"$MKIT_LOCAL/data/ini/$sect/$key"
  204. done
  205. done
  206. }
  207. _mkit_metadata() {
  208. #
  209. # Build meta data
  210. #
  211. test -d "$MKIT_LOCAL/data/MKIT_BUILTIN" && {
  212. warn "mkit: using cached _mkit_metadata: $(date -Isec -r "$MKIT_LOCAL/data/MKIT_BUILTIN")"
  213. warn "mkit: (hint: run 'make clean' to regenerate it)"
  214. return 0
  215. }
  216. __rec_builtr "$MKIT_LOCAL/data"
  217. echo "$MKIT_VERSION" | __macrow MKIT_BUILTIN/__MKIT_MKIT_VERSION__
  218. ini 1value project:name | __macrow MKIT_BUILTIN/__MKIT_PROJ_NAME__
  219. ini 1value project:codename | __macrow MKIT_BUILTIN/__MKIT_PROJ_CODENAME__
  220. ini 1value project:license | __macrow MKIT_BUILTIN/__MKIT_PROJ_LICENSE__
  221. ini 1value project:pkgname | __macrow MKIT_BUILTIN/__MKIT_PROJ_PKGNAME__
  222. ini 1value project:tagline | __macrow MKIT_BUILTIN/__MKIT_PROJ_TAGLINE__
  223. ini 1value project:maintainer | __macrow MKIT_BUILTIN/__MKIT_PROJ_MAINTAINER__
  224. ini 1value project:vcs_browser | __macrow MKIT_BUILTIN/__MKIT_PROJ_VCS_BROWSER__
  225. __cached git_lasthash | __macrow MKIT_BUILTIN/__MKIT_PROJ_GIT_LASTHASH__
  226. __cached git_lastsummary | __macrow MKIT_BUILTIN/__MKIT_PROJ_GIT_LASTSUMMARY__
  227. __cached semver | __macrow MKIT_BUILTIN/__MKIT_PROJ_VERSION__
  228. for section in macros pystuff:macros debstuff:macros rpmstuff:macros; do
  229. for macro in $(ini lskeys "$section"); do
  230. ini values "$section:$macro" | __macrow "$section/$macro"
  231. done
  232. done
  233. }
  234. __subdirs() {
  235. #
  236. # List direct sub-directories of $1
  237. #
  238. find "$1" -maxdepth 1 -mindepth 1 -printf '%P\n' -type d
  239. }
  240. __subfiles() {
  241. #
  242. # List direct sub-files of $1
  243. #
  244. find "$1" -maxdepth 1 -mindepth 1 -printf '%P\n' -type f
  245. }
  246. _mkit_data() {
  247. #
  248. # Build sampler showing all macro values
  249. #
  250. warn "DEPRECATION: _mkit_data is deprecated and will be removed soon!"
  251. warn "DEPRECATION: Use _mkit_show_metadata or _mkit_show_build instead."
  252. warn "DEPRECATION: (redirecting to _mkit_show_metadata)"
  253. _mkit_show_metadata
  254. }
  255. _mkit_show_metadata() {
  256. #
  257. # Show sampler of macro values
  258. #
  259. __show_msection MKIT_BUILTIN
  260. __show_msection macros
  261. __show_msection rpmstuff:macros
  262. __show_msection debstuff:macros
  263. __show_msection pystuff:macros
  264. }
  265. _mkit_show_builddata() {
  266. #
  267. # Show sampler of config values
  268. #
  269. __show_msection build:macros
  270. }
  271. __show_msection() {
  272. #
  273. # Show macros of section $1
  274. #
  275. local section=$1
  276. local mname
  277. local first=true
  278. local label=$section
  279. local secdir="$MKIT_LOCAL/data/${section//:/.}"
  280. test -d "$secdir" || return 0
  281. test "$section" == MKIT_BUILTIN && label="(builtin)"
  282. for mname in $(__subfiles "$secdir"); do
  283. $first && echo "$label:"; first=false
  284. echo " $mname => '$(<"$secdir/$mname")'"
  285. done
  286. }
  287. build() {
  288. #
  289. # Add meat to all skeletons
  290. #
  291. local srcpath # each source path
  292. find . -type f -name '*.skel' \
  293. | while read -r srcpath; do
  294. __build1 "$srcpath"
  295. done
  296. }
  297. clean() {
  298. #
  299. # Clean up tree after building
  300. #
  301. local path
  302. local line
  303. local depth
  304. test -f "$MKIT_LOCAL/built.lst" || return 0
  305. {
  306. cat "$MKIT_LOCAL/built.lst"
  307. echo "1:$MKIT_LOCAL/built.lst"
  308. echo "1:$MKIT_LOCAL"
  309. } \
  310. | grep -v -e '\.\.' -e ^/ -e '^~' \
  311. | while IFS=: read -r depth path; do
  312. test -e "$path" || continue
  313. case $depth in
  314. 1) warn "removing: $path"
  315. test -d "$path" \
  316. && rmdir -p --ignore-fail-on-non-empty "$path"
  317. test -f "$path" && rm "$path"
  318. ;;
  319. r) warn "removing recursively: $path"
  320. rm -r "$path"
  321. ;;
  322. *) warn "invalid built.lst format!"
  323. ;;
  324. esac
  325. done
  326. true
  327. }
  328. debstuff() {
  329. #
  330. # Build Debian stuff (eamed tarball, debian dir)
  331. #
  332. local version # package version
  333. local debian_skel # 'debian' folder skeleton
  334. local dfsrc # each source file from ^^
  335. local dftgt # each built packaging file
  336. version=$(__cached semver)
  337. # tarball - we should already have by means of 'dist'
  338. #
  339. mv "${MKIT_PROJ_PKGNAME}-$version.tar.gz" \
  340. "${MKIT_PROJ_PKGNAME}_$version.orig.tar.gz" \
  341. || die "could not rename tarball"
  342. __rec_built "${MKIT_PROJ_PKGNAME}_$version.orig.tar.gz"
  343. # read content of each mandatory file from debian_skel
  344. #
  345. debian_skel=$(ini 1value dist:debstuff)
  346. test -n "$debian_skel" || die "dist:debstuff not specified"
  347. test -d "$debian_skel" || die "debian directory template found: $debian_skel"
  348. mkdir -p debian/source
  349. find "$debian_skel" -type f \
  350. | while read -r dfsrc; do
  351. dftgt="debian/${dfsrc#$debian_skel}"
  352. mkdir -p "$(dirname "$dftgt")"
  353. __build1 "$dfsrc" "$dftgt" debstuff
  354. done
  355. __rec_builtr debian
  356. }
  357. dist() {
  358. #
  359. # Create distributable tarball
  360. #
  361. #FIXME: lacking Makefile skills, we do this step twice for
  362. # rpmstuff, hence -f hack for gzip
  363. #
  364. local version # tarball version
  365. local git_lasthash # last git commit hash
  366. local dirname # directory and tarball name
  367. version=$(semver)
  368. dirname=$MKIT_PROJ_PKGNAME-$version
  369. git_lasthash=$(git_lasthash)
  370. mkdir -p "$dirname"
  371. ini values "dist:tarball" | xargs -I DIST_ITEM cp -R DIST_ITEM "$dirname"
  372. mkdir -p "$dirname/.mkit"
  373. echo -n "$version" > "$dirname/.mkit/semver"
  374. echo -n "$git_lasthash" > "$dirname/.mkit/git_lasthash"
  375. cp -r "$MKIT_LOCAL/data" "$dirname/.mkit/"
  376. tar -cf "$dirname.tar" "$dirname"
  377. gzip -f "$dirname.tar" # see above FIXME
  378. __rec_built "$dirname.tar.gz"
  379. rm -rf "$dirname"
  380. }
  381. rpmstuff() {
  382. #
  383. # Build specfile
  384. #
  385. local specname=$MKIT_PROJ_PKGNAME.spec # .spec filename
  386. local specsrc # source of specfile
  387. specsrc="$(ini 1value "dist:rpmstuff")"
  388. test -n "$specsrc" || die "dist:rpmstuff not specified"
  389. test -f "$specsrc" || die "specfile template not found: $specsrc"
  390. __build1 "$specsrc" "$specname" rpmstuff
  391. }
  392. build_pystuff() {
  393. #
  394. # Build setup.py
  395. #
  396. local skel # source of specfile
  397. skel="$(ini 1value "dist:pystuff")"
  398. test -n "$skel" || die "dist:pystuff not specified"
  399. test -f "$skel" || die "setup.py template not found: $skel"
  400. __build1 "$skel" "setup.py" pystuff
  401. python setup.py sdist
  402. __rec_builtr dist
  403. __rec_built MANIFEST
  404. }