project 29 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543
  1. #!/usr/bin/env bash
  2. # Copyright (C) 2016 Paul Kocialkowski <contact@paulk.fr>
  3. # Copyright (C) 2018,2019 Andrew Robbins <contact@andrewrobbins.info>
  4. #
  5. # This program is free software: you can redistribute it and/or modify
  6. # it under the terms of the GNU General Public License as published by
  7. # the Free Software Foundation, either version 3 of the License, or
  8. # (at your option) any later version.
  9. #
  10. # This program is distributed in the hope that it will be useful,
  11. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. # GNU General Public License for more details.
  14. #
  15. # You should have received a copy of the GNU General Public License
  16. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. PROJECT_ACTIONS_GENERIC=(usage dependencies download extract update build install release clean)
  18. PROJECT_ACTIONS_GENERIC_IGNORE_CHECK=(usage clean)
  19. PROJECT_ACTIONS_HELPERS=(arguments dependencies)
  20. INSTALL_REGEX='\([^:]*\):\(.*\)'
  21. project_include() {
  22. local project=$1
  23. local project_path=$(project_path "$project")
  24. unset -f "${PROJECT_ACTIONS[@]}"
  25. source "$project_path/$project"
  26. project_helper_include "$project"
  27. }
  28. project_helper_include() {
  29. local project=$1
  30. local project_path=$(project_path "$project")
  31. local include="$project_path/$project-helper"
  32. if [[ -f "$include" ]]
  33. then
  34. source "$include"
  35. fi
  36. }
  37. project_check() {
  38. local project="${1##*/}"
  39. local project_path="$(project_path "$project")"
  40. if ! [[ -f "$project_path/$project" ]]; then
  41. return 1
  42. fi
  43. }
  44. project_dependencies() {
  45. local project=$1
  46. shift
  47. local -a dependencies
  48. mapfile -t dependencies < <(project_file_contents_herit "$project" "$CONFIGS" "$DEPENDENCIES" "$@")
  49. if [[ -n ${dependencies[*]} ]]; then
  50. printf '%s\n' "${dependencies[@]}"
  51. fi
  52. }
  53. project_dependencies_check() {
  54. local project=$1
  55. shift
  56. local -a dependencies
  57. mapfile -t dependencies < <(project_dependencies "$project" "$@")
  58. local -i missing=0
  59. for ((i = 0, nodeps = ${#dependencies[@]}; i < nodeps; ++i)); do
  60. local -a dependency=(${dependencies[i]})
  61. project_check "${dependency[0]}" || let ++missing
  62. done
  63. return $missing
  64. }
  65. project_dependencies_sources_check() {
  66. local project=$1
  67. shift
  68. local -a dependencies
  69. mapfile -t dependencies < <(project_dependencies "$project" "$@")
  70. local -i missing=0
  71. for ((i = 0, nodeps = ${#dependencies[@]}; i < nodeps; ++i)); do
  72. local -a dependency=(${dependencies[i]})
  73. project_sources_directory_filled_check "${dependency[0]}" ||
  74. let ++missing
  75. done
  76. return $missing
  77. }
  78. project_dependencies_action_arguments() {
  79. local action=$1
  80. local project=$2
  81. shift 2
  82. local -a dependencies
  83. mapfile -t dependencies < <(project_dependencies "$project" "$@")
  84. for ((i = 0, nodeps = ${#dependencies[@]}; i < nodeps; ++i)); do
  85. local -a dependency=(${dependencies[i]})
  86. if project_function_check "${dependency[0]}" "$action"; then
  87. project_action_arguments "$action" "${dependency[@]}"
  88. fi
  89. done
  90. }
  91. project_function_check() {
  92. local project=$1
  93. local function=$2
  94. project_include "$project"
  95. if ! function_check "$function"
  96. then
  97. return 1
  98. fi
  99. return 0
  100. }
  101. project_action() {
  102. local action="$1"
  103. shift
  104. local project="$1"
  105. shift
  106. local arguments="$*"
  107. if project_action_check "$action" "$project" "$@"; then
  108. return 0
  109. fi
  110. printf '%s\n\n' "Project $project $action (with ${arguments:-no argument})"
  111. (
  112. set +e
  113. "$action" "$@"
  114. )
  115. if [[ $? -eq 0 ]]; then
  116. printf '\n%s\n' "Project $project $action (with ${arguments:-no argument}) completed"
  117. else
  118. printf 1>&2 '\n%s\n' "Project $project $action (with ${arguments:-no argument}) failed"
  119. return 1
  120. fi
  121. }
  122. project_action_check() {
  123. local action="$1"
  124. shift
  125. local project="$1"
  126. shift
  127. (
  128. set +e
  129. if ! function_check "${action}_check"; then
  130. return 1
  131. fi
  132. for project_force in $PROJECTS_FORCE; do
  133. if [[ "$project_force" == "$project" ]]; then
  134. return 1
  135. fi
  136. done
  137. (
  138. set -e
  139. "${action}_check" "$@"
  140. )
  141. )
  142. }
  143. project_action_helper() {
  144. local helper="$1"
  145. shift
  146. local project="$1"
  147. shift
  148. if ! function_check "$helper"; then
  149. return 0
  150. fi
  151. "$helper" "$@"
  152. }
  153. project_action_arguments() {
  154. local action="$1"
  155. shift
  156. local project="$1"
  157. shift
  158. project_include "$project"
  159. project_action_arguments_verify_recursive "$action" "$project" "$@"
  160. project_action_arguments_recursive "$action" "$project" "$@"
  161. }
  162. project_action_arguments_verify_recursive() {
  163. local action="$1"
  164. shift
  165. local project="$1"
  166. shift
  167. local action_helper_arguments
  168. # Store final argument.
  169. local argument="${*:$#}"
  170. local test
  171. if [[ "$#" -gt 1 ]]; then
  172. # Set previous arguments.
  173. set "${@:1:$#-1}"
  174. elif [[ "$#" -eq 1 ]]; then
  175. shift
  176. else
  177. return 0
  178. fi
  179. action_helper_arguments="$(project_action_helper 'arguments' "$project" "$@")"
  180. if [[ -n "$action_helper_arguments" ]]; then
  181. test="$(printf '%s\n' "$action_helper_arguments" | grep -e "^$argument\$" || true)"
  182. if [[ -z "$test" ]]; then
  183. printf 1>&2 '%s\n' "Invalid argument $argument for project $project action $action"
  184. return 1
  185. fi
  186. fi
  187. project_action_arguments_verify_recursive "$action" "$project" "$@"
  188. }
  189. project_action_arguments_recursive() {
  190. local action="$1"
  191. shift
  192. local project="$1"
  193. shift
  194. local action_helper_arguments
  195. local argument
  196. action_helper_arguments="$(project_action_helper 'arguments' "$project" "$@" || true)"
  197. if [[ -z "$action_helper_arguments" ]]; then
  198. project_action "$action" "$project" "$@"
  199. else
  200. # This is to allow space characters in arguments.
  201. local ifs_save="$IFS"
  202. local IFS=$'\n'
  203. for argument in $(printf '%s\n' "$action_helper_arguments")
  204. do
  205. IFS="$ifs_save"
  206. # Only a single argument at a time is returned by the helper.
  207. project_action_arguments_recursive "$action" "$project" "$@" "$argument"
  208. done
  209. fi
  210. }
  211. project_action_projects() {
  212. local action="$1"
  213. shift
  214. local project="$1"
  215. shift
  216. local project_path="$(project_path "$project")"
  217. local project_projects_path="$project_path/$CONFIGS/$PROJECTS"
  218. local project_projects_action_path="$project_path/$CONFIGS/$PROJECTS-$action"
  219. local arguments
  220. local path
  221. if [[ -f "$project_projects_action_path" ]]; then
  222. path="$project_projects_action_path"
  223. else
  224. path="$project_projects_path"
  225. fi
  226. # Multiple arguments can be read from the file.
  227. while read -r arguments; do
  228. eval "project_action_arguments $action $arguments"
  229. done < "$path"
  230. }
  231. project_path() {
  232. local project=$1
  233. local project_path="$root/$PROJECTS/$project"
  234. printf '%s\n' "$project_path"
  235. }
  236. project_sources_path() {
  237. local project=$1
  238. shift
  239. local repository=$1
  240. shift
  241. local sources_path
  242. local argument
  243. local path
  244. # Check downloaded and extracted sources first, using "$project."
  245. path="$root/$SOURCES/$project"
  246. for argument in "" "$@"
  247. do
  248. if [[ -n "$argument" ]]
  249. then
  250. path="$path-$argument"
  251. fi
  252. if ! directory_filled_check "$path"
  253. then
  254. continue
  255. fi
  256. sources_path=$path
  257. done
  258. if [[ -n "$sources_path" ]]
  259. then
  260. printf '%s\n' "$sources_path"
  261. return
  262. fi
  263. # Check downloaded sources then, using "$repository."
  264. path="$root/$SOURCES/$repository"
  265. if directory_filled_check "$path"
  266. then
  267. printf '%s\n' "$path"
  268. return
  269. fi
  270. # Check project sources finally, using "$project."
  271. path="$root/$PROJECTS/$project/$SOURCES"
  272. for argument in "" "$@"
  273. do
  274. if [[ -n "$argument" ]]
  275. then
  276. path="$path/$argument"
  277. fi
  278. if ! directory_filled_check "$path"
  279. then
  280. continue
  281. fi
  282. sources_path=$path
  283. done
  284. if [[ -n "$sources_path" ]]
  285. then
  286. printf '%s\n' "$sources_path"
  287. return
  288. fi
  289. }
  290. project_sources_directory_filled_check() {
  291. local project=$1
  292. shift
  293. local sources_path=$(project_sources_path "$project" "$@")
  294. test ! -z "$sources_path"
  295. }
  296. project_sources_directory_filled_error() {
  297. local project=$1
  298. shift
  299. local arguments="$*"
  300. local sources_path=$(project_sources_path "$project" "$@")
  301. if [[ -n "$sources_path" ]]
  302. then
  303. printf 1>&2 '%s\n' "Sources directory for project $project (with ${arguments:-no argument}) already exists"
  304. return 1
  305. else
  306. return 0
  307. fi
  308. }
  309. project_sources_directory_missing_empty_error() {
  310. local project=$1
  311. shift
  312. local arguments="$*"
  313. local sources_path=$(project_sources_path "$project" "$@")
  314. if [[ -z "$sources_path" ]]
  315. then
  316. printf 1>&2 '%s\n' "Sources directory for project $project (with ${arguments:-no argument}) missing or empty"
  317. return 1
  318. else
  319. return 0
  320. fi
  321. }
  322. project_sources_archive() {
  323. local project=$1
  324. shift
  325. local sources_archive
  326. local argument
  327. local path="$root/$SOURCES/$project"
  328. for argument in "" "$@"
  329. do
  330. if [[ -n "$argument" ]]
  331. then
  332. path="$path-$argument"
  333. fi
  334. local archive="$path.$ARCHIVE"
  335. if ! [[ -f "$archive" ]]
  336. then
  337. continue
  338. fi
  339. sources_archive=$archive
  340. done
  341. if [[ -n "$sources_archive" ]]
  342. then
  343. printf '%s\n' "$sources_archive"
  344. fi
  345. }
  346. project_sources_archive_extract() {
  347. local project=$1
  348. shift
  349. local arguments="$*"
  350. local archive=$(project_sources_archive "$project" "$@")
  351. local destination=$(dirname "$archive")
  352. printf '%s\n' "Extracting source archive for $project (with ${arguments:-no argument})"
  353. file_verification_check "$archive"
  354. archive_extract "$archive" "$destination"
  355. }
  356. project_sources_archive_update() {
  357. local project=$1
  358. shift
  359. local arguments="$*"
  360. local repository=$project
  361. local sources_path=$(project_sources_path "$project" "$repository" "$@")
  362. local archive=$(project_sources_archive "$project" "$@")
  363. local destination=$(dirname "$archive")
  364. if [[ -d "$sources_path" ]]
  365. then
  366. rm -rf "$sources_path"
  367. fi
  368. printf '%s\n' "Extracting source archive for $project (with ${arguments:-no argument})"
  369. file_verification_check "$archive"
  370. archive_extract "$archive" "$destination"
  371. }
  372. project_sources_archive_missing_error() {
  373. local project=$1
  374. shift
  375. local arguments="$*"
  376. local archive=$(project_sources_archive "$project" "$@")
  377. if [[ -z "$archive" ]] || ! [[ -f "$archive" ]]
  378. then
  379. printf 1>&2 '%s\n' "Missing sources archive for $project (with ${arguments:-no argument})"
  380. return 1
  381. else
  382. return 0
  383. fi
  384. }
  385. project_sources_archive_missing_check() {
  386. local project=$1
  387. shift
  388. local archive=$(project_sources_archive "$project" "$@")
  389. if [[ -z "$archive" ]] || ! [[ -f "$archive" ]]
  390. then
  391. return 0
  392. else
  393. return 1
  394. fi
  395. }
  396. project_sources_prepare() {
  397. local project="$1"
  398. local sources_path="$2"
  399. # Not implemented yet / May end up not being needed
  400. #project_sources_prepare_blobs
  401. project_sources_prepare_patch "$project" "$sources_path" "$@"
  402. }
  403. project_sources_prepare_patch() {
  404. local project="$1"
  405. local sources_path="$2"
  406. local project_path="$(project_path "$project")"
  407. local patches_path="$project_path/$PATCHES"
  408. for patch in "$patches_path"/[!.]*.@(patch|diff); do
  409. diff_patch "$sources_path" "$patch"
  410. done
  411. }
  412. project_blobs() {
  413. local project=$1
  414. shift
  415. local blobs_path=$(project_blobs_path "$project" "$@")
  416. local blobs_ignore_path=$(project_blobs_ignore_path "$project" "$@")
  417. if [[ -n $blobs_path ]]; then
  418. if [[ -n $blobs_ignore_path ]]; then
  419. comm -23 <(sort "$blobs_path") <(sort "$blobs_ignore_path")
  420. else
  421. cat "$blobs_path"
  422. fi
  423. fi
  424. }
  425. project_blobs_path() {
  426. local project=$1
  427. shift
  428. local project_path=$(project_path "$project")
  429. local configs_path="$project_path/$CONFIGS"
  430. local argument
  431. local path
  432. for argument in "" "$@"
  433. do
  434. if [[ -n "$argument" ]]
  435. then
  436. if [[ -z "$path" ]]
  437. then
  438. path="$argument"
  439. else
  440. path="$path/$argument"
  441. fi
  442. fi
  443. local blobs_path="$configs_path/$path/$BLOBS"
  444. if [[ -f "$blobs_path" ]]
  445. then
  446. printf '%s\n' "$blobs_path"
  447. return
  448. fi
  449. done
  450. }
  451. project_blobs_ignore_path() {
  452. local project=$1
  453. shift
  454. local project_path=$(project_path "$project")
  455. local configs_path="$project_path/$CONFIGS"
  456. local argument
  457. local path
  458. for argument in "" "$@"
  459. do
  460. if [[ -n "$argument" ]]
  461. then
  462. if [[ -z "$path" ]]
  463. then
  464. path="$argument"
  465. else
  466. path="$path/$argument"
  467. fi
  468. fi
  469. blobs_ignore_path="$configs_path/$path/$BLOBS_IGNORE"
  470. if [[ -f "$blobs_ignore_path" ]]
  471. then
  472. printf '%s\n' "$blobs_ignore_path"
  473. return
  474. fi
  475. done
  476. }
  477. project_arguments_targets() {
  478. local project=$1
  479. shift
  480. local project_path=$(project_path "$project")
  481. local targets_path="$project_path/$CONFIGS"
  482. local argument
  483. for argument in "$@"
  484. do
  485. targets_path="$targets_path/$argument"
  486. done
  487. targets_path="$targets_path/$TARGETS"
  488. if [[ -f "$targets_path" ]]
  489. then
  490. cat "$targets_path"
  491. fi
  492. }
  493. project_usage_actions() {
  494. local project="$1"
  495. shift
  496. printf '\n%s\n' 'Generic actions:'
  497. (
  498. for action in "${PROJECT_ACTIONS_GENERIC[@]}"; do
  499. if function_check "$action"; then
  500. printf '%s\n' " $action"
  501. fi
  502. done
  503. )
  504. if [[ "$#" -gt 0 ]]; then
  505. printf '\n%s\n' 'Specific actions:'
  506. (
  507. for action in "$@"; do
  508. printf '%s\n' " $action"
  509. done
  510. )
  511. fi
  512. }
  513. project_usage_arguments() {
  514. local project="$1"
  515. shift
  516. printf '\n%s\n' 'Arguments:'
  517. project_usage_arguments_recursive "$project" ' ' "$@"
  518. }
  519. project_usage_arguments_recursive() {
  520. local project="$1"
  521. shift
  522. local spacing="$1"
  523. shift
  524. local action_helper_arguments
  525. local argument
  526. action_helper_arguments="$(project_action_helper 'arguments' "$project" "$@")"
  527. if [[ -n "$action_helper_arguments" ]]; then
  528. for argument in $action_helper_arguments; do
  529. printf '%s\n' "$spacing$argument"
  530. project_usage_arguments_recursive "$project" " $spacing" "$@" "$argument"
  531. done
  532. fi
  533. }
  534. project_download_git() {
  535. local project=$1
  536. shift
  537. local repository=$1
  538. shift
  539. local urls=$1
  540. shift
  541. requirements "git"
  542. if ! git_project_check "$repository"
  543. then
  544. project_sources_directory_filled_error "$project" "$repository" "$@"
  545. git_project_clone "$repository" "$urls"
  546. fi
  547. git_project_prepare "$project" "$repository" "$@"
  548. }
  549. project_download_check_git() {
  550. local project=$1
  551. shift
  552. local repository=$1
  553. shift
  554. requirements "git"
  555. git_project_check "$repository"
  556. git_project_prepare_check "$project" "$repository" "$@"
  557. }
  558. project_download_archive() {
  559. local project="$1"
  560. shift
  561. local archive_uri="$1"
  562. shift
  563. local archive_dsig_uri="$1"
  564. local archive="${archive_uri##*/}"
  565. local compress_fmt="${archive##*.tar}"
  566. local directory_prefix="$root/$SOURCES"
  567. local archive_path="$root/$SOURCES/$archive"
  568. local sources_path="$root/$SOURCES/$project"
  569. if [[ "${compress_fmt#*.}" != "${ARCHIVE#*.}" ]]; then
  570. ARCHIVE="tar$compress_fmt"
  571. fi
  572. # TODO: Split this code block into separate functions
  573. # Archive verification will be included at that point in time
  574. if ! project_sources_directory_filled_check "$project"; then
  575. download_wrapper "$directory_prefix" "$archive_uri" "$archive_dsig_uri"
  576. archive_extract "$archive_path" "$directory_prefix"
  577. mv "${archive_path%.tar*}" "$sources_path"
  578. fi
  579. # Patch the source, if necessary
  580. project_sources_prepare "$project" "$sources_path"
  581. }
  582. project_download_check_archive() {
  583. local project="$1"
  584. local sources_path="$2"
  585. # TODO: Write the following function
  586. #project_sources_archive_extract_check "$project" "$sources_path"
  587. }
  588. project_extract() {
  589. local project=$1
  590. shift
  591. local repository=$project
  592. if ! project_sources_directory_filled_check "$project" "$repository" "$@"
  593. then
  594. project_sources_archive_missing_error "$project" "$@" || return 1
  595. project_sources_archive_extract "$project" "$@"
  596. fi
  597. }
  598. project_extract_check() {
  599. local project=$1
  600. shift
  601. local repository=$project
  602. project_sources_directory_filled_check "$project" "$repository" "$@"
  603. }
  604. project_update_git() {
  605. local project=$1
  606. shift
  607. local repository=$1
  608. shift
  609. requirements "git"
  610. project_sources_directory_missing_empty_error "$project" "$repository" "$@"
  611. if git_project_check "$repository"
  612. then
  613. git_project_update "$project" "$repository" "$@"
  614. else
  615. if ! project_sources_archive_missing_check "$project" "$@"
  616. then
  617. project_sources_archive_update "$project" "$@"
  618. fi
  619. fi
  620. }
  621. project_update_check_git() {
  622. local project=$1
  623. shift
  624. local repository=$1
  625. shift
  626. requirements "git"
  627. if git_project_check "$repository"
  628. then
  629. # Git repository should always be updated (even if upstream didn't progress).
  630. # For instance, this is useful for testing new versions of patches without changing revision.
  631. return 1
  632. else
  633. project_sources_archive_missing_check "$project" "$@"
  634. fi
  635. }
  636. project_build_check() {
  637. local project=$1
  638. shift
  639. local project_path=$(project_path "$project")
  640. local build_path=$(project_build_path "$project" "$@")
  641. local source_file_path
  642. local argument
  643. local rule
  644. local path
  645. if ! [[ -d $build_path ]]
  646. then
  647. return 1
  648. fi
  649. for argument in "" "$@"
  650. do
  651. if [[ -n "$argument" ]]
  652. then
  653. if [[ -z "$path" ]]
  654. then
  655. path="$argument"
  656. else
  657. path="$path/$argument"
  658. fi
  659. fi
  660. configs_install_path="$project_path/$CONFIGS/$path/$INSTALL"
  661. if ! [[ -f "$configs_install_path" ]]
  662. then
  663. continue
  664. fi
  665. while read -r rule
  666. do
  667. source=$(printf '%s\n' "$rule" | sed "s/$INSTALL_REGEX/\\1/g")
  668. source_path="$build_path/$source"
  669. # Source may contain a wildcard.
  670. path_wildcard_expand "$source_path" | while read -r source_file_path
  671. do
  672. if ! [[ -f "$source_file_path" ]] && ! [[ -d "$source_file_path" ]]
  673. then
  674. return 1
  675. fi
  676. done
  677. done < "$configs_install_path"
  678. done
  679. }
  680. project_build_path() {
  681. local project=$1
  682. shift
  683. local build_path="$root/$BUILD/$project"
  684. local argument
  685. for argument in "$@"
  686. do
  687. build_path="$build_path-$argument"
  688. done
  689. printf '%s\n' "$build_path"
  690. }
  691. project_build_directory_missing_empty_error() {
  692. local project=$1
  693. shift
  694. local arguments="$*"
  695. local build_path=$(project_build_path "$project" "$@")
  696. if ! directory_filled_check "$build_path"
  697. then
  698. printf 1>&2 '%s\n' "Build directory for project $project (with ${arguments:-no argument}) missing or empty"
  699. return 1
  700. else
  701. return 0
  702. fi
  703. }
  704. project_install() {
  705. local project=$1
  706. shift
  707. local project_path=$(project_path "$project")
  708. local build_path=$(project_build_path "$project" "$@")
  709. local install_path=$(project_install_path "$project" "$@")
  710. local source_file_path
  711. local argument
  712. local rule
  713. local path
  714. # Install built files first.
  715. for argument in "" "$@"
  716. do
  717. if [[ -n "$argument" ]]
  718. then
  719. if [[ -z "$path" ]]
  720. then
  721. path="$argument"
  722. else
  723. path="$path/$argument"
  724. fi
  725. fi
  726. configs_install_path="$project_path/$CONFIGS/$path/$INSTALL"
  727. if ! [[ -f "$configs_install_path" ]]
  728. then
  729. continue
  730. fi
  731. project_build_directory_missing_empty_error "$project" "$@"
  732. while read -r rule
  733. do
  734. source=$(printf '%s\n' "$rule" | sed "s/$INSTALL_REGEX/\\1/g")
  735. source_path="$build_path/$source"
  736. destination=$(printf '%s\n' "$rule" | sed "s/$INSTALL_REGEX/\\2/g")
  737. destination_path="$install_path/$destination"
  738. destination_directory_path=$(dirname "$destination_path")
  739. mkdir -p "$destination_directory_path"
  740. # Source may contain a wildcard.
  741. path_wildcard_expand "$source_path" | while read -r source_file_path
  742. do
  743. cp -rT "$source_file_path" "$destination_path"
  744. done
  745. done < "$configs_install_path"
  746. done
  747. path=""
  748. # Install install files then.
  749. for argument in "" "$@"
  750. do
  751. if [[ -n "$argument" ]]
  752. then
  753. if [[ -z "$path" ]]
  754. then
  755. path="$argument"
  756. else
  757. path="$path/$argument"
  758. fi
  759. fi
  760. install_install_path="$project_path/$INSTALL/$path/$INSTALL"
  761. if ! [[ -f "$install_install_path" ]]
  762. then
  763. continue
  764. fi
  765. while read -r rule
  766. do
  767. source=$(printf '%s\n' "$rule" | sed "s/$INSTALL_REGEX/\\1/g")
  768. source_path="$project_path/$INSTALL/$path/$source"
  769. destination=$(printf '%s\n' "$rule" | sed "s/$INSTALL_REGEX/\\2/g")
  770. destination_path="$install_path/$destination"
  771. destination_directory_path=$(dirname "$destination_path")
  772. mkdir -p "$destination_directory_path"
  773. # Source may contain a wildcard.
  774. path_wildcard_expand "$source_path" | while read -r source_file_path
  775. do
  776. cp -rT "$source_file_path" "$destination_path"
  777. done
  778. done < "$install_install_path"
  779. done
  780. }
  781. project_install_check() {
  782. local project=$1
  783. shift
  784. local project_path=$(project_path "$project")
  785. local build_path=$(project_build_path "$project" "$@")
  786. local install_path=$(project_install_path "$project" "$@")
  787. local argument
  788. local rule
  789. local path
  790. if ! [[ -d $install_path ]]
  791. then
  792. return 1
  793. fi
  794. # Install built files first.
  795. for argument in "" "$@"
  796. do
  797. if [[ -n "$argument" ]]
  798. then
  799. if [[ -z "$path" ]]
  800. then
  801. path="$argument"
  802. else
  803. path="$path/$argument"
  804. fi
  805. fi
  806. configs_install_path="$project_path/$CONFIGS/$path/$INSTALL"
  807. if ! [[ -f "$configs_install_path" ]]
  808. then
  809. continue
  810. fi
  811. project_build_directory_missing_empty_error "$project" "$@"
  812. while read -r rule
  813. do
  814. destination=$(printf '%s\n' "$rule" | sed "s/$INSTALL_REGEX/\\2/g")
  815. destination_path="$install_path/$destination"
  816. if ! [[ -f "$destination_path" ]] && ! [[ -d "$destination_path" ]]
  817. then
  818. return 1
  819. fi
  820. done < "$configs_install_path"
  821. done
  822. path=""
  823. # Install install files then.
  824. for argument in "" "$@"
  825. do
  826. if [[ -n "$argument" ]]
  827. then
  828. if [[ -z "$path" ]]
  829. then
  830. path="$argument"
  831. else
  832. path="$path/$argument"
  833. fi
  834. fi
  835. install_install_path="$project_path/$INSTALL/$path/$INSTALL"
  836. if ! [[ -f "$install_install_path" ]]
  837. then
  838. continue
  839. fi
  840. while read -r rule
  841. do
  842. destination=$(printf '%s\n' "$rule" | sed "s/$INSTALL_REGEX/\\2/g")
  843. destination_path="$install_path/$destination"
  844. if ! [[ -f "$destination_path" ]] && ! [[ -d "$destination_path" ]]
  845. then
  846. return 1
  847. fi
  848. done < "$install_install_path"
  849. done
  850. }
  851. project_install_path() {
  852. local project=$1
  853. shift
  854. local install_path="$root/$INSTALL/$project"
  855. local argument
  856. for argument in "$@"
  857. do
  858. install_path="$install_path-$argument"
  859. done
  860. printf '%s\n' "$install_path"
  861. }
  862. project_install_directory_missing_empty_error() {
  863. local project=$1
  864. shift
  865. local arguments="$*"
  866. local install_path=$(project_install_path "$project" "$@")
  867. if ! directory_filled_check "$install_path"
  868. then
  869. printf 1>&2 '%s\n' "Install directory for project $project (with ${arguments:-no argument}) missing or empty"
  870. return 1
  871. else
  872. return 0
  873. fi
  874. }
  875. project_release_path() {
  876. local project=$1
  877. shift
  878. local prefix=$1
  879. local release_path="$root/$RELEASE/$prefix"
  880. # Special care for tools and systems, that depend on the host arch.
  881. if [[ "$prefix" = "$SYSTEMS" ]] || [[ "$prefix" = "$TOOLS" ]]
  882. then
  883. local machine=$(uname -m)
  884. release_path="$release_path/$machine/$project"
  885. else
  886. release_path="$release_path/$project"
  887. fi
  888. printf '%s\n' "$release_path"
  889. }
  890. project_release_archive_path() {
  891. local project=$1
  892. shift
  893. local prefix=$1
  894. shift
  895. local release_path=$(project_release_path "$project" "$prefix")
  896. local argument
  897. local path="$project"
  898. for argument in "$@"
  899. do
  900. path="$path-$argument"
  901. done
  902. local archive_path="$release_path/$path.$ARCHIVE"
  903. printf '%s\n' "$archive_path"
  904. }
  905. project_release_rootfs_path() {
  906. local project=$1
  907. shift
  908. local prefix=$1
  909. shift
  910. local release_path=$(project_release_path "$project" "$prefix")
  911. local argument
  912. local path="$project"
  913. for argument in "$@"
  914. do
  915. path="$path-$argument"
  916. done
  917. local rootfs_path="$release_path/$path.$ARCHIVE"
  918. printf '%s\n' "$rootfs_path"
  919. }
  920. project_release_sources_archive_path() {
  921. local project=$1
  922. shift
  923. local repository="$project"
  924. local sources_path="$(project_sources_path "$project" "$repository" "$@")"
  925. local archive_path="$root/$RELEASE/$SOURCES/$project/${sources_path##*/}.$ARCHIVE"
  926. printf '%s\n' "$archive_path"
  927. }
  928. project_release_sources_archive_create() {
  929. local project=$1
  930. shift
  931. local arguments="$*"
  932. local repository=$project
  933. local archive_path=$(project_release_sources_archive_path "$project" "$@")
  934. local sources_path=$(project_sources_path "$project" "$repository" "$@")
  935. printf '%s\n' "Releasing sources archive for $project (with ${arguments:-no argument})"
  936. archive_create "$archive_path" "$sources_path"
  937. file_verification_create "$archive_path"
  938. }
  939. project_release_sources_archive_exists_check() {
  940. local project=$1
  941. shift
  942. local archive_path=$(project_release_sources_archive_path "$project" "$@")
  943. if [[ -z "$archive_path" ]] || ! [[ -f "$archive_path" ]]
  944. then
  945. return 1
  946. else
  947. return 0
  948. fi
  949. }
  950. project_release_sources_git() {
  951. local project=$1
  952. shift
  953. local repository=$1
  954. shift
  955. requirements "git"
  956. project_sources_directory_missing_empty_error "$project" "$repository" "$@"
  957. if git_project_check "$repository"
  958. then
  959. if ! git_project_release_check "$project" "$repository" "$@"
  960. then
  961. git_project_release "$project" "$repository" "$@"
  962. fi
  963. else
  964. if ! project_release_sources_archive_exists_check "$project" "$@"
  965. then
  966. project_release_sources_archive_create "$project" "$@"
  967. fi
  968. fi
  969. }
  970. project_release_check_sources_git() {
  971. local project=$1
  972. shift
  973. local repository=$1
  974. shift
  975. requirements "git"
  976. if git_project_check "$repository"
  977. then
  978. git_project_release_check "$project" "$repository" "$@"
  979. else
  980. project_release_sources_archive_exists_check "$project" "$@"
  981. fi
  982. }
  983. project_release_install() {
  984. local project=$1
  985. shift
  986. local prefix=$1
  987. shift
  988. local install_path=$(project_install_path "$project" "$@")
  989. local release_path=$(project_release_path "$project" "$prefix")
  990. local directory_path
  991. local path
  992. project_install_directory_missing_empty_error "$project" "$@"
  993. local files=$(find "$install_path" -type f || true)
  994. local file
  995. printf '%s\n' "$files" | while read -r file
  996. do
  997. path="$release_path/$file"
  998. directory_path=$(dirname "$path")
  999. mkdir -p "$directory_path"
  1000. cp "$install_path/$file" "$path"
  1001. file_verification_create "$path"
  1002. done
  1003. }
  1004. project_release_install_check() {
  1005. local project=$1
  1006. shift
  1007. local prefix=$1
  1008. shift
  1009. local install_path=$(project_install_path "$project" "$@")
  1010. local release_path=$(project_release_path "$project" "$prefix")
  1011. local path
  1012. project_install_directory_missing_empty_error "$project" "$@"
  1013. local files=$(find "$install_path" -type f || true)
  1014. local file
  1015. printf '%s\n' "$files" | while read -r file
  1016. do
  1017. path="$release_path/$file"
  1018. file_exists_check "$path"
  1019. done
  1020. }
  1021. project_release_install_archive() {
  1022. local project=$1
  1023. shift
  1024. local prefix=$1
  1025. shift
  1026. project_install_directory_missing_empty_error "$project" "$@"
  1027. project_release_install_archive_create "$project" "$prefix" "$@"
  1028. }
  1029. project_release_install_archive_check() {
  1030. local project=$1
  1031. shift
  1032. project_release_install_archive_exists_check "$project" "$@"
  1033. }
  1034. project_release_install_archive_create() {
  1035. local project=$1
  1036. shift
  1037. local prefix=$1
  1038. shift
  1039. local arguments="$*"
  1040. local install_path=$(project_install_path "$project" "$@")
  1041. local archive_path=$(project_release_archive_path "$project" "$prefix" "$@")
  1042. printf '%s\n' "Releasing $prefix archive for $project (with ${arguments:-no argument})"
  1043. archive_create "$archive_path" "$install_path"
  1044. file_verification_create "$archive_path"
  1045. }
  1046. project_release_install_archive_exists_check() {
  1047. local project=$1
  1048. shift
  1049. local prefix=$1
  1050. shift
  1051. local archive_path=$(project_release_archive_path "$project" "$prefix" "$@")
  1052. file_exists_check "$archive_path"
  1053. }
  1054. project_release_install_rootfs() {
  1055. local project=$1
  1056. shift
  1057. local prefix=$1
  1058. shift
  1059. project_install_directory_missing_empty_error "$project" "$@"
  1060. if ! project_release_install_rootfs_exists_check "$project" "$prefix" "$@"
  1061. then
  1062. project_release_install_rootfs_create "$project" "$prefix" "$@"
  1063. fi
  1064. }
  1065. project_release_install_rootfs_check() {
  1066. local project=$1
  1067. shift
  1068. project_release_install_rootfs_exists_check "$project" "$@"
  1069. }
  1070. project_release_install_rootfs_create() {
  1071. local project=$1
  1072. shift
  1073. local prefix=$1
  1074. shift
  1075. local arguments="$*"
  1076. local install_path=$(project_install_path "$project" "$@")
  1077. local rootfs_path=$(project_release_rootfs_path "$project" "$prefix" "$@")
  1078. printf '%s\n' "Releasing $prefix rootfs for $project (with ${arguments:-no argument})"
  1079. rootfs_create "$rootfs_path" "$install_path"
  1080. file_verification_create "$rootfs_path"
  1081. }
  1082. project_release_install_rootfs_exists_check() {
  1083. local project=$1
  1084. shift
  1085. local prefix=$1
  1086. shift
  1087. local rootfs_path=$(project_release_rootfs_path "$project" "$prefix" "$@")
  1088. file_exists_check "$rootfs_path"
  1089. }
  1090. project_clean() {
  1091. local project=$1
  1092. shift
  1093. project_clean_build "$project" "$@"
  1094. project_clean_install "$project" "$@"
  1095. project_clean_release "$project" "$@"
  1096. }
  1097. project_clean_build() {
  1098. local project=$1
  1099. shift
  1100. local build_path=$(project_build_path "$project" "$@")
  1101. rm -rf "$build_path"
  1102. }
  1103. project_clean_install() {
  1104. local project=$1
  1105. shift
  1106. local install_path=$(project_install_path "$project" "$@")
  1107. rm -rf "$install_path"
  1108. }
  1109. project_clean_release() {
  1110. local project=$1
  1111. shift
  1112. local prefix
  1113. for prefix in "$SOURCES" "$SYSTEMS" "$IMAGES" "$TOOLS" "$DOCS"
  1114. do
  1115. local release_path=$(project_release_path "$project" "$prefix")
  1116. rm -rf "$release_path"
  1117. done
  1118. }
  1119. project_clean_rootfs() {
  1120. local project=$1
  1121. shift
  1122. project_clean_build "$project" "$@"
  1123. project_clean_rootfs_install "$project" "$@"
  1124. project_clean_release "$project" "$@"
  1125. }
  1126. project_clean_rootfs_install() {
  1127. local project=$1
  1128. shift
  1129. local install_path=$(project_install_path "$project" "$@")
  1130. execute_root rm -rf "$install_path"
  1131. }
  1132. project_file_path() {
  1133. local project=$1
  1134. shift
  1135. local directory=$1
  1136. shift
  1137. local file=$1
  1138. shift
  1139. local project_path=$(project_path "$project")
  1140. local path="$project_path/$directory"
  1141. local argument
  1142. local file_path
  1143. for argument in "" "$@"
  1144. do
  1145. if [[ -n "$argument" ]]
  1146. then
  1147. path="$path/$argument"
  1148. fi
  1149. if ! [[ -f "$path/$file" ]]
  1150. then
  1151. continue
  1152. fi
  1153. file_path="$path/$file"
  1154. break
  1155. done
  1156. if [[ -z "$file_path" ]]
  1157. then
  1158. return 1
  1159. fi
  1160. printf '%s\n' "$file_path"
  1161. }
  1162. project_file_test() {
  1163. local file_path=$(project_file_path "$@")
  1164. test -f "$file_path"
  1165. }
  1166. project_file_contents() {
  1167. local file_path=$(project_file_path "$@")
  1168. if [[ -f "$file_path" ]]
  1169. then
  1170. cat "$file_path"
  1171. fi
  1172. }
  1173. project_file_contents_herit() {
  1174. local project=$1
  1175. shift
  1176. local directory=$1
  1177. shift
  1178. local file=$1
  1179. shift
  1180. local project_path=$(project_path "$project")
  1181. local path="$project_path/$directory"
  1182. local argument
  1183. local file_path
  1184. for argument in "" "$@"
  1185. do
  1186. if [[ -n "$argument" ]]
  1187. then
  1188. path="$path/$argument"
  1189. fi
  1190. file_path="$path/$file"
  1191. if ! [[ -f "$file_path" ]]
  1192. then
  1193. continue
  1194. fi
  1195. cat "$file_path"
  1196. done
  1197. }