project 31 KB

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